Lang aware search indices settings

This commit is contained in:
Vincent Prouillet 2021-03-13 21:27:17 +01:00
parent 187bc30f00
commit 32433e7d6c
4 changed files with 42 additions and 27 deletions

View file

@ -4,6 +4,7 @@ use errors::{bail, Result};
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use unic_langid::LanguageIdentifier; use unic_langid::LanguageIdentifier;
use crate::config::search;
use crate::config::taxonomies; use crate::config::taxonomies;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@ -15,9 +16,11 @@ pub struct LanguageOptions {
pub description: Option<String>, pub description: Option<String>,
/// Whether to generate a feed for that language, defaults to `false` /// Whether to generate a feed for that language, defaults to `false`
pub generate_feed: bool, pub generate_feed: bool,
pub taxonomies: Vec<taxonomies::Taxonomy>,
/// Whether to generate search index for that language, defaults to `false` /// Whether to generate search index for that language, defaults to `false`
pub build_search_index: bool, pub build_search_index: bool,
pub taxonomies: Vec<taxonomies::Taxonomy>, /// The search config, telling what to include in the search index for that language
pub search: search::Search,
} }
impl Default for LanguageOptions { impl Default for LanguageOptions {
@ -28,6 +31,7 @@ impl Default for LanguageOptions {
generate_feed: false, generate_feed: false,
build_search_index: false, build_search_index: false,
taxonomies: Vec::new(), taxonomies: Vec::new(),
search: search::Search::default(),
} }
} }
} }

View file

@ -205,6 +205,7 @@ impl Config {
generate_feed: self.generate_feed, generate_feed: self.generate_feed,
build_search_index: self.build_search_index, build_search_index: self.build_search_index,
taxonomies: self.taxonomies.clone(), taxonomies: self.taxonomies.clone(),
search: self.search.clone(),
}, },
); );
} }
@ -290,7 +291,7 @@ impl Config {
translations: &self.translations, translations: &self.translations,
generate_feed: options.generate_feed, generate_feed: options.generate_feed,
taxonomies: &options.taxonomies, taxonomies: &options.taxonomies,
build_search_index: self.build_search_index, build_search_index: options.build_search_index,
extra: &self.extra, extra: &self.extra,
} }
} }

View file

@ -3,8 +3,8 @@ pub mod highlighting;
mod theme; mod theme;
pub use crate::config::{ pub use crate::config::{
languages::LanguageOptions, link_checker::LinkChecker, slugify::Slugify, taxonomies::Taxonomy, languages::LanguageOptions, link_checker::LinkChecker, search::Search, slugify::Slugify,
Config, taxonomies::Taxonomy, Config,
}; };
use errors::Result; use errors::Result;

View file

@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet};
use elasticlunr::{Index, Language}; use elasticlunr::{Index, Language};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use config::Config; use config::{Config, Search};
use errors::{bail, Result}; use errors::{bail, Result};
use library::{Library, Section}; use library::{Library, Section};
@ -26,17 +26,17 @@ lazy_static! {
}; };
} }
fn build_fields(config: &Config) -> Vec<String> { fn build_fields(search_config: &Search) -> Vec<String> {
let mut fields = vec![]; let mut fields = vec![];
if config.search.include_title { if search_config.include_title {
fields.push("title".to_owned()); fields.push("title".to_owned());
} }
if config.search.include_description { if search_config.include_description {
fields.push("description".to_owned()); fields.push("description".to_owned());
} }
if config.search.include_content { if search_config.include_content {
fields.push("body".to_owned()); fields.push("body".to_owned());
} }
@ -44,24 +44,24 @@ fn build_fields(config: &Config) -> Vec<String> {
} }
fn fill_index( fn fill_index(
config: &Config, search_config: &Search,
title: &Option<String>, title: &Option<String>,
description: &Option<String>, description: &Option<String>,
content: &str, content: &str,
) -> Vec<String> { ) -> Vec<String> {
let mut row = vec![]; let mut row = vec![];
if config.search.include_title { if search_config.include_title {
row.push(title.clone().unwrap_or_default()); row.push(title.clone().unwrap_or_default());
} }
if config.search.include_description { if search_config.include_description {
row.push(description.clone().unwrap_or_default()); row.push(description.clone().unwrap_or_default());
} }
if config.search.include_content { if search_config.include_content {
let body = AMMONIA.clean(&content).to_string(); let body = AMMONIA.clean(&content).to_string();
if let Some(truncate_len) = config.search.truncate_content_length { if let Some(truncate_len) = search_config.truncate_content_length {
// Not great for unicode // Not great for unicode
// TODO: fix it like the truncate in Tera // TODO: fix it like the truncate in Tera
match body.char_indices().nth(truncate_len) { match body.char_indices().nth(truncate_len) {
@ -87,19 +87,24 @@ pub fn build_index(lang: &str, library: &Library, config: &Config) -> Result<Str
bail!("Tried to build search index for language {} which is not supported", lang); bail!("Tried to build search index for language {} which is not supported", lang);
} }
}; };
let language_options = &config.languages[lang];
let mut index = Index::with_language(language, &build_fields(&config)); let mut index = Index::with_language(language, &build_fields(&language_options.search));
for section in library.sections_values() { for section in library.sections_values() {
if section.lang == lang { if section.lang == lang {
add_section_to_index(&mut index, section, library, config); add_section_to_index(&mut index, section, library, &language_options.search);
} }
} }
Ok(index.to_json()) Ok(index.to_json())
} }
fn add_section_to_index(index: &mut Index, section: &Section, library: &Library, config: &Config) { fn add_section_to_index(
index: &mut Index,
section: &Section,
library: &Library,
search_config: &Search,
) {
if !section.meta.in_search_index { if !section.meta.in_search_index {
return; return;
} }
@ -108,7 +113,12 @@ fn add_section_to_index(index: &mut Index, section: &Section, library: &Library,
if section.meta.redirect_to.is_none() { if section.meta.redirect_to.is_none() {
index.add_doc( index.add_doc(
&section.permalink, &section.permalink,
&fill_index(config, &section.meta.title, &section.meta.description, &section.content), &fill_index(
search_config,
&section.meta.title,
&section.meta.description,
&section.content,
),
); );
} }
@ -120,7 +130,7 @@ fn add_section_to_index(index: &mut Index, section: &Section, library: &Library,
index.add_doc( index.add_doc(
&page.permalink, &page.permalink,
&fill_index(config, &page.meta.title, &page.meta.description, &page.content), &fill_index(search_config, &page.meta.title, &page.meta.description, &page.content),
); );
} }
} }
@ -134,20 +144,20 @@ mod tests {
#[test] #[test]
fn can_build_fields() { fn can_build_fields() {
let mut config = Config::default(); let mut config = Config::default();
let fields = build_fields(&config); let fields = build_fields(&config.search);
assert_eq!(fields, vec!["title", "body"]); assert_eq!(fields, vec!["title", "body"]);
config.search.include_content = false; config.search.include_content = false;
config.search.include_description = true; config.search.include_description = true;
let fields = build_fields(&config); let fields = build_fields(&config.search);
assert_eq!(fields, vec!["title", "description"]); assert_eq!(fields, vec!["title", "description"]);
config.search.include_content = true; config.search.include_content = true;
let fields = build_fields(&config); let fields = build_fields(&config.search);
assert_eq!(fields, vec!["title", "description", "body"]); assert_eq!(fields, vec!["title", "description", "body"]);
config.search.include_title = false; config.search.include_title = false;
let fields = build_fields(&config); let fields = build_fields(&config.search);
assert_eq!(fields, vec!["description", "body"]); assert_eq!(fields, vec!["description", "body"]);
} }
@ -158,7 +168,7 @@ mod tests {
let description = Some("A description".to_string()); let description = Some("A description".to_string());
let content = "Some content".to_string(); let content = "Some content".to_string();
let res = fill_index(&config, &title, &description, &content); let res = fill_index(&config.search, &title, &description, &content);
assert_eq!(res.len(), 2); assert_eq!(res.len(), 2);
assert_eq!(res[0], title.unwrap()); assert_eq!(res[0], title.unwrap());
assert_eq!(res[1], content); assert_eq!(res[1], content);
@ -172,7 +182,7 @@ mod tests {
let description = Some("A description".to_string()); let description = Some("A description".to_string());
let content = "Some content".to_string(); let content = "Some content".to_string();
let res = fill_index(&config, &title, &description, &content); let res = fill_index(&config.search, &title, &description, &content);
assert_eq!(res.len(), 3); assert_eq!(res.len(), 3);
assert_eq!(res[0], title.unwrap()); assert_eq!(res[0], title.unwrap());
assert_eq!(res[1], description.unwrap()); assert_eq!(res[1], description.unwrap());
@ -187,7 +197,7 @@ mod tests {
let description = Some("A description".to_string()); let description = Some("A description".to_string());
let content = "Some content".to_string(); let content = "Some content".to_string();
let res = fill_index(&config, &title, &description, &content); let res = fill_index(&config.search, &title, &description, &content);
assert_eq!(res.len(), 2); assert_eq!(res.len(), 2);
assert_eq!(res[0], title.unwrap()); assert_eq!(res[0], title.unwrap());
assert_eq!(res[1], content[..5]); assert_eq!(res[1], content[..5]);