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.

357 lines
12KB

  1. use std::collections::{HashMap, HashSet};
  2. use std::path::{Path, PathBuf};
  3. use slotmap::{DenseSlotMap, Key};
  4. use tera::{Value, to_value};
  5. use front_matter::SortBy;
  6. use sorting::{find_siblings, sort_pages_by_weight, sort_pages_by_date};
  7. use content::{Page, Section};
  8. #[derive(Debug)]
  9. struct Values {
  10. pages: HashMap<Key, Value>,
  11. sections: HashMap<Key, Value>,
  12. }
  13. impl Values {
  14. pub fn new(cap_pages: usize, cap_sections: usize) -> Values {
  15. Values {
  16. pages: HashMap::with_capacity(cap_pages),
  17. sections: HashMap::with_capacity(cap_sections),
  18. }
  19. }
  20. pub fn get_page(&self, key: &Key) -> &Value {
  21. return self.pages.get(key).unwrap()
  22. }
  23. pub fn insert_page(&mut self, key: Key, value: Value) {
  24. self.pages.insert(key, value);
  25. }
  26. pub fn remove_page(&mut self, key: &Key) {
  27. self.pages.remove(key);
  28. }
  29. pub fn get_section(&self, key: &Key) -> &Value {
  30. return self.sections.get(key).unwrap()
  31. }
  32. pub fn insert_section(&mut self, key: Key, value: Value) {
  33. self.sections.insert(key, value);
  34. }
  35. pub fn remove_section(&mut self, key: &Key) {
  36. self.sections.remove(key);
  37. }
  38. }
  39. // Houses everything about pages/sections/taxonomies
  40. #[derive(Debug)]
  41. pub struct Library {
  42. pages: DenseSlotMap<Page>,
  43. sections: DenseSlotMap<Section>,
  44. paths_to_pages: HashMap<PathBuf, Key>,
  45. paths_to_sections: HashMap<PathBuf, Key>,
  46. values: Values,
  47. }
  48. impl Library {
  49. pub fn new(cap_pages: usize, cap_sections: usize) -> Self {
  50. Library {
  51. pages: DenseSlotMap::with_capacity(cap_pages),
  52. sections: DenseSlotMap::with_capacity(cap_sections),
  53. paths_to_pages: HashMap::with_capacity(cap_pages),
  54. paths_to_sections: HashMap::with_capacity(cap_sections),
  55. values: Values::new(cap_pages, cap_sections),
  56. }
  57. }
  58. pub fn insert_section(&mut self, section: Section) -> Key {
  59. let path = section.file.path.clone();
  60. let key = self.sections.insert(section);
  61. self.paths_to_sections.insert(path, key);
  62. key
  63. }
  64. pub fn insert_page(&mut self, page: Page) -> Key {
  65. let path = page.file.path.clone();
  66. let key = self.pages.insert(page);
  67. self.paths_to_pages.insert(path, key);
  68. key
  69. }
  70. pub fn pages(&self) -> &DenseSlotMap<Page> {
  71. &self.pages
  72. }
  73. pub fn pages_mut(&mut self) -> &mut DenseSlotMap<Page> {
  74. &mut self.pages
  75. }
  76. pub fn pages_values(&self) -> Vec<&Page> {
  77. self.pages.values().collect::<Vec<_>>()
  78. }
  79. pub fn pages_values_mut(&mut self) -> Vec<&mut Page> {
  80. self.pages.values_mut().collect::<Vec<_>>()
  81. }
  82. pub fn sections(&self) -> &DenseSlotMap<Section> {
  83. &self.sections
  84. }
  85. pub fn sections_mut(&mut self) -> &mut DenseSlotMap<Section> {
  86. &mut self.sections
  87. }
  88. pub fn sections_values(&self) -> Vec<&Section> {
  89. self.sections.values().collect::<Vec<_>>()
  90. }
  91. pub fn sections_values_mut(&mut self) -> Vec<&mut Section> {
  92. self.sections.values_mut().collect::<Vec<_>>()
  93. }
  94. /// Find out the direct subsections of each subsection if there are some
  95. /// as well as the pages for each section
  96. pub fn populate_sections(&mut self) {
  97. let mut grandparent_paths: HashMap<PathBuf, Vec<PathBuf>> = HashMap::new();
  98. for section in self.sections.values_mut() {
  99. if let Some(ref grand_parent) = section.file.grand_parent {
  100. grandparent_paths
  101. .entry(grand_parent.to_path_buf())
  102. .or_insert_with(|| vec![])
  103. .push(section.file.path.clone());
  104. }
  105. // Make sure the pages of a section are empty since we can call that many times on `serve`
  106. section.pages = vec![];
  107. section.ignored_pages = vec![];
  108. }
  109. for (key, page) in &mut self.pages {
  110. let parent_section_path = page.file.parent.join("_index.md");
  111. if let Some(section_key) = self.paths_to_sections.get(&parent_section_path) {
  112. self.sections.get_mut(*section_key).unwrap().pages.push(key);
  113. }
  114. }
  115. self.sort_sections_pages(None);
  116. let sections = self.paths_to_sections.clone();
  117. let mut sections_weight = HashMap::new();
  118. for (key, section) in &self.sections {
  119. sections_weight.insert(key, section.meta.weight);
  120. }
  121. for section in self.sections.values_mut() {
  122. if let Some(paths) = grandparent_paths.get(&section.file.parent) {
  123. section.subsections = paths
  124. .iter()
  125. .map(|p| sections[p])
  126. .collect::<Vec<_>>();
  127. section.subsections
  128. .sort_by(|a, b| sections_weight[a].cmp(&sections_weight[b]));
  129. }
  130. }
  131. }
  132. pub fn sort_sections_pages(&mut self, only: Option<&Path>) {
  133. let mut updates = HashMap::new();
  134. for (key, section) in &self.sections {
  135. if let Some(p) = only {
  136. if p != section.file.path {
  137. continue;
  138. }
  139. }
  140. // TODO: use an enum to avoid duplication there and in sorting.rs?
  141. let (sorted_pages, cannot_be_sorted_pages) = match section.meta.sort_by {
  142. SortBy::None => continue,
  143. SortBy::Date => {
  144. let data = section.pages
  145. .iter()
  146. .map(|k| {
  147. if let Some(page) = self.pages.get(*k) {
  148. (k, page.meta.datetime, page.permalink.as_ref())
  149. } else {
  150. unreachable!("Sorting got an unknown page")
  151. }
  152. })
  153. .collect();
  154. sort_pages_by_date(data)
  155. },
  156. SortBy::Weight => {
  157. let data = section.pages
  158. .iter()
  159. .map(|k| {
  160. if let Some(page) = self.pages.get(*k) {
  161. (k, page.meta.weight, page.permalink.as_ref())
  162. } else {
  163. unreachable!("Sorting got an unknown page")
  164. }
  165. })
  166. .collect();
  167. sort_pages_by_weight(data)
  168. }
  169. };
  170. updates.insert(key, (sorted_pages, cannot_be_sorted_pages, section.meta.sort_by));
  171. }
  172. for (key, (sorted, cannot_be_sorted, sort_by)) in updates {
  173. // Find sibling between sorted pages first
  174. let with_siblings = find_siblings(sorted.iter().map(|k| {
  175. if let Some(page) = self.pages.get(*k) {
  176. (k, page.is_draft())
  177. } else {
  178. unreachable!("Sorting got an unknown page")
  179. }
  180. }).collect());
  181. for (k2, val1, val2) in with_siblings {
  182. if let Some(page) = self.pages.get_mut(k2) {
  183. match sort_by {
  184. SortBy::Date => {
  185. page.earlier = val2;
  186. page.later = val1;
  187. },
  188. SortBy::Weight => {
  189. page.lighter = val1;
  190. page.heavier = val2;
  191. },
  192. SortBy::None => unreachable!("Impossible to find siblings in SortBy::None")
  193. }
  194. } else {
  195. unreachable!("Sorting got an unknown page")
  196. }
  197. }
  198. if let Some(s) = self.sections.get_mut(key) {
  199. s.pages = sorted;
  200. s.ignored_pages = cannot_be_sorted;
  201. }
  202. }
  203. }
  204. pub fn cache_all_pages(&mut self) {
  205. let mut cache = HashMap::with_capacity(self.pages.capacity());
  206. for (key, page) in &self.pages {
  207. cache.insert(key, to_value(page.to_serialized(self.pages())).unwrap());
  208. }
  209. for (key, value) in cache {
  210. self.values.insert_page(key, value);
  211. }
  212. }
  213. // We need to do it from the bottom up to ensure all subsections of a section have been
  214. // cached before doing it
  215. pub fn cache_all_sections(&mut self) {
  216. // we get the Key in order we want to process them first
  217. let mut deps = HashMap::new();
  218. for (key, section) in &self.sections {
  219. deps.insert(key, section.subsections.clone());
  220. }
  221. loop {
  222. if deps.is_empty() {
  223. break;
  224. }
  225. let mut processed_keys = vec![];
  226. for (key, _) in deps.iter().filter(|(_, v)| v.is_empty()) {
  227. let section = self.sections.get(*key).unwrap();
  228. let value = to_value(section.to_serialized(self)).unwrap();
  229. self.values.insert_section(*key, value);
  230. processed_keys.push(*key);
  231. }
  232. // remove the processed keys from the action
  233. for key in processed_keys {
  234. deps.remove(&key);
  235. for (_, subs) in &mut deps {
  236. subs.retain(|k| k != &key);
  237. }
  238. }
  239. }
  240. }
  241. pub fn get_all_orphan_pages(&self) -> Vec<&Page> {
  242. let pages_in_sections = self.sections
  243. .values()
  244. .flat_map(|s| s.all_pages_path())
  245. .collect::<HashSet<_>>();
  246. self.pages
  247. .values()
  248. .filter(|page| !pages_in_sections.contains(&page.file.path))
  249. .collect()
  250. }
  251. pub fn get_section(&self, path: &PathBuf) -> Option<&Section> {
  252. self.sections.get(self.paths_to_sections.get(path).cloned().unwrap_or_default())
  253. }
  254. pub fn get_section_mut(&mut self, path: &PathBuf) -> Option<&mut Section> {
  255. self.sections.get_mut(self.paths_to_sections.get(path).cloned().unwrap_or_default())
  256. }
  257. pub fn get_section_by_key(&self, key: Key) -> &Section {
  258. self.sections.get(key).unwrap()
  259. }
  260. pub fn remove_section_by_path(&mut self, path: &PathBuf) -> Option<Section> {
  261. if let Some(k) = self.paths_to_sections.remove(path) {
  262. self.values.remove_section(&k);
  263. self.sections.remove(k)
  264. } else {
  265. None
  266. }
  267. }
  268. pub fn contains_section(&self, path: &PathBuf) -> bool {
  269. self.paths_to_sections.contains_key(path)
  270. }
  271. pub fn get_cached_section_value(&self, path: &PathBuf) -> &Value {
  272. self.values.get_section(self.paths_to_sections.get(path).unwrap())
  273. }
  274. pub fn get_cached_section_value_by_key(&self, key: &Key) -> &Value {
  275. self.values.get_section(key)
  276. }
  277. pub fn get_page(&self, path: &PathBuf) -> Option<&Page> {
  278. self.pages.get(self.paths_to_pages.get(path).cloned().unwrap_or_default())
  279. }
  280. pub fn get_cached_page_value(&self, path: &PathBuf) -> &Value {
  281. self.values.get_page(self.paths_to_pages.get(path).unwrap())
  282. }
  283. pub fn get_cached_page_value_by_key(&self, key: &Key) -> &Value {
  284. self.values.get_page(key)
  285. }
  286. pub fn get_page_by_key(&self, key: Key) -> &Page {
  287. self.pages.get(key).unwrap()
  288. }
  289. pub fn remove_page_by_path(&mut self, path: &PathBuf) -> Option<Page> {
  290. if let Some(k) = self.paths_to_pages.remove(path) {
  291. self.values.remove_page(&k);
  292. self.pages.remove(k)
  293. } else {
  294. None
  295. }
  296. }
  297. pub fn contains_page(&self, path: &PathBuf) -> bool {
  298. self.paths_to_pages.contains_key(path)
  299. }
  300. }