about summary refs log tree commit diff
path: root/src/doc/rustc-dev-guide/pagetoc.js
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-08-05 01:53:59 +0000
committerbors <bors@rust-lang.org>2025-08-05 01:53:59 +0000
commit0f353363965ebf05e0757f7679c800b39c51a07e (patch)
treeba4c09b6d1616f0505e88cf7d9c76f7b0ed45e5b /src/doc/rustc-dev-guide/pagetoc.js
parent0060d5a2a8a86a31f6299311fe64b1d755a91c4f (diff)
parent5c11681820a843da59d7b9c5e848f3e9e7fd0f62 (diff)
downloadrust-0f353363965ebf05e0757f7679c800b39c51a07e.tar.gz
rust-0f353363965ebf05e0757f7679c800b39c51a07e.zip
Auto merge of #144934 - samueltardieu:rollup-25jvb9g, r=samueltardieu
Rollup of 17 pull requests

Successful merges:

 - rust-lang/rust#144467 (rustdoc template font links only emit `crossorigin` when needed)
 - rust-lang/rust#144548 (Rehome 21 `tests/ui/issues/` tests to other subdirectories under `tests/ui/`)
 - rust-lang/rust#144741 (fix: Error on illegal `[const]`s inside blocks within legal positions)
 - rust-lang/rust#144776 (`Printer` cleanups)
 - rust-lang/rust#144779 (Implement debugging output of the bootstrap Step graph into a DOT file)
 - rust-lang/rust#144813 (Add a tidy check to prevent adding UI tests directly under `tests/ui/`)
 - rust-lang/rust#144817 (Properly reject tail calls to `&FnPtr` or `&FnDef`)
 - rust-lang/rust#144852 (Rename `rust_panic_without_hook` to `resume_unwind` )
 - rust-lang/rust#144866 (Remove `SHOULD_EMIT_LINTS` in favor of `should_emit`)
 - rust-lang/rust#144867 (Use `as_array` in PartialEq for arrays)
 - rust-lang/rust#144872 (Document Poisoning in `LazyCell` and `LazyLock`)
 - rust-lang/rust#144877 (coverage: Various small cleanups)
 - rust-lang/rust#144887 (`rust-analyzer` subtree update)
 - rust-lang/rust#144890 (Add `InterpCx::project_fields`)
 - rust-lang/rust#144894 (Delete `tests/ui/threads-sendsync/tcp-stress.rs`)
 - rust-lang/rust#144905 (rustc-dev-guide subtree update)
 - rust-lang/rust#144920 (Dont print arg span in MIR dump for tail call)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src/doc/rustc-dev-guide/pagetoc.js')
-rw-r--r--src/doc/rustc-dev-guide/pagetoc.js104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/doc/rustc-dev-guide/pagetoc.js b/src/doc/rustc-dev-guide/pagetoc.js
new file mode 100644
index 00000000000..927a5b10749
--- /dev/null
+++ b/src/doc/rustc-dev-guide/pagetoc.js
@@ -0,0 +1,104 @@
+// Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL)
+
+let activeHref = location.href;
+function updatePageToc(elem = undefined) {
+    let selectedPageTocElem = elem;
+    const pagetoc = document.getElementById("pagetoc");
+
+    function getRect(element) {
+        return element.getBoundingClientRect();
+    }
+
+    function overflowTop(container, element) {
+        return getRect(container).top - getRect(element).top;
+    }
+
+    function overflowBottom(container, element) {
+        return getRect(container).bottom - getRect(element).bottom;
+    }
+
+    // We've not selected a heading to highlight, and the URL needs updating
+    // so we need to find a heading based on the URL
+    if (selectedPageTocElem === undefined && location.href !== activeHref) {
+        activeHref = location.href;
+        for (const pageTocElement of pagetoc.children) {
+            if (pageTocElement.href === activeHref) {
+                selectedPageTocElem = pageTocElement;
+            }
+        }
+    }
+
+    // We still don't have a selected heading, let's try and find the most
+    // suitable heading based on the scroll position
+    if (selectedPageTocElem === undefined) {
+        const margin = window.innerHeight / 3;
+
+        const headers = document.getElementsByClassName("header");
+        for (let i = 0; i < headers.length; i++) {
+            const header = headers[i];
+            if (selectedPageTocElem === undefined && getRect(header).top >= 0) {
+                if (getRect(header).top < margin) {
+                    selectedPageTocElem = header;
+                } else {
+                    selectedPageTocElem = headers[Math.max(0, i - 1)];
+                }
+            }
+            // a very long last section's heading is over the screen
+            if (selectedPageTocElem === undefined && i === headers.length - 1) {
+                selectedPageTocElem = header;
+            }
+        }
+    }
+
+    // Remove the active flag from all pagetoc elements
+    for (const pageTocElement of pagetoc.children) {
+        pageTocElement.classList.remove("active");
+    }
+
+    // If we have a selected heading, set it to active and scroll to it
+    if (selectedPageTocElem !== undefined) {
+        for (const pageTocElement of pagetoc.children) {
+            if (selectedPageTocElem.href.localeCompare(pageTocElement.href) === 0) {
+                pageTocElement.classList.add("active");
+                if (overflowTop(pagetoc, pageTocElement) > 0) {
+                    pagetoc.scrollTop = pageTocElement.offsetTop;
+                }
+                if (overflowBottom(pagetoc, pageTocElement) < 0) {
+                    pagetoc.scrollTop -= overflowBottom(pagetoc, pageTocElement);
+                }
+            }
+        }
+    }
+}
+
+if (document.getElementById("sidetoc") === null &&
+    document.getElementsByClassName("header").length > 0) {
+    // The sidetoc element doesn't exist yet, let's create it
+
+    // Create the empty sidetoc and pagetoc elements
+    const sidetoc = document.createElement("div");
+    const pagetoc = document.createElement("div");
+    sidetoc.id = "sidetoc";
+    pagetoc.id = "pagetoc";
+    sidetoc.appendChild(pagetoc);
+
+    // And append them to the current DOM
+    const main = document.querySelector('main');
+    main.insertBefore(sidetoc, main.firstChild);
+
+    // Populate sidebar on load
+    window.addEventListener("load", () => {
+        for (const header of document.getElementsByClassName("header")) {
+            const link = document.createElement("a");
+            link.innerHTML = header.innerHTML;
+            link.href = header.hash;
+            link.classList.add("pagetoc-" + header.parentElement.tagName);
+            document.getElementById("pagetoc").appendChild(link);
+            link.onclick = () => updatePageToc(link);
+        }
+        updatePageToc();
+    });
+
+    // Update page table of contents selected heading on scroll
+    window.addEventListener("scroll", () => updatePageToc());
+}