diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index e5a686bd07d07..855934ef4d430 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -58,6 +58,7 @@ crate fn render( {style_files}\ \ \ + \ \ {css_extension}\ {favicon}\ @@ -112,10 +113,10 @@ crate fn render(
\
\ {after_content}\ -
+
\ {extra_scripts}\ - \ \ ", css_extension = if layout.css_file_extension.is_some() { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 58e9e41e6a53c..dd531f1510220 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1039,10 +1039,12 @@ themePicker.onblur = handleThemeButtonsBlur; cx.shared.fs.write(&dst, v.as_bytes())?; } - // Update the search index + // Update the search index and crate list. let dst = cx.dst.join(&format!("search-index{}.js", cx.shared.resource_suffix)); let (mut all_indexes, mut krates) = try_err!(collect_json(&dst, &krate.name.as_str()), &dst); all_indexes.push(search_index); + krates.push(krate.name.to_string()); + krates.sort(); // Sort the indexes by crate so the file will be generated identically even // with rustdoc running in parallel. @@ -1050,11 +1052,15 @@ themePicker.onblur = handleThemeButtonsBlur; { let mut v = String::from("var searchIndex = JSON.parse('{\\\n"); v.push_str(&all_indexes.join(",\\\n")); - // "addSearchOptions" has to be called first so the crate filtering can be set before the - // search might start (if it's set into the URL for example). - v.push_str("\\\n}');\naddSearchOptions(searchIndex);initSearch(searchIndex);"); + v.push_str("\\\n}');\ninitSearch(searchIndex);"); cx.shared.fs.write(&dst, &v)?; } + + let crate_list_dst = cx.dst.join(&format!("crates{}.js", cx.shared.resource_suffix)); + let crate_list = + format!("window.ALL_CRATES = [{}];", krates.iter().map(|k| format!("\"{}\"", k)).join(",")); + cx.shared.fs.write(&crate_list_dst, &crate_list)?; + if options.enable_index_page { if let Some(index_page) = options.index_page.clone() { let mut md_opts = options.clone(); @@ -1076,9 +1082,6 @@ themePicker.onblur = handleThemeButtonsBlur; extra_scripts: &[], static_extra_scripts: &[], }; - krates.push(krate.name.to_string()); - krates.sort(); - krates.dedup(); let content = format!( "

\ diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 76449a171d7cc..89b1362b32b63 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -42,6 +42,7 @@ if (!DOMTokenList.prototype.remove) { if (rustdocVars) { window.rootPath = rustdocVars.attributes["data-root-path"].value; window.currentCrate = rustdocVars.attributes["data-current-crate"].value; + window.searchJS = rustdocVars.attributes["data-search-js"].value; } var sidebarVars = document.getElementById("sidebar-vars"); if (sidebarVars) { @@ -1922,8 +1923,8 @@ function defocusSearchBar() { return searchWords; } - function startSearch() { - var callback = function() { + function registerSearchEvents() { + var searchAfter500ms = function() { clearInputTimeout(); if (search_input.value.length === 0) { if (browserSupportsHistoryApi()) { @@ -1935,8 +1936,8 @@ function defocusSearchBar() { searchTimeout = setTimeout(search, 500); } }; - search_input.onkeyup = callback; - search_input.oninput = callback; + search_input.onkeyup = searchAfter500ms; + search_input.oninput = searchAfter500ms; document.getElementsByClassName("search-form")[0].onsubmit = function(e) { e.preventDefault(); clearInputTimeout(); @@ -1999,7 +2000,6 @@ function defocusSearchBar() { } }); } - search(); // This is required in firefox to avoid this problem: Navigating to a search result // with the keyboard, hitting enter, and then hitting back would take you back to @@ -2017,8 +2017,14 @@ function defocusSearchBar() { } index = buildIndex(rawSearchIndex); - startSearch(); + registerSearchEvents(); + // If there's a search term in the URL, execute the search now. + if (getQueryStringParams().search) { + search(); + } + }; + function addSidebarCrates(crates) { // Draw a convenient sidebar of known crates if we have a listing if (window.rootPath === "../" || window.rootPath === "./") { var sidebar = document.getElementsByClassName("sidebar-elems")[0]; @@ -2029,14 +2035,6 @@ function defocusSearchBar() { var ul = document.createElement("ul"); div.appendChild(ul); - var crates = []; - for (var crate in rawSearchIndex) { - if (!hasOwnProperty(rawSearchIndex, crate)) { - continue; - } - crates.push(crate); - } - crates.sort(); for (var i = 0; i < crates.length; ++i) { var klass = "crate"; if (window.rootPath !== "./" && crates[i] === window.currentCrate) { @@ -2044,9 +2042,6 @@ function defocusSearchBar() { } var link = document.createElement("a"); link.href = window.rootPath + crates[i] + "/index.html"; - // The summary in the search index has HTML, so we need to - // dynamically render it as plaintext. - link.title = convertHTMLToPlaintext(rawSearchIndex[crates[i]].doc); link.className = klass; link.textContent = crates[i]; @@ -2057,7 +2052,7 @@ function defocusSearchBar() { sidebar.appendChild(div); } } - }; + } /** * Convert HTML to plaintext: @@ -2862,37 +2857,18 @@ function defocusSearchBar() { } } - window.addSearchOptions = function(crates) { + function addSearchOptions(crates) { var elem = document.getElementById("crate-search"); if (!elem) { enableSearchInput(); return; } - var crates_text = []; - if (Object.keys(crates).length > 1) { - for (var crate in crates) { - if (hasOwnProperty(crates, crate)) { - crates_text.push(crate); - } - } - } - crates_text.sort(function(a, b) { - var lower_a = a.toLowerCase(); - var lower_b = b.toLowerCase(); - - if (lower_a < lower_b) { - return -1; - } else if (lower_a > lower_b) { - return 1; - } - return 0; - }); var savedCrate = getSettingValue("saved-filter-crate"); - for (var i = 0, len = crates_text.length; i < len; ++i) { + for (var i = 0, len = crates.length; i < len; ++i) { var option = document.createElement("option"); - option.value = crates_text[i]; - option.innerText = crates_text[i]; + option.value = crates[i]; + option.innerText = crates[i]; elem.appendChild(option); // Set the crate filter from saved storage, if the current page has the saved crate // filter. @@ -2900,7 +2876,7 @@ function defocusSearchBar() { // If not, ignore the crate filter -- we want to support filtering for crates on sites // like doc.rust-lang.org where the crates may differ from page to page while on the // same domain. - if (crates_text[i] === savedCrate) { + if (crates[i] === savedCrate) { elem.value = savedCrate; } } @@ -2969,6 +2945,44 @@ function defocusSearchBar() { buildHelperPopup = function() {}; } + function loadScript(url) { + var script = document.createElement('script'); + script.src = url; + document.head.append(script); + } + + function setupSearchLoader() { + var searchLoaded = false; + function loadSearch() { + if (!searchLoaded) { + searchLoaded = true; + loadScript(window.searchJS); + } + } + + // `crates{version}.js` should always be loaded before this script, so we can use it safely. + addSearchOptions(window.ALL_CRATES); + addSidebarCrates(window.ALL_CRATES); + + search_input.addEventListener("focus", function() { + search_input.origPlaceholder = search_input.placeholder; + search_input.placeholder = "Type your search here."; + loadSearch(); + }); + search_input.addEventListener("blur", function() { + search_input.placeholder = search_input.origPlaceholder; + }); + enableSearchInput(); + + var crateSearchDropDown = document.getElementById("crate-search"); + crateSearchDropDown.addEventListener("focus", loadSearch); + var params = getQueryStringParams(); + if (params.search !== undefined) { + loadSearch(); + } + } + onHashChange(null); window.onhashchange = onHashChange; + setupSearchLoader(); }());