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.

306 lines
9.6KB

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