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.

294 lines
9.2KB

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