From 96516f09dfbbd253f953d2a7e0b2e6102469cc35 Mon Sep 17 00:00:00 2001 From: alstjr7375 Date: Thu, 15 Aug 2024 16:11:44 +0900 Subject: [PATCH] Create a TOC on the about:preference page --- .../components/preferences/content/general.js | 87 ++++++++++++++++++- .../content/preferences-general.xhtml | 4 + .../browser/components/preferences/jar.mn | 2 + 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/waterfox/browser/components/preferences/content/general.js b/waterfox/browser/components/preferences/content/general.js index b824393406526..d4a43d458793a 100644 --- a/waterfox/browser/components/preferences/content/general.js +++ b/waterfox/browser/components/preferences/content/general.js @@ -78,7 +78,16 @@ const gMainPaneOverlay = { this.setEventListener("dynamicThemeGroup", "command", event => { this.updateDynamicThemePref(event.target.value); }); - document.initialized = true; + if (document.readyState === "complete") { + this.tocGenerate(); + } else { + document.addEventListener("readystatechange", () => { + if (document.readyState === "complete") { + this.tocGenerate(); + } + }); + } + document.initialized = true; } this.setEventListener("enableObliviousDns", "click", function () { let value = document.getElementById("enableObliviousDns").checked ? 2 : 0; @@ -86,6 +95,82 @@ const gMainPaneOverlay = { }); }, + tocGenerate() { + const contentSelector = "#mainPrefPane"; + const headingSelector = "#mainPrefPane > hbox:not([hidden]) > h1, #mainPrefPane > groupbox:not([hidden]) > h2, #mainPrefPane > groupbox:not([hidden]) label:not([hidden]) > h2"; + const headerTarget = headingSelector.replaceAll(":not([hidden])", ""); + const specialCharRegex = /[\!\@\#\$\%\^\&\*\(\):]/ig; + const createHeadingId = () => { + const content = document.querySelector(contentSelector); + const headings = content?.querySelectorAll(headerTarget); + const headingMap = {}; + + let count = 0; + /** + * @param {Element} heading + * @returns {string} + */ + const getHeadingId = (heading) => { + const id = heading.id; + if (id) { + return id; + } + + if (heading instanceof HTMLElement) { + const i18nId = heading.dataset.l10nId; + if (i18nId) { + return i18nId; + } + } + + return heading.textContent?.trim().toLowerCase().split(" ").join("-").replace(specialCharRegex, "") ?? `${count++}`; + } + /** + * @param {string} headingText + * @param {number} count + * @returns {string} + */ + const createId = (headingText, count) => `${headingText}${count > 0 ? `-${count}` : ""}`; + headings?.forEach((heading) => { + const id = getHeadingId(heading); + headingMap[id] = !isNaN(headingMap[id]) ? ++headingMap[id] : 0; + heading.id = createId(id, headingMap[id]); + }); + } + + createHeadingId(); + tocbot.init({ + tocSelector: ".toc", + contentSelector, + headingSelector, + scrollContainer: ".main-content", + headingsOffset: 100, // 90 + margins + hasInnerContainers: false, + + /** + * @param {MouseEvent} e + */ + onClick(e) { + e.preventDefault(); + + /** @type {HTMLLinkElement} */ + const link = e.target; + const targetSelector = link?.getAttribute("href"); + if (targetSelector) { + const target = document.querySelector(targetSelector); + if (target) { + target.scrollIntoView({ behavior: "smooth", block: "start" }); + } + } + } + }); + const tocRefresh = () => { + createHeadingId(); + tocbot.refresh(); + } + window.addEventListener("hashchange", tocRefresh); + }, + showRelevantElements() { let idsGeneral = [ "dynamicThemeGroup", diff --git a/waterfox/browser/components/preferences/content/preferences-general.xhtml b/waterfox/browser/components/preferences/content/preferences-general.xhtml index 5ab808609d55b..4bdc9de92307e 100644 --- a/waterfox/browser/components/preferences/content/preferences-general.xhtml +++ b/waterfox/browser/components/preferences/content/preferences-general.xhtml @@ -3,12 +3,14 @@ + @@ -120,6 +122,8 @@ #endif + + diff --git a/waterfox/browser/components/preferences/jar.mn b/waterfox/browser/components/preferences/jar.mn index fb553c2447fbc..28f6848b5e20a 100644 --- a/waterfox/browser/components/preferences/jar.mn +++ b/waterfox/browser/components/preferences/jar.mn @@ -5,6 +5,8 @@ browser.jar: content/browser/overlays/general.js (content/general.js) content/browser/overlays/privacy.js (content/privacy.js) content/browser/overlays/theme.js (content/theme.js) + content/browser/overlays/tocbot.js (content/tocbot.js) + content/browser/overlays/tocbot.css (content/tocbot.css) content/browser/overlays/images (images/**) % resource waterfox %waterfox/ contentaccessible=yes