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.

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