You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

295 lines
9.1KB

  1. //! What we are sending to the templates when rendering them
  2. use std::collections::HashMap;
  3. use tera::{Map, Value};
  4. use content::{Page, Section};
  5. use library::Library;
  6. #[derive(Clone, Debug, PartialEq, Serialize)]
  7. pub struct TranslatedContent<'a> {
  8. lang: &'a str,
  9. permalink: &'a str,
  10. title: &'a Option<String>,
  11. }
  12. impl<'a> TranslatedContent<'a> {
  13. // copypaste eh, not worth creating an enum imo
  14. pub fn find_all_sections(section: &'a Section, library: &'a Library) -> Vec<Self> {
  15. let mut translations = vec![];
  16. for key in &section.translations {
  17. let other = library.get_section_by_key(*key);
  18. translations.push(TranslatedContent {
  19. lang: &other.lang,
  20. permalink: &other.permalink,
  21. title: &other.meta.title,
  22. });
  23. }
  24. translations
  25. }
  26. pub fn find_all_pages(page: &'a Page, library: &'a Library) -> Vec<Self> {
  27. let mut translations = vec![];
  28. for key in &page.translations {
  29. let other = library.get_page_by_key(*key);
  30. translations.push(TranslatedContent {
  31. lang: &other.lang,
  32. permalink: &other.permalink,
  33. title: &other.meta.title,
  34. });
  35. }
  36. translations
  37. }
  38. }
  39. #[derive(Clone, Debug, PartialEq, Serialize)]
  40. pub struct SerializingPage<'a> {
  41. relative_path: &'a str,
  42. content: &'a str,
  43. permalink: &'a str,
  44. slug: &'a str,
  45. ancestors: Vec<String>,
  46. title: &'a Option<String>,
  47. description: &'a Option<String>,
  48. date: &'a Option<String>,
  49. year: Option<i32>,
  50. month: Option<u32>,
  51. day: Option<u32>,
  52. taxonomies: &'a HashMap<String, Vec<String>>,
  53. extra: &'a Map<String, Value>,
  54. path: &'a str,
  55. components: &'a [String],
  56. summary: &'a Option<String>,
  57. word_count: Option<usize>,
  58. reading_time: Option<usize>,
  59. assets: &'a [String],
  60. draft: bool,
  61. lang: &'a str,
  62. lighter: Option<Box<SerializingPage<'a>>>,
  63. heavier: Option<Box<SerializingPage<'a>>>,
  64. earlier: Option<Box<SerializingPage<'a>>>,
  65. later: Option<Box<SerializingPage<'a>>>,
  66. translations: Vec<TranslatedContent<'a>>,
  67. }
  68. impl<'a> SerializingPage<'a> {
  69. /// Grabs all the data from a page, including sibling pages
  70. pub fn from_page(page: &'a Page, library: &'a Library) -> Self {
  71. let mut year = None;
  72. let mut month = None;
  73. let mut day = None;
  74. if let Some(d) = page.meta.datetime_tuple {
  75. year = Some(d.0);
  76. month = Some(d.1);
  77. day = Some(d.2);
  78. }
  79. let pages = library.pages();
  80. let lighter = page
  81. .lighter
  82. .map(|k| Box::new(Self::from_page_basic(pages.get(k).unwrap(), Some(library))));
  83. let heavier = page
  84. .heavier
  85. .map(|k| Box::new(Self::from_page_basic(pages.get(k).unwrap(), Some(library))));
  86. let earlier = page
  87. .earlier
  88. .map(|k| Box::new(Self::from_page_basic(pages.get(k).unwrap(), Some(library))));
  89. let later = page
  90. .later
  91. .map(|k| Box::new(Self::from_page_basic(pages.get(k).unwrap(), Some(library))));
  92. let ancestors = page
  93. .ancestors
  94. .iter()
  95. .map(|k| library.get_section_by_key(*k).file.relative.clone())
  96. .collect();
  97. let translations = TranslatedContent::find_all_pages(page, library);
  98. SerializingPage {
  99. relative_path: &page.file.relative,
  100. ancestors,
  101. content: &page.content,
  102. permalink: &page.permalink,
  103. slug: &page.slug,
  104. title: &page.meta.title,
  105. description: &page.meta.description,
  106. extra: &page.meta.extra,
  107. date: &page.meta.date,
  108. year,
  109. month,
  110. day,
  111. taxonomies: &page.meta.taxonomies,
  112. path: &page.path,
  113. components: &page.components,
  114. summary: &page.summary,
  115. word_count: page.word_count,
  116. reading_time: page.reading_time,
  117. assets: &page.serialized_assets,
  118. draft: page.is_draft(),
  119. lang: &page.lang,
  120. lighter,
  121. heavier,
  122. earlier,
  123. later,
  124. translations,
  125. }
  126. }
  127. /// Same as from_page but does not fill sibling pages
  128. pub fn from_page_basic(page: &'a Page, library: Option<&'a Library>) -> Self {
  129. let mut year = None;
  130. let mut month = None;
  131. let mut day = None;
  132. if let Some(d) = page.meta.datetime_tuple {
  133. year = Some(d.0);
  134. month = Some(d.1);
  135. day = Some(d.2);
  136. }
  137. let ancestors = if let Some(ref lib) = library {
  138. page.ancestors
  139. .iter()
  140. .map(|k| lib.get_section_by_key(*k).file.relative.clone())
  141. .collect()
  142. } else {
  143. vec![]
  144. };
  145. let translations = if let Some(ref lib) = library {
  146. TranslatedContent::find_all_pages(page, lib)
  147. } else {
  148. vec![]
  149. };
  150. SerializingPage {
  151. relative_path: &page.file.relative,
  152. ancestors,
  153. content: &page.content,
  154. permalink: &page.permalink,
  155. slug: &page.slug,
  156. title: &page.meta.title,
  157. description: &page.meta.description,
  158. extra: &page.meta.extra,
  159. date: &page.meta.date,
  160. year,
  161. month,
  162. day,
  163. taxonomies: &page.meta.taxonomies,
  164. path: &page.path,
  165. components: &page.components,
  166. summary: &page.summary,
  167. word_count: page.word_count,
  168. reading_time: page.reading_time,
  169. assets: &page.serialized_assets,
  170. draft: page.is_draft(),
  171. lang: &page.lang,
  172. lighter: None,
  173. heavier: None,
  174. earlier: None,
  175. later: None,
  176. translations,
  177. }
  178. }
  179. }
  180. #[derive(Clone, Debug, PartialEq, Serialize)]
  181. pub struct SerializingSection<'a> {
  182. relative_path: &'a str,
  183. content: &'a str,
  184. permalink: &'a str,
  185. ancestors: Vec<String>,
  186. title: &'a Option<String>,
  187. description: &'a Option<String>,
  188. extra: &'a HashMap<String, Value>,
  189. path: &'a str,
  190. components: &'a [String],
  191. word_count: Option<usize>,
  192. reading_time: Option<usize>,
  193. lang: &'a str,
  194. assets: &'a [String],
  195. pages: Vec<SerializingPage<'a>>,
  196. subsections: Vec<&'a str>,
  197. translations: Vec<TranslatedContent<'a>>,
  198. }
  199. impl<'a> SerializingSection<'a> {
  200. pub fn from_section(section: &'a Section, library: &'a Library) -> Self {
  201. let mut pages = Vec::with_capacity(section.pages.len());
  202. let mut subsections = Vec::with_capacity(section.subsections.len());
  203. for k in &section.pages {
  204. pages.push(library.get_page_by_key(*k).to_serialized_basic(library));
  205. }
  206. for k in &section.subsections {
  207. subsections.push(library.get_section_path_by_key(*k));
  208. }
  209. let ancestors = section
  210. .ancestors
  211. .iter()
  212. .map(|k| library.get_section_by_key(*k).file.relative.clone())
  213. .collect();
  214. let translations = TranslatedContent::find_all_sections(section, library);
  215. SerializingSection {
  216. relative_path: &section.file.relative,
  217. ancestors,
  218. content: &section.content,
  219. permalink: &section.permalink,
  220. title: &section.meta.title,
  221. description: &section.meta.description,
  222. extra: &section.meta.extra,
  223. path: &section.path,
  224. components: &section.components,
  225. word_count: section.word_count,
  226. reading_time: section.reading_time,
  227. assets: &section.serialized_assets,
  228. lang: &section.lang,
  229. pages,
  230. subsections,
  231. translations,
  232. }
  233. }
  234. /// Same as from_section but doesn't fetch pages and sections
  235. pub fn from_section_basic(section: &'a Section, library: Option<&'a Library>) -> Self {
  236. let ancestors = if let Some(ref lib) = library {
  237. section
  238. .ancestors
  239. .iter()
  240. .map(|k| lib.get_section_by_key(*k).file.relative.clone())
  241. .collect()
  242. } else {
  243. vec![]
  244. };
  245. let translations = if let Some(ref lib) = library {
  246. TranslatedContent::find_all_sections(section, lib)
  247. } else {
  248. vec![]
  249. };
  250. SerializingSection {
  251. relative_path: &section.file.relative,
  252. ancestors,
  253. content: &section.content,
  254. permalink: &section.permalink,
  255. title: &section.meta.title,
  256. description: &section.meta.description,
  257. extra: &section.meta.extra,
  258. path: &section.path,
  259. components: &section.components,
  260. word_count: section.word_count,
  261. reading_time: section.reading_time,
  262. assets: &section.serialized_assets,
  263. lang: &section.lang,
  264. pages: vec![],
  265. subsections: vec![],
  266. translations,
  267. }
  268. }
  269. }