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.

191 lines
6.5KB

  1. use rayon::prelude::*;
  2. use page::Page;
  3. use front_matter::SortBy;
  4. /// Sort pages using the method for the given section
  5. ///
  6. /// Any pages that doesn't have a date when the sorting method is date or order
  7. /// when the sorting method is order will be ignored.
  8. pub fn sort_pages(pages: Vec<Page>, sort_by: SortBy) -> (Vec<Page>, Vec<Page>) {
  9. match sort_by {
  10. SortBy::Date => {
  11. let mut can_be_sorted = vec![];
  12. let mut cannot_be_sorted = vec![];
  13. for page in pages {
  14. if page.meta.date.is_some() {
  15. can_be_sorted.push(page);
  16. } else {
  17. cannot_be_sorted.push(page);
  18. }
  19. }
  20. can_be_sorted.par_sort_unstable_by(|a, b| b.meta.date().unwrap().cmp(&a.meta.date().unwrap()));
  21. (can_be_sorted, cannot_be_sorted)
  22. },
  23. SortBy::Order | SortBy::Weight => {
  24. let mut can_be_sorted = vec![];
  25. let mut cannot_be_sorted = vec![];
  26. for page in pages {
  27. if page.meta.order.is_some() {
  28. can_be_sorted.push(page);
  29. } else {
  30. cannot_be_sorted.push(page);
  31. }
  32. }
  33. if sort_by == SortBy::Order {
  34. can_be_sorted.par_sort_unstable_by(|a, b| b.meta.order().cmp(&a.meta.order()));
  35. } else {
  36. can_be_sorted.par_sort_unstable_by(|a, b| a.meta.order().cmp(&b.meta.order()));
  37. }
  38. (can_be_sorted, cannot_be_sorted)
  39. },
  40. SortBy::None => (pages, vec![])
  41. }
  42. }
  43. /// Horribly inefficient way to set previous and next on each pages
  44. /// So many clones
  45. pub fn populate_previous_and_next_pages(input: &[Page]) -> Vec<Page> {
  46. let pages = input.to_vec();
  47. let mut res = Vec::new();
  48. // the input is already sorted
  49. // We might put prev/next randomly if a page is missing date/order, probably fine
  50. for (i, page) in input.iter().enumerate() {
  51. let mut new_page = page.clone();
  52. if i > 0 {
  53. let next = &pages[i - 1];
  54. let mut next_page = next.clone();
  55. // Remove prev/next otherwise we serialise the whole thing...
  56. next_page.previous = None;
  57. next_page.next = None;
  58. new_page.next = Some(Box::new(next_page));
  59. }
  60. if i < input.len() - 1 {
  61. let previous = &pages[i + 1];
  62. // Remove prev/next otherwise we serialise the whole thing...
  63. let mut previous_page = previous.clone();
  64. previous_page.previous = None;
  65. previous_page.next = None;
  66. new_page.previous = Some(Box::new(previous_page));
  67. }
  68. res.push(new_page);
  69. }
  70. res
  71. }
  72. #[cfg(test)]
  73. mod tests {
  74. use front_matter::{PageFrontMatter, SortBy};
  75. use page::Page;
  76. use super::{sort_pages, populate_previous_and_next_pages};
  77. fn create_page_with_date(date: &str) -> Page {
  78. let mut front_matter = PageFrontMatter::default();
  79. front_matter.date = Some(date.to_string());
  80. Page::new("content/hello.md", front_matter)
  81. }
  82. fn create_page_with_order(order: usize) -> Page {
  83. let mut front_matter = PageFrontMatter::default();
  84. front_matter.order = Some(order);
  85. Page::new("content/hello.md", front_matter)
  86. }
  87. #[test]
  88. fn can_sort_by_dates() {
  89. let input = vec![
  90. create_page_with_date("2018-01-01"),
  91. create_page_with_date("2017-01-01"),
  92. create_page_with_date("2019-01-01"),
  93. ];
  94. let (pages, _) = sort_pages(input, SortBy::Date);
  95. // Should be sorted by date
  96. assert_eq!(pages[0].clone().meta.date.unwrap(), "2019-01-01");
  97. assert_eq!(pages[1].clone().meta.date.unwrap(), "2018-01-01");
  98. assert_eq!(pages[2].clone().meta.date.unwrap(), "2017-01-01");
  99. }
  100. #[test]
  101. fn can_sort_by_order() {
  102. let input = vec![
  103. create_page_with_order(2),
  104. create_page_with_order(3),
  105. create_page_with_order(1),
  106. ];
  107. let (pages, _) = sort_pages(input, SortBy::Order);
  108. // Should be sorted by date
  109. assert_eq!(pages[0].clone().meta.order.unwrap(), 3);
  110. assert_eq!(pages[1].clone().meta.order.unwrap(), 2);
  111. assert_eq!(pages[2].clone().meta.order.unwrap(), 1);
  112. }
  113. #[test]
  114. fn can_sort_by_weight() {
  115. let input = vec![
  116. create_page_with_order(2),
  117. create_page_with_order(3),
  118. create_page_with_order(1),
  119. ];
  120. let (pages, _) = sort_pages(input, SortBy::Weight);
  121. // Should be sorted by date
  122. assert_eq!(pages[0].clone().meta.order.unwrap(), 1);
  123. assert_eq!(pages[1].clone().meta.order.unwrap(), 2);
  124. assert_eq!(pages[2].clone().meta.order.unwrap(), 3);
  125. }
  126. #[test]
  127. fn can_sort_by_none() {
  128. let input = vec![
  129. create_page_with_order(2),
  130. create_page_with_order(3),
  131. create_page_with_order(1),
  132. ];
  133. let (pages, _) = sort_pages(input, SortBy::None);
  134. // Should be sorted by date
  135. assert_eq!(pages[0].clone().meta.order.unwrap(), 2);
  136. assert_eq!(pages[1].clone().meta.order.unwrap(), 3);
  137. assert_eq!(pages[2].clone().meta.order.unwrap(), 1);
  138. }
  139. #[test]
  140. fn ignore_page_with_missing_field() {
  141. let input = vec![
  142. create_page_with_order(2),
  143. create_page_with_order(3),
  144. create_page_with_date("2019-01-01"),
  145. ];
  146. let (pages, unsorted) = sort_pages(input, SortBy::Order);
  147. assert_eq!(pages.len(), 2);
  148. assert_eq!(unsorted.len(), 1);
  149. }
  150. #[test]
  151. fn can_populate_previous_and_next_pages() {
  152. let input = vec![
  153. create_page_with_order(3),
  154. create_page_with_order(2),
  155. create_page_with_order(1),
  156. ];
  157. let pages = populate_previous_and_next_pages(input.as_slice());
  158. assert!(pages[0].clone().next.is_none());
  159. assert!(pages[0].clone().previous.is_some());
  160. assert_eq!(pages[0].clone().previous.unwrap().meta.order.unwrap(), 2);
  161. assert!(pages[1].clone().next.is_some());
  162. assert!(pages[1].clone().previous.is_some());
  163. assert_eq!(pages[1].clone().next.unwrap().meta.order.unwrap(), 3);
  164. assert_eq!(pages[1].clone().previous.unwrap().meta.order.unwrap(), 1);
  165. assert!(pages[2].clone().next.is_some());
  166. assert!(pages[2].clone().previous.is_none());
  167. assert_eq!(pages[2].clone().next.unwrap().meta.order.unwrap(), 2);
  168. }
  169. }