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.

128 lines
4.1KB

  1. use std::borrow::Cow;
  2. use std::hash::{Hash, Hasher};
  3. use std::collections::{HashSet};
  4. use tera::{Map, Value};
  5. use config::{Config};
  6. use library::{Library, Taxonomy};
  7. /// The sitemap only needs links, potentially date and extra for pages in case of updates
  8. /// for examples so we trim down all entries to only that
  9. #[derive(Debug, Serialize)]
  10. pub struct SitemapEntry<'a> {
  11. permalink: Cow<'a, str>,
  12. date: Option<String>,
  13. extra: Option<&'a Map<String, Value>>,
  14. }
  15. // Hash/Eq is not implemented for tera::Map but in our case we only care about the permalink
  16. // when comparing/hashing so we implement it manually
  17. impl<'a> Hash for SitemapEntry<'a> {
  18. fn hash<H: Hasher>(&self, state: &mut H) {
  19. self.permalink.hash(state);
  20. }
  21. }
  22. impl<'a> PartialEq for SitemapEntry<'a> {
  23. fn eq(&self, other: &SitemapEntry) -> bool {
  24. self.permalink == other.permalink
  25. }
  26. }
  27. impl<'a> Eq for SitemapEntry<'a> {}
  28. impl<'a> SitemapEntry<'a> {
  29. pub fn new(permalink: Cow<'a, str>, date: Option<String>) -> Self {
  30. SitemapEntry { permalink, date, extra: None }
  31. }
  32. pub fn add_extra(&mut self, extra: &'a Map<String, Value>) {
  33. self.extra = Some(extra);
  34. }
  35. }
  36. /// Finds out all the links to put in a sitemap from the pages/sections/taxonomies
  37. /// There are no duplicate permalinks in the output vec
  38. pub fn find_entries<'a>(library: &'a Library, taxonomies: &'a [Taxonomy], config: &'a Config) -> Vec<SitemapEntry<'a>> {
  39. let pages = library
  40. .pages_values()
  41. .iter()
  42. .filter(|p| !p.is_draft())
  43. .map(|p| {
  44. let date = match p.meta.date {
  45. Some(ref d) => Some(d.to_string()),
  46. None => None,
  47. };
  48. let mut entry = SitemapEntry::new(Cow::Borrowed(&p.permalink), date);
  49. entry.add_extra(&p.meta.extra);
  50. entry
  51. })
  52. .collect::<Vec<_>>();
  53. let mut sections = library
  54. .sections_values()
  55. .iter()
  56. .filter(|s| s.meta.render)
  57. .map(|s| SitemapEntry::new(Cow::Borrowed(&s.permalink), None))
  58. .collect::<Vec<_>>();
  59. for section in library
  60. .sections_values()
  61. .iter()
  62. .filter(|s| s.meta.paginate_by.is_some())
  63. {
  64. let number_pagers = (section.pages.len() as f64
  65. / section.meta.paginate_by.unwrap() as f64)
  66. .ceil() as isize;
  67. for i in 1..=number_pagers {
  68. let permalink =
  69. format!("{}{}/{}/", section.permalink, section.meta.paginate_path, i);
  70. sections.push(SitemapEntry::new(Cow::Owned(permalink), None))
  71. }
  72. }
  73. let mut taxonomies_entries = vec![];
  74. for taxonomy in taxonomies {
  75. let name = &taxonomy.kind.name;
  76. let mut terms = vec![];
  77. terms.push(SitemapEntry::new(Cow::Owned(config.make_permalink(name)), None));
  78. for item in &taxonomy.items {
  79. terms.push(SitemapEntry::new(
  80. Cow::Owned(config.make_permalink(&format!("{}/{}", name, item.slug))),
  81. None,
  82. ));
  83. if taxonomy.kind.is_paginated() {
  84. let number_pagers = (item.pages.len() as f64
  85. / taxonomy.kind.paginate_by.unwrap() as f64)
  86. .ceil() as isize;
  87. for i in 1..=number_pagers {
  88. let permalink = config.make_permalink(&format!(
  89. "{}/{}/{}/{}",
  90. name,
  91. item.slug,
  92. taxonomy.kind.paginate_path(),
  93. i
  94. ));
  95. terms.push(SitemapEntry::new(Cow::Owned(permalink), None))
  96. }
  97. }
  98. }
  99. taxonomies_entries.push(terms);
  100. }
  101. let mut all_sitemap_entries = HashSet::new();
  102. for p in pages {
  103. all_sitemap_entries.insert(p);
  104. }
  105. for s in sections {
  106. all_sitemap_entries.insert(s);
  107. }
  108. for terms in taxonomies_entries {
  109. for term in terms {
  110. all_sitemap_entries.insert(term);
  111. }
  112. }
  113. all_sitemap_entries.into_iter().collect::<Vec<_>>()
  114. }