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.

81 lines
2.3KB

  1. extern crate elasticlunr;
  2. #[macro_use]
  3. extern crate lazy_static;
  4. extern crate ammonia;
  5. #[macro_use]
  6. extern crate errors;
  7. extern crate content;
  8. use std::collections::{HashMap, HashSet};
  9. use std::path::PathBuf;
  10. use elasticlunr::{Index, Language};
  11. use content::Section;
  12. use errors::Result;
  13. pub const ELASTICLUNR_JS: &'static str = include_str!("elasticlunr.min.js");
  14. lazy_static! {
  15. static ref AMMONIA: ammonia::Builder<'static> = {
  16. let mut clean_content = HashSet::new();
  17. clean_content.insert("script");
  18. clean_content.insert("style");
  19. let mut builder = ammonia::Builder::new();
  20. builder
  21. .tags(HashSet::new())
  22. .tag_attributes(HashMap::new())
  23. .generic_attributes(HashSet::new())
  24. .link_rel(None)
  25. .allowed_classes(HashMap::new())
  26. .clean_content_tags(clean_content);
  27. builder
  28. };
  29. }
  30. /// Returns the generated JSON index with all the documents of the site added using
  31. /// the language given
  32. /// Errors if the language given is not available in Elasticlunr
  33. /// TODO: is making `in_search_index` apply to subsections of a `false` section useful?
  34. pub fn build_index(sections: &HashMap<PathBuf, Section>, lang: &str) -> Result<String> {
  35. let language = match Language::from_code(lang) {
  36. Some(l) => l,
  37. None => { bail!("Tried to build search index for language {} which is not supported", lang); }
  38. };
  39. let mut index = Index::with_language(language, &["title", "body"]);
  40. for section in sections.values() {
  41. add_section_to_index(&mut index, section);
  42. }
  43. Ok(index.to_json())
  44. }
  45. fn add_section_to_index(index: &mut Index, section: &Section) {
  46. if !section.meta.in_search_index {
  47. return;
  48. }
  49. // Don't index redirecting sections
  50. if section.meta.redirect_to.is_none() {
  51. index.add_doc(
  52. &section.permalink,
  53. &[&section.meta.title.clone().unwrap_or(String::new()), &AMMONIA.clean(&section.content).to_string()],
  54. );
  55. }
  56. for page in &section.pages {
  57. if !page.meta.in_search_index || page.meta.draft {
  58. continue;
  59. }
  60. index.add_doc(
  61. &page.permalink,
  62. &[&page.meta.title.clone().unwrap_or(String::new()), &AMMONIA.clean(&page.content).to_string()],
  63. );
  64. }
  65. }