2 /* global sourcesIndex */
4 // Local js definitions:
5 /* global addClass, getCurrentValue, onEachLazy, removeClass, browserSupportsHistoryApi */
6 /* global updateLocalStorage */
12 const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-path"].value;
14 const NAME_OFFSET = 0;
15 const DIRS_OFFSET = 1;
16 const FILES_OFFSET = 2;
18 function closeSidebarIfMobile() {
19 if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) {
20 updateLocalStorage("source-sidebar-show", "false");
24 function createDirEntry(elem, parent, fullPath, hasFoundFile) {
25 const dirEntry = document.createElement("details");
26 const summary = document.createElement("summary");
28 dirEntry.className = "dir-entry";
30 fullPath += elem[NAME_OFFSET] + "/";
32 summary.innerText = elem[NAME_OFFSET];
33 dirEntry.appendChild(summary);
35 const folders = document.createElement("div");
36 folders.className = "folders";
37 if (elem[DIRS_OFFSET]) {
38 for (const dir of elem[DIRS_OFFSET]) {
39 if (createDirEntry(dir, folders, fullPath, false)) {
45 dirEntry.appendChild(folders);
47 const files = document.createElement("div");
48 files.className = "files";
49 if (elem[FILES_OFFSET]) {
50 for (const file_text of elem[FILES_OFFSET]) {
51 const file = document.createElement("a");
52 file.innerText = file_text;
53 file.href = rootPath + "src/" + fullPath + file_text + ".html";
54 file.addEventListener("click", closeSidebarIfMobile);
55 const w = window.location.href.split("#")[0];
56 if (!hasFoundFile && w === file.href) {
57 file.className = "selected";
61 files.appendChild(file);
64 dirEntry.appendChild(files);
65 parent.appendChild(dirEntry);
69 function toggleSidebar() {
70 const child = this.parentNode.children[0];
71 if (child.innerText === ">") {
72 window.rustdocMobileScrollLock();
73 addClass(document.documentElement, "source-sidebar-expanded");
74 child.innerText = "<";
75 updateLocalStorage("source-sidebar-show", "true");
77 window.rustdocMobileScrollUnlock();
78 removeClass(document.documentElement, "source-sidebar-expanded");
79 child.innerText = ">";
80 updateLocalStorage("source-sidebar-show", "false");
84 function createSidebarToggle() {
85 const sidebarToggle = document.createElement("div");
86 sidebarToggle.id = "sidebar-toggle";
88 const inner = document.createElement("button");
90 if (getCurrentValue("source-sidebar-show") === "true") {
91 inner.innerText = "<";
93 inner.innerText = ">";
95 inner.onclick = toggleSidebar;
97 sidebarToggle.appendChild(inner);
101 // This function is called from "source-files.js", generated in `html/render/write_shared.rs`.
102 // eslint-disable-next-line no-unused-vars
103 function createSourceSidebar() {
104 const container = document.querySelector("nav.sidebar");
106 const sidebarToggle = createSidebarToggle();
107 container.insertBefore(sidebarToggle, container.firstChild);
109 const sidebar = document.createElement("div");
110 sidebar.id = "source-sidebar";
112 let hasFoundFile = false;
114 const title = document.createElement("div");
115 title.className = "title";
116 title.innerText = "Files";
117 sidebar.appendChild(title);
118 Object.keys(sourcesIndex).forEach(key => {
119 sourcesIndex[key][NAME_OFFSET] = key;
120 hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
124 container.appendChild(sidebar);
125 // Focus on the current file in the source files sidebar.
126 const selected_elem = sidebar.getElementsByClassName("selected")[0];
127 if (typeof selected_elem !== "undefined") {
128 selected_elem.focus();
132 const lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/;
134 function highlightSourceLines(match) {
135 if (typeof match === "undefined") {
136 match = window.location.hash.match(lineNumbersRegex);
141 let from = parseInt(match[1], 10);
143 if (typeof match[2] !== "undefined") {
144 to = parseInt(match[2], 10);
151 let elem = document.getElementById(from);
155 const x = document.getElementById(from);
159 onEachLazy(document.getElementsByClassName("src-line-numbers"), e => {
160 onEachLazy(e.getElementsByTagName("span"), i_e => {
161 removeClass(i_e, "line-highlighted");
164 for (let i = from; i <= to; ++i) {
165 elem = document.getElementById(i);
169 addClass(elem, "line-highlighted");
173 const handleSourceHighlight = (function() {
174 let prev_line_id = 0;
176 const set_fragment = name => {
177 const x = window.scrollX,
179 if (browserSupportsHistoryApi()) {
180 history.replaceState(null, null, "#" + name);
181 highlightSourceLines();
183 location.replace("#" + name);
185 // Prevent jumps when selecting one or many lines
186 window.scrollTo(x, y);
190 let cur_line_id = parseInt(ev.target.id, 10);
191 // It can happen when clicking not on a line number span.
192 if (isNaN(cur_line_id)) {
197 if (ev.shiftKey && prev_line_id) {
198 // Swap selection if needed
199 if (prev_line_id > cur_line_id) {
200 const tmp = prev_line_id;
201 prev_line_id = cur_line_id;
205 set_fragment(prev_line_id + "-" + cur_line_id);
207 prev_line_id = cur_line_id;
209 set_fragment(cur_line_id);
214 window.addEventListener("hashchange", () => {
215 const match = window.location.hash.match(lineNumbersRegex);
217 return highlightSourceLines(match);
221 onEachLazy(document.getElementsByClassName("src-line-numbers"), el => {
222 el.addEventListener("click", handleSourceHighlight);
225 highlightSourceLines();
227 window.createSourceSidebar = createSourceSidebar;