Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load rustdoc's JS search index on-demand. #82310

Merged
merged 1 commit into from
Mar 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/librustdoc/html/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ crate fn render<T: Print, S: Print>(
{style_files}\
<script id=\"default-settings\"{default_settings}></script>\
<script src=\"{static_root_path}storage{suffix}.js\"></script>\
<script src=\"{static_root_path}crates{suffix}.js\"></script>\
<noscript><link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\"></noscript>\
{css_extension}\
{favicon}\
Expand Down Expand Up @@ -112,10 +113,10 @@ crate fn render<T: Print, S: Print>(
<section id=\"search\" class=\"content hidden\"></section>\
<section class=\"footer\"></section>\
{after_content}\
<div id=\"rustdoc-vars\" data-root-path=\"{root_path}\" data-current-crate=\"{krate}\"></div>
<div id=\"rustdoc-vars\" data-root-path=\"{root_path}\" data-current-crate=\"{krate}\" \
data-search-js=\"{root_path}search-index{suffix}.js\"></div>
<script src=\"{static_root_path}main{suffix}.js\"></script>\
{extra_scripts}\
<script defer src=\"{root_path}search-index{suffix}.js\"></script>\
</body>\
</html>",
css_extension = if layout.css_file_extension.is_some() {
Expand Down
17 changes: 10 additions & 7 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1039,22 +1039,28 @@ 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.
all_indexes.sort();
{
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(","));
GuillaumeGomez marked this conversation as resolved.
Show resolved Hide resolved
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();
Expand All @@ -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!(
"<h1 class=\"fqn\">\
Expand Down
98 changes: 56 additions & 42 deletions src/librustdoc/html/static/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -1922,8 +1923,8 @@ function defocusSearchBar() {
return searchWords;
}

function startSearch() {
var callback = function() {
function registerSearchEvents() {
var searchAfter500ms = function() {
GuillaumeGomez marked this conversation as resolved.
Show resolved Hide resolved
clearInputTimeout();
if (search_input.value.length === 0) {
if (browserSupportsHistoryApi()) {
Expand All @@ -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();
Expand Down Expand Up @@ -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
Expand All @@ -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];
Expand All @@ -2029,24 +2035,13 @@ 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) {
klass += " current";
}
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];

Expand All @@ -2057,7 +2052,7 @@ function defocusSearchBar() {
sidebar.appendChild(div);
}
}
};
}

/**
* Convert HTML to plaintext:
Expand Down Expand Up @@ -2862,45 +2857,26 @@ 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.
//
// 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;
}
}
Expand Down Expand Up @@ -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.";
GuillaumeGomez marked this conversation as resolved.
Show resolved Hide resolved
loadSearch();
});
search_input.addEventListener("blur", function() {
search_input.placeholder = search_input.origPlaceholder;
GuillaumeGomez marked this conversation as resolved.
Show resolved Hide resolved
});
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();
}());