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.

170 lines
5.5KB

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