about summary refs log tree commit diff
path: root/src/librustdoc/html/static/js/source-script.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustdoc/html/static/js/source-script.js')
-rw-r--r--src/librustdoc/html/static/js/source-script.js242
1 files changed, 242 insertions, 0 deletions
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
new file mode 100644
index 00000000000..aa77e62ba5a
--- /dev/null
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -0,0 +1,242 @@
+// From rust:
+/* global search, sourcesIndex */
+
+// Local js definitions:
+/* global addClass, getCurrentValue, hasClass, onEachLazy, removeClass, searchState */
+/* global updateLocalStorage */
+(function() {
+
+function getCurrentFilePath() {
+    var parts = window.location.pathname.split("/");
+    var rootPathParts = window.rootPath.split("/");
+
+    for (var i = 0, len = rootPathParts.length; i < len; ++i) {
+        if (rootPathParts[i] === "..") {
+            parts.pop();
+        }
+    }
+    var file = window.location.pathname.substring(parts.join("/").length);
+    if (file.startsWith("/")) {
+        file = file.substring(1);
+    }
+    return file.substring(0, file.length - 5);
+}
+
+function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
+    var name = document.createElement("div");
+    name.className = "name";
+
+    fullPath += elem["name"] + "/";
+
+    name.onclick = function() {
+        if (hasClass(this, "expand")) {
+            removeClass(this, "expand");
+        } else {
+            addClass(this, "expand");
+        }
+    };
+    name.innerText = elem["name"];
+
+    var i, len;
+
+    var children = document.createElement("div");
+    children.className = "children";
+    var folders = document.createElement("div");
+    folders.className = "folders";
+    if (elem.dirs) {
+        for (i = 0, len = elem.dirs.length; i < len; ++i) {
+            if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
+                               hasFoundFile)) {
+                addClass(name, "expand");
+                hasFoundFile = true;
+            }
+        }
+    }
+    children.appendChild(folders);
+
+    var files = document.createElement("div");
+    files.className = "files";
+    if (elem.files) {
+        for (i = 0, len = elem.files.length; i < len; ++i) {
+            var file = document.createElement("a");
+            file.innerText = elem.files[i];
+            file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
+            if (!hasFoundFile && currentFile === fullPath + elem.files[i]) {
+                file.className = "selected";
+                addClass(name, "expand");
+                hasFoundFile = true;
+            }
+            files.appendChild(file);
+        }
+    }
+    search.fullPath = fullPath;
+    children.appendChild(files);
+    parent.appendChild(name);
+    parent.appendChild(children);
+    return hasFoundFile && currentFile.startsWith(fullPath);
+}
+
+function toggleSidebar() {
+    var sidebar = document.querySelector("nav.sidebar");
+    var child = this.children[0];
+    if (child.innerText === ">") {
+        sidebar.classList.add("expanded");
+        child.innerText = "<";
+        updateLocalStorage("source-sidebar-show", "true");
+    } else {
+        sidebar.classList.remove("expanded");
+        child.innerText = ">";
+        updateLocalStorage("source-sidebar-show", "false");
+    }
+}
+
+function createSidebarToggle() {
+    var sidebarToggle = document.createElement("div");
+    sidebarToggle.id = "sidebar-toggle";
+    sidebarToggle.onclick = toggleSidebar;
+
+    var inner = document.createElement("div");
+
+    if (getCurrentValue("source-sidebar-show") === "true") {
+        inner.innerText = "<";
+    } else {
+        inner.innerText = ">";
+    }
+
+    sidebarToggle.appendChild(inner);
+    return sidebarToggle;
+}
+
+// This function is called from "source-files.js", generated in `html/render/mod.rs`.
+// eslint-disable-next-line no-unused-vars
+function createSourceSidebar() {
+    if (!window.rootPath.endsWith("/")) {
+        window.rootPath += "/";
+    }
+    var container = document.querySelector("nav.sidebar");
+
+    var sidebarToggle = createSidebarToggle();
+    container.insertBefore(sidebarToggle, container.firstChild);
+
+    var sidebar = document.createElement("div");
+    sidebar.id = "source-sidebar";
+    if (getCurrentValue("source-sidebar-show") !== "true") {
+        container.classList.remove("expanded");
+    } else {
+        container.classList.add("expanded");
+    }
+
+    var currentFile = getCurrentFilePath();
+    var hasFoundFile = false;
+
+    var title = document.createElement("div");
+    title.className = "title";
+    title.innerText = "Files";
+    sidebar.appendChild(title);
+    Object.keys(sourcesIndex).forEach(function(key) {
+        sourcesIndex[key].name = key;
+        hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
+                                      currentFile, hasFoundFile);
+    });
+
+    container.appendChild(sidebar);
+    // Focus on the current file in the source files sidebar.
+    var selected_elem = sidebar.getElementsByClassName("selected")[0];
+    if (typeof selected_elem !== "undefined") {
+        selected_elem.focus();
+    }
+}
+
+var lineNumbersRegex = /^#?(\d+)(?:-(\d+))?$/;
+
+function highlightSourceLines(match) {
+    if (typeof match === "undefined") {
+        match = window.location.hash.match(lineNumbersRegex);
+    }
+    if (!match) {
+        return;
+    }
+    var from = parseInt(match[1], 10);
+    var to = from;
+    if (typeof match[2] !== "undefined") {
+        to = parseInt(match[2], 10);
+    }
+    if (to < from) {
+        var tmp = to;
+        to = from;
+        from = tmp;
+    }
+    var elem = document.getElementById(from);
+    if (!elem) {
+        return;
+    }
+    var x = document.getElementById(from);
+    if (x) {
+        x.scrollIntoView();
+    }
+    onEachLazy(document.getElementsByClassName("line-numbers"), function(e) {
+        onEachLazy(e.getElementsByTagName("span"), function(i_e) {
+            removeClass(i_e, "line-highlighted");
+        });
+    });
+    for (var i = from; i <= to; ++i) {
+        elem = document.getElementById(i);
+        if (!elem) {
+            break;
+        }
+        addClass(elem, "line-highlighted");
+    }
+}
+
+var handleSourceHighlight = (function() {
+    var prev_line_id = 0;
+
+    var set_fragment = function(name) {
+        var x = window.scrollX,
+            y = window.scrollY;
+        if (searchState.browserSupportsHistoryApi()) {
+            history.replaceState(null, null, "#" + name);
+            highlightSourceLines();
+        } else {
+            location.replace("#" + name);
+        }
+        // Prevent jumps when selecting one or many lines
+        window.scrollTo(x, y);
+    };
+
+    return function(ev) {
+        var cur_line_id = parseInt(ev.target.id, 10);
+        ev.preventDefault();
+
+        if (ev.shiftKey && prev_line_id) {
+            // Swap selection if needed
+            if (prev_line_id > cur_line_id) {
+                var tmp = prev_line_id;
+                prev_line_id = cur_line_id;
+                cur_line_id = tmp;
+            }
+
+            set_fragment(prev_line_id + "-" + cur_line_id);
+        } else {
+            prev_line_id = cur_line_id;
+
+            set_fragment(cur_line_id);
+        }
+    };
+}());
+
+window.addEventListener("hashchange", function() {
+    var match = window.location.hash.match(lineNumbersRegex);
+    if (match) {
+        return highlightSourceLines(match);
+    }
+});
+
+onEachLazy(document.getElementsByClassName("line-numbers"), function(el) {
+    el.addEventListener("click", handleSourceHighlight);
+});
+
+highlightSourceLines();
+
+window.createSourceSidebar = createSourceSidebar;
+})();