diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index da020b85ed4..b91aab44f10 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -789,6 +789,37 @@ themePicker.onblur = handleThemeButtonsBlur;
Ok((ret, krates))
}
+ fn collect_json(path: &Path, krate: &str) -> io::Result<(Vec, Vec)> {
+ let mut ret = Vec::new();
+ let mut krates = Vec::new();
+
+ if path.exists() {
+ for line in BufReader::new(File::open(path)?).lines() {
+ let line = line?;
+ if !line.starts_with("\"") {
+ continue;
+ }
+ if line.starts_with(&format!("\"{}\"", krate)) {
+ continue;
+ }
+ if line.ends_with(",\\") {
+ ret.push(line[..line.len() - 2].to_string());
+ } else {
+ // Ends with "\\" (it's the case for the last added crate line)
+ ret.push(line[..line.len() - 1].to_string());
+ }
+ krates.push(
+ line.split('"')
+ .filter(|s| !s.is_empty())
+ .next()
+ .map(|s| s.to_owned())
+ .unwrap_or_else(String::new),
+ );
+ }
+ }
+ Ok((ret, krates))
+ }
+
fn show_item(item: &IndexItem, krate: &str) -> String {
format!(
"{{'crate':'{}','ty':{},'name':'{}','desc':'{}','p':'{}'{}}}",
@@ -909,18 +940,18 @@ themePicker.onblur = handleThemeButtonsBlur;
// Update the search index
let dst = cx.dst.join(&format!("search-index{}.js", cx.shared.resource_suffix));
- let (mut all_indexes, mut krates) = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
+ let (mut all_indexes, mut krates) = try_err!(collect_json(&dst, &krate.name), &dst);
all_indexes.push(search_index);
// 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={};\n");
- v.push_str(&all_indexes.join("\n"));
+ 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("\naddSearchOptions(searchIndex);initSearch(searchIndex);");
+ v.push_str("\\\n}');\naddSearchOptions(searchIndex);initSearch(searchIndex);");
cx.shared.fs.write(&dst, &v)?;
}
if options.enable_index_page {
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index a8efb16a1d3..03aa5d519c6 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -631,7 +631,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
// Collect the index into a string
format!(
- r#"searchIndex["{}"] = {};"#,
+ r#""{}":{}"#,
krate.name,
serde_json::to_string(&CrateData {
doc: crate_doc,
@@ -639,6 +639,11 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
paths: crate_paths,
})
.expect("failed serde conversion")
+ // All these `replace` calls are because we have to go through JS string for JSON content.
+ .replace(r"\", r"\\")
+ .replace("'", r"\'")
+ // We need to escape double quotes for the JSON.
+ .replace("\\\"", "\\\\\"")
)
}