From 8cd7061ff28e6fd8d8588a63b8d7a64f060fdfca Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Wed, 13 Jun 2018 13:11:25 -0500 Subject: [PATCH 1/8] Add search.enable config field --- book-example/src/format/config.md | 2 ++ src/config.rs | 5 ++++- src/renderer/html_handlebars/hbs_renderer.rs | 13 +++++++------ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/book-example/src/format/config.md b/book-example/src/format/config.md index 96da0e74..4c65f553 100644 --- a/book-example/src/format/config.md +++ b/book-example/src/format/config.md @@ -113,6 +113,7 @@ Available configuration options for the `[output.html.playpen]` table: Available configuration options for the `[output.html.search]` table: +- **enable:** Enables the search feature. Defaults to `true`. - **limit-results:** The maximum number of search results. Defaults to `30`. - **teaser-word-count:** The number of words used for a search result teaser. Defaults to `30`. @@ -168,6 +169,7 @@ boost-hierarchy = 1 boost-paragraph = 1 expand = true heading-split-level = 3 +copy-js = true ``` diff --git a/src/config.rs b/src/config.rs index 898ec6b7..2e0ec51a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -463,9 +463,11 @@ impl Default for Playpen { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(default, rename_all = "kebab-case")] pub struct Search { + /// Enable the search feature. Default: `true`. + pub enable: bool, /// Maximum number of visible results. Default: `30`. pub limit_results: u32, - /// The number of words used for a search result teaser. Default: `30`, + /// The number of words used for a search result teaser. Default: `30`. pub teaser_word_count: u32, /// Define the logical link between multiple search words. /// If true, all search words must appear in each result. Default: `true`. @@ -494,6 +496,7 @@ impl Default for Search { fn default() -> Search { // Please update the documentation of `Search` when changing values! Search { + enable: true, limit_results: 30, teaser_word_count: 30, use_boolean_and: false, diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 4fad1eef..52e58f81 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -367,8 +367,10 @@ impl Renderer for HtmlHandlebars { .chain_err(|| "Unable to copy across additional CSS and JS")?; // Render search index - #[cfg(feature = "search")] - super::search::create_files(&html_config.search.unwrap_or_default(), &destination, &book)?; + let search = html_config.search.unwrap_or_default(); + if cfg!(feature = "search") && search.enable { + super::search::create_files(&search, &destination, &book)?; + } // Copy all remaining files utils::fs::copy_files_except_ext(&src_dir, &destination, true, &["md"])?; @@ -446,10 +448,9 @@ fn make_data( let search = html_config.search.clone(); if cfg!(feature = "search") { - data.insert("search_enabled".to_owned(), json!(true)); - if search.unwrap_or_default().copy_js { - data.insert("search_js".to_owned(), json!(true)); - } + let search = search.unwrap_or_default(); + data.insert("search_enabled".to_owned(), json!(search.enable)); + data.insert("search_js".to_owned(), json!(search.copy_js)); } else if search.is_some() { warn!("mdBook compiled without search support, ignoring `output.html.search` table"); warn!( From 019e74041d00e7bb6c788c672077cea0be475c8c Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Wed, 13 Jun 2018 14:09:31 -0500 Subject: [PATCH 2/8] Use integer doc_refs to shrink the search index This change reduced the searchindex.js of book_example from 508KB to 317KB. --- src/renderer/html_handlebars/search.rs | 41 ++++++++++++++++---------- src/theme/searcher/searcher.js | 18 ++++++----- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/renderer/html_handlebars/search.rs b/src/renderer/html_handlebars/search.rs index 1ee66a51..a6f9a89d 100644 --- a/src/renderer/html_handlebars/search.rs +++ b/src/renderer/html_handlebars/search.rs @@ -18,12 +18,13 @@ use theme::searcher; /// Creates all files required for search. pub fn create_files(search_config: &Search, destination: &Path, book: &Book) -> Result<()> { let mut index = Index::new(&["title", "body", "breadcrumbs"]); + let mut doc_urls = Vec::with_capacity(book.sections.len()); for item in book.iter() { - render_item(&mut index, &search_config, item)?; + render_item(&mut index, &search_config, &mut doc_urls, item)?; } - let index = write_to_js(index, &search_config)?; + let index = write_to_js(index, &search_config, doc_urls)?; debug!("Writing search index ✓"); if search_config.copy_js { @@ -38,26 +39,31 @@ pub fn create_files(search_config: &Search, destination: &Path, book: &Book) -> } /// Uses the given arguments to construct a search document, then inserts it to the given index. -fn add_doc<'a>( +fn add_doc( index: &mut Index, - anchor_base: &'a str, + doc_urls: &mut Vec, + anchor_base: &str, section_id: &Option, items: &[&str], ) { - let doc_ref: Cow<'a, str> = if let &Some(ref id) = section_id { - format!("{}#{}", anchor_base, id).into() + let doc_ref = if let &Some(ref id) = section_id { + Cow::Owned(format!("{}#{}", anchor_base, id)) } else { - anchor_base.into() + Cow::Borrowed(anchor_base.into()) }; let doc_ref = utils::collapse_whitespace(doc_ref.trim()); + let key = doc_urls.len(); + doc_urls.push(doc_ref.into()); + let items = items.iter().map(|&x| utils::collapse_whitespace(x.trim())); - index.add_doc(&doc_ref, items); + index.add_doc(&key.to_string(), items); } /// Renders markdown into flat unformatted text and adds it to the search index. fn render_item( index: &mut Index, search_config: &Search, + doc_urls: &mut Vec, item: &BookItem, ) -> Result<()> { let chapter = match item { @@ -92,6 +98,7 @@ fn render_item( // Write the data to the index, and clear it for the next section add_doc( index, + doc_urls, &anchor_base, §ion_id, &[&heading, &body, &breadcrumbs.join(" » ")], @@ -144,6 +151,7 @@ fn render_item( // Make sure the last section is added to the index add_doc( index, + doc_urls, &anchor_base, §ion_id, &[&heading, &body, &breadcrumbs.join(" » ")], @@ -156,7 +164,7 @@ fn render_item( /// Exports the index and search options to a JS script which stores the index in `window.search`. /// Using a JS script is a workaround for CORS in `file://` URIs. It also removes the need for /// downloading/parsing JSON in JS. -fn write_to_js(index: Index, search_config: &Search) -> Result { +fn write_to_js(index: Index, search_config: &Search, doc_urls: Vec) -> Result { use std::collections::BTreeMap; use self::elasticlunr::config::{SearchBool, SearchOptions, SearchOptionsField}; @@ -169,9 +177,11 @@ fn write_to_js(index: Index, search_config: &Search) -> Result { #[derive(Serialize)] struct SearchindexJson { /// The options used for displaying search results - resultsoptions: ResultsOptions, + results_options: ResultsOptions, /// The searchoptions for elasticlunr.js - searchoptions: SearchOptions, + search_options: SearchOptions, + /// Used to lookup a document's URL from an integer document ref. + doc_urls: Vec, /// The index for elasticlunr.js index: elasticlunr::Index, } @@ -185,7 +195,7 @@ fn write_to_js(index: Index, search_config: &Search) -> Result { opt.boost = Some(search_config.boost_hierarchy); fields.insert("breadcrumbs".into(), opt); - let searchoptions = SearchOptions { + let search_options = SearchOptions { bool: if search_config.use_boolean_and { SearchBool::And } else { @@ -195,14 +205,15 @@ fn write_to_js(index: Index, search_config: &Search) -> Result { fields, }; - let resultsoptions = ResultsOptions { + let results_options = ResultsOptions { limit_results: search_config.limit_results, teaser_word_count: search_config.teaser_word_count, }; let json_contents = SearchindexJson { - resultsoptions, - searchoptions, + results_options, + search_options, + doc_urls, index, }; diff --git a/src/theme/searcher/searcher.js b/src/theme/searcher/searcher.js index 32080bcd..85c890ae 100644 --- a/src/theme/searcher/searcher.js +++ b/src/theme/searcher/searcher.js @@ -27,11 +27,12 @@ window.search = window.search || {}; content = document.getElementById('content'), searchindex = null, - resultsoptions = { + doc_urls = [], + results_options = { teaser_word_count: 30, limit_results: 30, }, - searchoptions = { + search_options = { bool: "AND", expand: true, fields: { @@ -139,7 +140,7 @@ window.search = window.search || {}; teaser_count++; // The ?URL_MARK_PARAM= parameter belongs inbetween the page and the #heading-anchor - var url = result.ref.split("#"); + var url = doc_urls[result.ref].split("#"); if (url.length == 1) { // no anchor found url.push(""); } @@ -196,7 +197,7 @@ window.search = window.search || {}; } var window_weight = []; - var window_size = Math.min(weighted.length, resultsoptions.teaser_word_count); + var window_size = Math.min(weighted.length, results_options.teaser_word_count); var cur_sum = 0; for (var wordindex = 0; wordindex < window_size; wordindex++) { @@ -247,9 +248,10 @@ window.search = window.search || {}; } function init() { - resultsoptions = window.search.resultsoptions; - searchoptions = window.search.searchoptions; + results_options = window.search.results_options; + search_options = window.search.search_options; searchbar_outer = window.search.searchbar_outer; + doc_urls = window.search.doc_urls; searchindex = elasticlunr.Index.load(window.search.index); // Set up events @@ -441,8 +443,8 @@ window.search = window.search || {}; if (searchindex == null) { return; } // Do the actual search - var results = searchindex.search(searchterm, searchoptions); - var resultcount = Math.min(results.length, resultsoptions.limit_results); + var results = searchindex.search(searchterm, search_options); + var resultcount = Math.min(results.length, results_options.limit_results); // Display search metrics searchresults_header.innerText = formatSearchMetric(resultcount, searchterm); From b8011de3e819cf1b50c5ad7a2f5e51d94cdceb2a Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Wed, 13 Jun 2018 14:15:27 -0500 Subject: [PATCH 3/8] Warn when search index is >10MB --- src/renderer/html_handlebars/search.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/renderer/html_handlebars/search.rs b/src/renderer/html_handlebars/search.rs index a6f9a89d..310d8f09 100644 --- a/src/renderer/html_handlebars/search.rs +++ b/src/renderer/html_handlebars/search.rs @@ -26,6 +26,9 @@ pub fn create_files(search_config: &Search, destination: &Path, book: &Book) -> let index = write_to_js(index, &search_config, doc_urls)?; debug!("Writing search index ✓"); + if index.len() > 10_000_000 { + warn!("searchindex.js is very large ({} bytes)", index.len()); + } if search_config.copy_js { utils::fs::write_file(destination, "searchindex.js", index.as_bytes())?; From 62c83113014624680a3b80a43992aebcb0f52086 Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Wed, 13 Jun 2018 14:18:47 -0500 Subject: [PATCH 4/8] Don't copy search js when disabled --- src/renderer/html_handlebars/hbs_renderer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/html_handlebars/hbs_renderer.rs b/src/renderer/html_handlebars/hbs_renderer.rs index 52e58f81..45cb052a 100644 --- a/src/renderer/html_handlebars/hbs_renderer.rs +++ b/src/renderer/html_handlebars/hbs_renderer.rs @@ -450,7 +450,7 @@ fn make_data( if cfg!(feature = "search") { let search = search.unwrap_or_default(); data.insert("search_enabled".to_owned(), json!(search.enable)); - data.insert("search_js".to_owned(), json!(search.copy_js)); + data.insert("search_js".to_owned(), json!(search.enable && search.copy_js)); } else if search.is_some() { warn!("mdBook compiled without search support, ignoring `output.html.search` table"); warn!( From e1a46d213e69ca194bf57c9bcacc912ab9c16f42 Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Wed, 13 Jun 2018 14:51:15 -0500 Subject: [PATCH 5/8] Use JSON search index with JS fallback This allows the search index to be loaded asynchronously, and should use fewer resources as it doesn't have to execute the JS. JS loading is kept as a fallback for CORS issues with file:// URIs in Chrome. --- src/renderer/html_handlebars/search.rs | 14 ++++++-------- src/theme/searcher/searcher.js | 23 ++++++++++++++++------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/renderer/html_handlebars/search.rs b/src/renderer/html_handlebars/search.rs index 310d8f09..20a17cfc 100644 --- a/src/renderer/html_handlebars/search.rs +++ b/src/renderer/html_handlebars/search.rs @@ -24,14 +24,15 @@ pub fn create_files(search_config: &Search, destination: &Path, book: &Book) -> render_item(&mut index, &search_config, &mut doc_urls, item)?; } - let index = write_to_js(index, &search_config, doc_urls)?; + let index = write_to_json(index, &search_config, doc_urls)?; debug!("Writing search index ✓"); if index.len() > 10_000_000 { - warn!("searchindex.js is very large ({} bytes)", index.len()); + warn!("searchindex.json is very large ({} bytes)", index.len()); } if search_config.copy_js { - utils::fs::write_file(destination, "searchindex.js", index.as_bytes())?; + utils::fs::write_file(destination, "searchindex.json", index.as_bytes())?; + utils::fs::write_file(destination, "searchindex.js", format!("window.search = {};", index).as_bytes())?; utils::fs::write_file(destination, "searcher.js", searcher::JS)?; utils::fs::write_file(destination, "mark.min.js", searcher::MARK_JS)?; utils::fs::write_file(destination, "elasticlunr.min.js", searcher::ELASTICLUNR_JS)?; @@ -164,10 +165,7 @@ fn render_item( Ok(()) } -/// Exports the index and search options to a JS script which stores the index in `window.search`. -/// Using a JS script is a workaround for CORS in `file://` URIs. It also removes the need for -/// downloading/parsing JSON in JS. -fn write_to_js(index: Index, search_config: &Search, doc_urls: Vec) -> Result { +fn write_to_json(index: Index, search_config: &Search, doc_urls: Vec) -> Result { use std::collections::BTreeMap; use self::elasticlunr::config::{SearchBool, SearchOptions, SearchOptionsField}; @@ -225,7 +223,7 @@ fn write_to_js(index: Index, search_config: &Search, doc_urls: Vec) -> R let json_contents = serde_json::to_value(&json_contents)?; let json_contents = serde_json::to_string(&json_contents)?; - Ok(format!("window.search = {};", json_contents)) + Ok(json_contents) } fn clean_html(html: &str) -> String { diff --git a/src/theme/searcher/searcher.js b/src/theme/searcher/searcher.js index 85c890ae..82041c66 100644 --- a/src/theme/searcher/searcher.js +++ b/src/theme/searcher/searcher.js @@ -247,12 +247,12 @@ window.search = window.search || {}; return teaser_split.join(''); } - function init() { - results_options = window.search.results_options; - search_options = window.search.search_options; - searchbar_outer = window.search.searchbar_outer; - doc_urls = window.search.doc_urls; - searchindex = elasticlunr.Index.load(window.search.index); + function init(config) { + results_options = config.results_options; + search_options = config.search_options; + searchbar_outer = config.searchbar_outer; + doc_urls = config.doc_urls; + searchindex = elasticlunr.Index.load(config.index); // Set up events searchicon.addEventListener('click', function(e) { searchIconClickHandler(); }, false); @@ -462,7 +462,16 @@ window.search = window.search || {}; showResults(true); } - init(); + fetch('searchindex.json') + .then(response => response.json()) + .then(json => init(json)) + .catch(error => { // Try to load searchindex.js if fetch failed + var script = document.createElement('script'); + script.src = 'searchindex.js'; + script.onload = () => init(window.search); + document.head.appendChild(script); + }); + // Exported functions search.hasFocus = hasFocus; })(window.search); From e94078cc9cefd7798f6b37d76b4af0622a702ccb Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Wed, 13 Jun 2018 15:15:58 -0500 Subject: [PATCH 6/8] Fix tests --- tests/rendered_output.rs | 32 ++- tests/searchindex_fixture.json | 427 +++++++++++++++++---------------- 2 files changed, 242 insertions(+), 217 deletions(-) diff --git a/tests/rendered_output.rs b/tests/rendered_output.rs index a6549ed0..16abcdac 100644 --- a/tests/rendered_output.rs +++ b/tests/rendered_output.rs @@ -426,25 +426,39 @@ mod search { let index = read_book_index(temp.path()); + let doc_urls = index["doc_urls"].as_array().unwrap(); + let get_doc_ref = |url: &str| -> String { + doc_urls.iter() + .position(|s| s == url) + .unwrap() + .to_string() + }; + + let first_chapter = get_doc_ref("first/index.html#first-chapter"); + let introduction = get_doc_ref("intro.html#introduction"); + let some_section = get_doc_ref("first/index.html#some-section"); + let summary = get_doc_ref("first/includes.html#summary"); + let conclusion = get_doc_ref("conclusion.html#conclusion"); + let bodyidx = &index["index"]["index"]["body"]["root"]; let textidx = &bodyidx["t"]["e"]["x"]["t"]; assert_eq!(textidx["df"], 2); - assert_eq!(textidx["docs"]["first/index.html#first-chapter"]["tf"], 1.0); - assert_eq!(textidx["docs"]["intro.html#introduction"]["tf"], 1.0); + assert_eq!(textidx["docs"][&first_chapter]["tf"], 1.0); + assert_eq!(textidx["docs"][&introduction]["tf"], 1.0); let docs = &index["index"]["documentStore"]["docs"]; - assert_eq!(docs["first/index.html#first-chapter"]["body"], "more text."); - assert_eq!(docs["first/index.html#some-section"]["body"], ""); + assert_eq!(docs[&first_chapter]["body"], "more text."); + assert_eq!(docs[&some_section]["body"], ""); assert_eq!( - docs["first/includes.html#summary"]["body"], + docs[&summary]["body"], "Introduction First Chapter Nested Chapter Includes Recursive Second Chapter Conclusion" ); assert_eq!( - docs["first/includes.html#summary"]["breadcrumbs"], + docs[&summary]["breadcrumbs"], "First Chapter » Summary" ); assert_eq!( - docs["conclusion.html#conclusion"]["body"], + docs[&conclusion]["body"], "I put <HTML> in here!" ); } @@ -452,7 +466,7 @@ mod search { // Setting this to `true` may cause issues with `cargo watch`, // since it may not finish writing the fixture before the tests // are run again. - const GENERATE_FIXTURE: bool = true; + const GENERATE_FIXTURE: bool = false; fn get_fixture() -> serde_json::Value { if GENERATE_FIXTURE { @@ -481,7 +495,7 @@ mod search { // // If you're pretty sure you haven't broken anything, change `GENERATE_FIXTURE` // above to `true`, and run `cargo test` to generate a new fixture. Then - // change it back to `false`. Include the changed `searchindex_fixture.json` in your commit. + // **change it back to `false`**. Include the changed `searchindex_fixture.json` in your commit. #[test] fn search_index_hasnt_changed_accidentally() { let temp = DummyBook::new().build().unwrap(); diff --git a/tests/searchindex_fixture.json b/tests/searchindex_fixture.json index aa9493bd..8e2f082e 100644 --- a/tests/searchindex_fixture.json +++ b/tests/searchindex_fixture.json @@ -1,107 +1,118 @@ { + "doc_urls": [ + "intro.html#introduction", + "first/index.html#first-chapter", + "first/index.html#some-section", + "first/nested.html#nested-chapter", + "first/nested.html#some-section", + "first/includes.html#includes", + "first/includes.html#summary", + "second.html#second-chapter", + "conclusion.html#conclusion" + ], "index": { "documentStore": { "docInfo": { - "conclusion.html#conclusion": { + "0": { "body": 3, "breadcrumbs": 1, "title": 1 }, - "first/includes.html#includes": { - "body": 0, - "breadcrumbs": 3, - "title": 1 - }, - "first/includes.html#summary": { - "body": 10, - "breadcrumbs": 3, - "title": 1 - }, - "first/index.html#first-chapter": { + "1": { "body": 2, "breadcrumbs": 2, "title": 2 }, - "first/index.html#some-section": { + "2": { "body": 0, "breadcrumbs": 1, "title": 1 }, - "first/nested.html#nested-chapter": { + "3": { "body": 4, "breadcrumbs": 4, "title": 2 }, - "first/nested.html#some-section": { + "4": { "body": 0, "breadcrumbs": 3, "title": 1 }, - "intro.html#introduction": { - "body": 3, - "breadcrumbs": 1, + "5": { + "body": 0, + "breadcrumbs": 3, "title": 1 }, - "second.html#second-chapter": { + "6": { + "body": 10, + "breadcrumbs": 3, + "title": 1 + }, + "7": { "body": 20, "breadcrumbs": 2, "title": 2 + }, + "8": { + "body": 3, + "breadcrumbs": 1, + "title": 1 } }, "docs": { - "conclusion.html#conclusion": { - "body": "I put <HTML> in here!", - "breadcrumbs": "Conclusion", - "id": "conclusion.html#conclusion", - "title": "Conclusion" - }, - "first/includes.html#includes": { - "body": "", - "breadcrumbs": "First Chapter » Includes", - "id": "first/includes.html#includes", - "title": "Includes" - }, - "first/includes.html#summary": { - "body": "Introduction First Chapter Nested Chapter Includes Recursive Second Chapter Conclusion", - "breadcrumbs": "First Chapter » Summary", - "id": "first/includes.html#summary", - "title": "Summary" - }, - "first/index.html#first-chapter": { - "body": "more text.", - "breadcrumbs": "First Chapter", - "id": "first/index.html#first-chapter", - "title": "First Chapter" - }, - "first/index.html#some-section": { - "body": "", - "breadcrumbs": "Some Section", - "id": "first/index.html#some-section", - "title": "Some Section" - }, - "first/nested.html#nested-chapter": { - "body": "This file has some testable code. assert!(true);", - "breadcrumbs": "First Chapter » Nested Chapter", - "id": "first/nested.html#nested-chapter", - "title": "Nested Chapter" - }, - "first/nested.html#some-section": { - "body": "", - "breadcrumbs": "First Chapter » Some Section", - "id": "first/nested.html#some-section", - "title": "Some Section" - }, - "intro.html#introduction": { + "0": { "body": "Here's some interesting text...", "breadcrumbs": "Introduction", - "id": "intro.html#introduction", + "id": "0", "title": "Introduction" }, - "second.html#second-chapter": { + "1": { + "body": "more text.", + "breadcrumbs": "First Chapter", + "id": "1", + "title": "First Chapter" + }, + "2": { + "body": "", + "breadcrumbs": "Some Section", + "id": "2", + "title": "Some Section" + }, + "3": { + "body": "This file has some testable code. assert!(true);", + "breadcrumbs": "First Chapter » Nested Chapter", + "id": "3", + "title": "Nested Chapter" + }, + "4": { + "body": "", + "breadcrumbs": "First Chapter » Some Section", + "id": "4", + "title": "Some Section" + }, + "5": { + "body": "", + "breadcrumbs": "First Chapter » Includes", + "id": "5", + "title": "Includes" + }, + "6": { + "body": "Introduction First Chapter Nested Chapter Includes Recursive Second Chapter Conclusion", + "breadcrumbs": "First Chapter » Summary", + "id": "6", + "title": "Summary" + }, + "7": { "body": "This makes sure you can insert runnable Rust files. fn main() { println!(\"Hello World!\");\n#\n# // You can even hide lines! :D\n# println!(\"I am hidden! Expand the code snippet to see me\");\n}", "breadcrumbs": "Second Chapter", - "id": "second.html#second-chapter", + "id": "7", "title": "Second Chapter" + }, + "8": { + "body": "I put <HTML> in here!", + "breadcrumbs": "Conclusion", + "id": "8", + "title": "Conclusion" } }, "length": 9, @@ -144,7 +155,7 @@ "u": { "df": 1, "docs": { - "first/nested.html#nested-chapter": { + "3": { "tf": 1.0 } } @@ -182,16 +193,16 @@ "r": { "df": 4, "docs": { - "first/includes.html#summary": { + "1": { + "tf": 1.0 + }, + "3": { + "tf": 1.0 + }, + "6": { "tf": 1.7320508075688773 }, - "first/index.html#first-chapter": { - "tf": 1.0 - }, - "first/nested.html#nested-chapter": { - "tf": 1.0 - }, - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -210,10 +221,10 @@ "e": { "df": 2, "docs": { - "first/nested.html#nested-chapter": { + "3": { "tf": 1.0 }, - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -234,10 +245,10 @@ "s": { "df": 2, "docs": { - "conclusion.html#conclusion": { + "6": { "tf": 1.0 }, - "first/includes.html#summary": { + "8": { "tf": 1.0 } } @@ -253,7 +264,7 @@ "d": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -272,7 +283,7 @@ "n": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -290,7 +301,7 @@ "d": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -316,10 +327,10 @@ "e": { "df": 2, "docs": { - "first/nested.html#nested-chapter": { + "3": { "tf": 1.0 }, - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -334,10 +345,10 @@ "t": { "df": 2, "docs": { - "first/includes.html#summary": { + "1": { "tf": 1.0 }, - "first/index.html#first-chapter": { + "6": { "tf": 1.0 } } @@ -348,7 +359,7 @@ "n": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -367,14 +378,14 @@ "'": { "df": 1, "docs": { - "intro.html#introduction": { + "0": { "tf": 1.0 } } }, "df": 1, "docs": { - "conclusion.html#conclusion": { + "8": { "tf": 1.0 } } @@ -392,7 +403,7 @@ "n": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -404,7 +415,7 @@ "e": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -428,10 +439,10 @@ "d": { "df": 2, "docs": { - "first/includes.html#includes": { + "5": { "tf": 1.0 }, - "first/includes.html#summary": { + "6": { "tf": 1.0 } } @@ -455,7 +466,7 @@ "t": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -481,7 +492,7 @@ "t": { "df": 1, "docs": { - "intro.html#introduction": { + "0": { "tf": 1.0 } } @@ -504,10 +515,10 @@ "t": { "df": 2, "docs": { - "first/includes.html#summary": { + "0": { "tf": 1.0 }, - "intro.html#introduction": { + "6": { "tf": 1.0 } } @@ -536,7 +547,7 @@ "e": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -566,7 +577,7 @@ "t": { "df": 1, "docs": { - "conclusion.html#conclusion": { + "8": { "tf": 1.0 } } @@ -594,7 +605,7 @@ "n": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -606,7 +617,7 @@ "e": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -624,7 +635,7 @@ "e": { "df": 1, "docs": { - "first/index.html#first-chapter": { + "1": { "tf": 1.0 } } @@ -644,10 +655,10 @@ "t": { "df": 2, "docs": { - "first/includes.html#summary": { + "3": { "tf": 1.0 }, - "first/nested.html#nested-chapter": { + "6": { "tf": 1.0 } } @@ -694,7 +705,7 @@ "o": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -706,7 +717,7 @@ "i": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -732,7 +743,7 @@ "t": { "df": 1, "docs": { - "conclusion.html#conclusion": { + "8": { "tf": 1.0 } } @@ -755,7 +766,7 @@ "s": { "df": 1, "docs": { - "first/includes.html#summary": { + "6": { "tf": 1.0 } } @@ -780,7 +791,7 @@ "l": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -799,7 +810,7 @@ "t": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -821,10 +832,10 @@ "d": { "df": 2, "docs": { - "first/includes.html#summary": { + "6": { "tf": 1.0 }, - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -845,10 +856,10 @@ "n": { "df": 2, "docs": { - "first/index.html#some-section": { + "2": { "tf": 1.0 }, - "first/nested.html#some-section": { + "4": { "tf": 1.0 } } @@ -862,7 +873,7 @@ "e": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -886,7 +897,7 @@ "t": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -912,7 +923,7 @@ "i": { "df": 1, "docs": { - "first/includes.html#summary": { + "6": { "tf": 1.0 } } @@ -929,7 +940,7 @@ "e": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -954,7 +965,7 @@ "l": { "df": 1, "docs": { - "first/nested.html#nested-chapter": { + "3": { "tf": 1.0 } } @@ -973,10 +984,10 @@ "t": { "df": 2, "docs": { - "first/index.html#first-chapter": { + "0": { "tf": 1.0 }, - "intro.html#introduction": { + "1": { "tf": 1.0 } } @@ -997,7 +1008,7 @@ "d": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1041,7 +1052,7 @@ "u": { "df": 1, "docs": { - "first/nested.html#nested-chapter": { + "3": { "tf": 1.0 } } @@ -1079,22 +1090,22 @@ "r": { "df": 6, "docs": { - "first/includes.html#includes": { - "tf": 1.0 - }, - "first/includes.html#summary": { - "tf": 2.0 - }, - "first/index.html#first-chapter": { + "1": { "tf": 1.4142135623730952 }, - "first/nested.html#nested-chapter": { + "3": { "tf": 1.7320508075688773 }, - "first/nested.html#some-section": { + "4": { "tf": 1.0 }, - "second.html#second-chapter": { + "5": { + "tf": 1.0 + }, + "6": { + "tf": 2.0 + }, + "7": { "tf": 1.4142135623730952 } } @@ -1113,10 +1124,10 @@ "e": { "df": 2, "docs": { - "first/nested.html#nested-chapter": { + "3": { "tf": 1.0 }, - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1137,11 +1148,11 @@ "s": { "df": 2, "docs": { - "conclusion.html#conclusion": { - "tf": 1.4142135623730952 - }, - "first/includes.html#summary": { + "6": { "tf": 1.0 + }, + "8": { + "tf": 1.4142135623730952 } } } @@ -1156,7 +1167,7 @@ "d": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1175,7 +1186,7 @@ "n": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1193,7 +1204,7 @@ "d": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1219,10 +1230,10 @@ "e": { "df": 2, "docs": { - "first/nested.html#nested-chapter": { + "3": { "tf": 1.0 }, - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1237,20 +1248,20 @@ "t": { "df": 5, "docs": { - "first/includes.html#includes": { - "tf": 1.0 - }, - "first/includes.html#summary": { + "1": { "tf": 1.4142135623730952 }, - "first/index.html#first-chapter": { + "3": { + "tf": 1.0 + }, + "4": { + "tf": 1.0 + }, + "5": { + "tf": 1.0 + }, + "6": { "tf": 1.4142135623730952 - }, - "first/nested.html#nested-chapter": { - "tf": 1.0 - }, - "first/nested.html#some-section": { - "tf": 1.0 } } } @@ -1260,7 +1271,7 @@ "n": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1279,14 +1290,14 @@ "'": { "df": 1, "docs": { - "intro.html#introduction": { + "0": { "tf": 1.0 } } }, "df": 1, "docs": { - "conclusion.html#conclusion": { + "8": { "tf": 1.0 } } @@ -1304,7 +1315,7 @@ "n": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1316,7 +1327,7 @@ "e": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1340,10 +1351,10 @@ "d": { "df": 2, "docs": { - "first/includes.html#includes": { + "5": { "tf": 1.4142135623730952 }, - "first/includes.html#summary": { + "6": { "tf": 1.0 } } @@ -1367,7 +1378,7 @@ "t": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1393,7 +1404,7 @@ "t": { "df": 1, "docs": { - "intro.html#introduction": { + "0": { "tf": 1.0 } } @@ -1416,11 +1427,11 @@ "t": { "df": 2, "docs": { - "first/includes.html#summary": { - "tf": 1.0 - }, - "intro.html#introduction": { + "0": { "tf": 1.4142135623730952 + }, + "6": { + "tf": 1.0 } } } @@ -1448,7 +1459,7 @@ "e": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1478,7 +1489,7 @@ "t": { "df": 1, "docs": { - "conclusion.html#conclusion": { + "8": { "tf": 1.0 } } @@ -1506,7 +1517,7 @@ "n": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1518,7 +1529,7 @@ "e": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1536,7 +1547,7 @@ "e": { "df": 1, "docs": { - "first/index.html#first-chapter": { + "1": { "tf": 1.0 } } @@ -1556,11 +1567,11 @@ "t": { "df": 2, "docs": { - "first/includes.html#summary": { - "tf": 1.0 - }, - "first/nested.html#nested-chapter": { + "3": { "tf": 1.4142135623730952 + }, + "6": { + "tf": 1.0 } } } @@ -1606,7 +1617,7 @@ "o": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1618,7 +1629,7 @@ "i": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1644,7 +1655,7 @@ "t": { "df": 1, "docs": { - "conclusion.html#conclusion": { + "8": { "tf": 1.0 } } @@ -1667,7 +1678,7 @@ "s": { "df": 1, "docs": { - "first/includes.html#summary": { + "6": { "tf": 1.0 } } @@ -1692,7 +1703,7 @@ "l": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1711,7 +1722,7 @@ "t": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1733,10 +1744,10 @@ "d": { "df": 2, "docs": { - "first/includes.html#summary": { + "6": { "tf": 1.0 }, - "second.html#second-chapter": { + "7": { "tf": 1.4142135623730952 } } @@ -1757,10 +1768,10 @@ "n": { "df": 2, "docs": { - "first/index.html#some-section": { + "2": { "tf": 1.4142135623730952 }, - "first/nested.html#some-section": { + "4": { "tf": 1.4142135623730952 } } @@ -1774,7 +1785,7 @@ "e": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1798,7 +1809,7 @@ "t": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1824,7 +1835,7 @@ "i": { "df": 1, "docs": { - "first/includes.html#summary": { + "6": { "tf": 1.4142135623730952 } } @@ -1841,7 +1852,7 @@ "e": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1866,7 +1877,7 @@ "l": { "df": 1, "docs": { - "first/nested.html#nested-chapter": { + "3": { "tf": 1.0 } } @@ -1885,10 +1896,10 @@ "t": { "df": 2, "docs": { - "first/index.html#first-chapter": { + "0": { "tf": 1.0 }, - "intro.html#introduction": { + "1": { "tf": 1.0 } } @@ -1909,7 +1920,7 @@ "d": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1943,13 +1954,13 @@ "r": { "df": 3, "docs": { - "first/index.html#first-chapter": { + "1": { "tf": 1.0 }, - "first/nested.html#nested-chapter": { + "3": { "tf": 1.0 }, - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -1977,7 +1988,7 @@ "s": { "df": 1, "docs": { - "conclusion.html#conclusion": { + "8": { "tf": 1.0 } } @@ -2007,7 +2018,7 @@ "t": { "df": 1, "docs": { - "first/index.html#first-chapter": { + "1": { "tf": 1.0 } } @@ -2030,7 +2041,7 @@ "d": { "df": 1, "docs": { - "first/includes.html#includes": { + "5": { "tf": 1.0 } } @@ -2059,7 +2070,7 @@ "t": { "df": 1, "docs": { - "intro.html#introduction": { + "0": { "tf": 1.0 } } @@ -2088,7 +2099,7 @@ "t": { "df": 1, "docs": { - "first/nested.html#nested-chapter": { + "3": { "tf": 1.0 } } @@ -2110,7 +2121,7 @@ "d": { "df": 1, "docs": { - "second.html#second-chapter": { + "7": { "tf": 1.0 } } @@ -2131,10 +2142,10 @@ "n": { "df": 2, "docs": { - "first/index.html#some-section": { + "2": { "tf": 1.0 }, - "first/nested.html#some-section": { + "4": { "tf": 1.0 } } @@ -2162,7 +2173,7 @@ "i": { "df": 1, "docs": { - "first/includes.html#summary": { + "6": { "tf": 1.0 } } @@ -2186,11 +2197,11 @@ "ref": "id", "version": "0.9.5" }, - "resultsoptions": { + "results_options": { "limit_results": 30, "teaser_word_count": 30 }, - "searchoptions": { + "search_options": { "bool": "OR", "expand": true, "fields": { From 384582aebafcbe9639438a5de845ca655a00c165 Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Wed, 13 Jun 2018 15:22:41 -0500 Subject: [PATCH 7/8] Cleanup add_doc --- src/renderer/html_handlebars/search.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/renderer/html_handlebars/search.rs b/src/renderer/html_handlebars/search.rs index 20a17cfc..325e73fb 100644 --- a/src/renderer/html_handlebars/search.rs +++ b/src/renderer/html_handlebars/search.rs @@ -50,17 +50,17 @@ fn add_doc( section_id: &Option, items: &[&str], ) { - let doc_ref = if let &Some(ref id) = section_id { + let url = if let &Some(ref id) = section_id { Cow::Owned(format!("{}#{}", anchor_base, id)) } else { - Cow::Borrowed(anchor_base.into()) + Cow::Borrowed(anchor_base) }; - let doc_ref = utils::collapse_whitespace(doc_ref.trim()); - let key = doc_urls.len(); - doc_urls.push(doc_ref.into()); + let url = utils::collapse_whitespace(url.trim()); + let doc_ref = doc_urls.len().to_string(); + doc_urls.push(url.into()); let items = items.iter().map(|&x| utils::collapse_whitespace(x.trim())); - index.add_doc(&key.to_string(), items); + index.add_doc(&doc_ref, items); } /// Renders markdown into flat unformatted text and adds it to the search index. From d9dbba49ea960785ba25c085fd5a4469832566b0 Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Mon, 23 Jul 2018 12:19:59 -0500 Subject: [PATCH 8/8] Fix for relative paths --- src/theme/searcher/searcher.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/theme/searcher/searcher.js b/src/theme/searcher/searcher.js index 82041c66..7fd97d48 100644 --- a/src/theme/searcher/searcher.js +++ b/src/theme/searcher/searcher.js @@ -462,12 +462,12 @@ window.search = window.search || {}; showResults(true); } - fetch('searchindex.json') + fetch(path_to_root + 'searchindex.json') .then(response => response.json()) .then(json => init(json)) .catch(error => { // Try to load searchindex.js if fetch failed var script = document.createElement('script'); - script.src = 'searchindex.js'; + script.src = path_to_root + 'searchindex.js'; script.onload = () => init(window.search); document.head.appendChild(script); });