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.

302 lines
9.3KB

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