diff --git a/components/config/src/config/search.rs b/components/config/src/config/search.rs index aa36c46e76..c96a874847 100644 --- a/components/config/src/config/search.rs +++ b/components/config/src/config/search.rs @@ -1,5 +1,18 @@ use serde::{Deserialize, Serialize}; +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum IndexFormat { + ElasticlunrJson, + ElasticlunrJavascript, +} + +impl Default for IndexFormat { + fn default() -> IndexFormat { + IndexFormat::ElasticlunrJavascript + } +} + #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(default)] pub struct Search { @@ -15,6 +28,8 @@ pub struct Search { pub include_description: bool, /// Include the path of the page in the search index. `false` by default. pub include_path: bool, + /// Foramt of the search index to be produced. Javascript by default + pub index_format: IndexFormat, } impl Default for Search { @@ -25,6 +40,7 @@ impl Default for Search { include_description: false, include_path: false, truncate_content_length: None, + index_format: Default::default(), } } } diff --git a/components/config/src/lib.rs b/components/config/src/lib.rs index 59c6568b74..05d621615c 100644 --- a/components/config/src/lib.rs +++ b/components/config/src/lib.rs @@ -5,8 +5,13 @@ mod theme; use std::path::Path; pub use crate::config::{ - languages::LanguageOptions, link_checker::LinkChecker, link_checker::LinkCheckerLevel, - search::Search, slugify::Slugify, taxonomies::TaxonomyConfig, Config, + languages::LanguageOptions, + link_checker::LinkChecker, + link_checker::LinkCheckerLevel, + search::{IndexFormat, Search}, + slugify::Slugify, + taxonomies::TaxonomyConfig, + Config, }; use errors::Result; diff --git a/components/site/src/lib.rs b/components/site/src/lib.rs index 834e4d7f3e..079bc65635 100644 --- a/components/site/src/lib.rs +++ b/components/site/src/lib.rs @@ -15,7 +15,7 @@ use libs::rayon::prelude::*; use libs::tera::{Context, Tera}; use libs::walkdir::{DirEntry, WalkDir}; -use config::{get_config, Config}; +use config::{get_config, Config, IndexFormat}; use content::{Library, Page, Paginator, Section, Taxonomy}; use errors::{anyhow, bail, Context as ErrorContext, Result}; use libs::relative_path::RelativePathBuf; @@ -764,32 +764,36 @@ impl Site { Ok(()) } + fn index_for_lang(&self, lang: &str) -> Result<()> { + let index_json = search::build_index( + &self.config.default_language, + &self.library.read().unwrap(), + &self.config, + )?; + let (path, content) = match &self.config.search.index_format { + IndexFormat::ElasticlunrJson => { + let path = self.output_path.join(&format!("search_index.{}.json", lang)); + (path, index_json) + } + IndexFormat::ElasticlunrJavascript => { + let path = self.output_path.join(&format!("search_index.{}.js", lang)); + let content = format!("window.searchIndex = {};", index_json); + (path, content) + } + }; + create_file(&path, &content) + } + pub fn build_search_index(&self) -> Result<()> { ensure_directory_exists(&self.output_path)?; // TODO: add those to the SITE_CONTENT map // index first - create_file( - &self.output_path.join(&format!("search_index.{}.js", self.config.default_language)), - &format!( - "window.searchIndex = {};", - search::build_index( - &self.config.default_language, - &self.library.read().unwrap(), - &self.config - )? - ), - )?; + self.index_for_lang(&self.config.default_language)?; for (code, language) in &self.config.other_languages() { if code != &self.config.default_language && language.build_search_index { - create_file( - &self.output_path.join(&format!("search_index.{}.js", &code)), - &format!( - "window.searchIndex = {};", - search::build_index(code, &self.library.read().unwrap(), &self.config)? - ), - )?; + self.index_for_lang(code)?; } } diff --git a/docs/config.toml b/docs/config.toml index 87a0215e2e..1a462a72ce 100644 --- a/docs/config.toml +++ b/docs/config.toml @@ -5,6 +5,9 @@ description = "Everything you need to make a static site engine in one binary." compile_sass = true build_search_index = true +[search] +index_format = "elasticlunr_json" + [markdown] highlight_code = true highlight_theme = "kronuz" diff --git a/docs/content/documentation/content/search.md b/docs/content/documentation/content/search.md index d0f8779cb5..c57c1fc114 100644 --- a/docs/content/documentation/content/search.md +++ b/docs/content/documentation/content/search.md @@ -17,6 +17,9 @@ After `zola build` or `zola serve`, you should see two files in your public dire - `search_index.${default_language}.js`: so `search_index.en.js` for a default setup - `elasticlunr.min.js` +If you set `index_format = "elasticlunr_json"` in your `config.toml`, a `search_index.${default_language}.json` is generated +instead of the default `search_index.${default_language}.js`. + As each site will be different, Zola makes no assumptions about your search function and doesn't provide the JavaScript/CSS code to do an actual search and display results. You can look at how this site implements it to get an idea: [search.js](https://github.com/getzola/zola/tree/master/docs/static/search.js). diff --git a/docs/content/documentation/getting-started/configuration.md b/docs/content/documentation/getting-started/configuration.md index 92675197ca..0748b5ca54 100644 --- a/docs/content/documentation/getting-started/configuration.md +++ b/docs/content/documentation/getting-started/configuration.md @@ -160,6 +160,10 @@ include_content = true # become too big to load on the site. Defaults to not being set. # truncate_content_length = 100 +# Wether to produce the search index as a javascript file or as a JSON file +# Accepted value "elasticlunr_javascript" or "elasticlunr_json" +index_format = "elasticlunr_javascript" + # Optional translation object for the default language # Example: # default_language = "fr" diff --git a/docs/static/search.js b/docs/static/search.js index 408156555d..553b1de368 100644 --- a/docs/static/search.js +++ b/docs/static/search.js @@ -142,11 +142,24 @@ function initSearch() { } }; var currentTerm = ""; - var index = elasticlunr.Index.load(window.searchIndex); + var index; + + var initIndex = async function () { + if (index === undefined) { + index = fetch("/search_index.en.json") + .then( + async function(response) { + return await elasticlunr.Index.load(await response.json()); + } + ); + } + let res = await index; + return res; + } - $searchInput.addEventListener("keyup", debounce(function() { + $searchInput.addEventListener("keyup", debounce(async function() { var term = $searchInput.value.trim(); - if (term === currentTerm || !index) { + if (term === currentTerm) { return; } $searchResults.style.display = term === "" ? "none" : "block"; @@ -156,7 +169,7 @@ function initSearch() { return; } - var results = index.search(term, options); + var results = (await initIndex()).search(term, options); if (results.length === 0) { $searchResults.style.display = "none"; return; diff --git a/docs/templates/index.html b/docs/templates/index.html index 2efb0373b4..de9134f306 100644 --- a/docs/templates/index.html +++ b/docs/templates/index.html @@ -103,7 +103,6 @@