diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 27ad91d09e064..6fb41ff327916 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -366,13 +366,15 @@ pub(super) fn write_shared( .collect::>(); files.sort_unstable(); let subs = subs.iter().map(|s| s.to_json_string()).collect::>().join(","); - let dirs = - if subs.is_empty() { String::new() } else { format!(",\"dirs\":[{}]", subs) }; + let dirs = if subs.is_empty() && files.is_empty() { + String::new() + } else { + format!(",[{}]", subs) + }; let files = files.join(","); - let files = - if files.is_empty() { String::new() } else { format!(",\"files\":[{}]", files) }; + let files = if files.is_empty() { String::new() } else { format!(",[{}]", files) }; format!( - "{{\"name\":\"{name}\"{dirs}{files}}}", + "[\"{name}\"{dirs}{files}]", name = self.elem.to_str().expect("invalid osstring conversion"), dirs = dirs, files = files @@ -411,18 +413,23 @@ pub(super) fn write_shared( let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix)); let make_sources = || { let (mut all_sources, _krates) = - try_err!(collect(&dst, krate.name(cx.tcx()).as_str(), "sourcesIndex"), &dst); + try_err!(collect_json(&dst, krate.name(cx.tcx()).as_str()), &dst); all_sources.push(format!( - "sourcesIndex[\"{}\"] = {};", + r#""{}":{}"#, &krate.name(cx.tcx()), - hierarchy.to_json_string() + hierarchy + .to_json_string() + // All these `replace` calls are because we have to go through JS string for JSON content. + .replace('\\', r"\\") + .replace('\'', r"\'") + // We need to escape double quotes for the JSON. + .replace("\\\"", "\\\\\"") )); all_sources.sort(); - Ok(format!( - "var sourcesIndex = {{}};\n{}\ncreateSourceSidebar();\n", - all_sources.join("\n") - ) - .into_bytes()) + let mut v = String::from("var sourcesIndex = JSON.parse('{\\\n"); + v.push_str(&all_sources.join(",\\\n")); + v.push_str("\\\n}');\ncreateSourceSidebar();\n"); + Ok(v.into_bytes()) }; write_crate("source-files.js", &make_sources)?; } diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js index a6a0b09ef31fe..c45d614293a85 100644 --- a/src/librustdoc/html/static/js/source-script.js +++ b/src/librustdoc/html/static/js/source-script.js @@ -12,6 +12,10 @@ const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-path"].value; let oldScrollPosition = 0; +const NAME_OFFSET = 0; +const DIRS_OFFSET = 1; +const FILES_OFFSET = 2; + function closeSidebarIfMobile() { if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) { updateLocalStorage("source-sidebar-show", "false"); @@ -24,15 +28,15 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) { dirEntry.className = "dir-entry"; - fullPath += elem["name"] + "/"; + fullPath += elem[NAME_OFFSET] + "/"; - summary.innerText = elem["name"]; + summary.innerText = elem[NAME_OFFSET]; dirEntry.appendChild(summary); const folders = document.createElement("div"); folders.className = "folders"; - if (elem.dirs) { - for (const dir of elem.dirs) { + if (elem[DIRS_OFFSET]) { + for (const dir of elem[DIRS_OFFSET]) { if (createDirEntry(dir, folders, fullPath, false)) { dirEntry.open = true; hasFoundFile = true; @@ -43,8 +47,8 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) { const files = document.createElement("div"); files.className = "files"; - if (elem.files) { - for (const file_text of elem.files) { + if (elem[FILES_OFFSET]) { + for (const file_text of elem[FILES_OFFSET]) { const file = document.createElement("a"); file.innerText = file_text; file.href = rootPath + "src/" + fullPath + file_text + ".html"; @@ -125,7 +129,7 @@ function createSourceSidebar() { title.innerText = "Files"; sidebar.appendChild(title); Object.keys(sourcesIndex).forEach(key => { - sourcesIndex[key].name = key; + sourcesIndex[key][NAME_OFFSET] = key; hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "", hasFoundFile); });