Skip to content

Commit

Permalink
Add Table of Contents to preferences
Browse files Browse the repository at this point in the history
- Implement tocbot library for generating table of contents
- Modify general.js to initialize and handle table of contents generation
- Update preferences-general.xhtml to include tocbot styles and scripts
- Add placeholder for table of contents in the preferences UI
- Implement smooth scrolling and highlighting for table of contents items
- Adjust styling for table of contents to match preferences design
  • Loading branch information
black7375 authored Aug 15, 2024
1 parent 19a4529 commit 23a0e27
Show file tree
Hide file tree
Showing 5 changed files with 1,306 additions and 1 deletion.
87 changes: 86 additions & 1 deletion waterfox/browser/components/preferences/content/general.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,99 @@ 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;
Services.prefs.setIntPref("network.trr.mode", value);
});
},

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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://browser/content/overlays/tocbot.css" type="text/css"?>

<overlay id="preferences-overlay" xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script>
/* eslint-env mozilla/browser-window */
/* globals gMainPaneOverlay */
Services.scriptloader.loadSubScript("chrome://browser/content/overlays/tocbot.js", this);
Services.scriptloader.loadSubScript("chrome://browser/content/overlays/general.js", this);
gMainPaneOverlay.init();
</script>
Expand Down Expand Up @@ -120,6 +122,8 @@
</radiogroup>
</groupbox>
#endif
<!-- TOC Placeholder -->
<html:nav class="toc" />
</vbox>

<!-- Browsing -->
Expand Down
57 changes: 57 additions & 0 deletions waterfox/browser/components/preferences/content/tocbot.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.toc{overflow-y:auto}.toc>.toc-list{overflow:hidden;position:relative}.toc>.toc-list li{list-style:none}.toc-list{margin:0;padding-left:10px}a.toc-link{color:currentColor;height:100%}.is-collapsible{max-height:1000px;overflow:hidden;transition:all 300ms ease-in-out}.is-collapsed{max-height:0}.is-position-fixed{position:fixed !important;top:0}.is-active-link{font-weight:700}.toc-link::before{background-color:#eee;content:" ";display:inline-block;height:inherit;left:0;margin-top:-1px;position:absolute;width:2px}.is-active-link::before{background-color:#54bc4b}/*# sourceMappingURL=tocbot.css.map */

/* Patched version */
.toc {
--uc-toc-margin: 0.5em;
display: block;
position: fixed;
width: 300px;
height: calc(100vh - 90px); /* .main-content inline style scroll-padding-top: 90px; */
transform: translateX(calc(var(--main-pane-width, 664px) + max(60px, 8vw)));
scrollbar-width: none;
}
@media (max-width: 1280px) {
.toc {
display: none;
}
}
.toc-list > .toc-list-item:only-child:not(:has(.toc-list)) {
/* If only one exists, remove it. */
display: none;
}

.toc-list-item {
cursor: pointer;
}
.toc-list-item > .toc-list:not(.is-collapsed) {
margin-top: var(--uc-toc-margin);
}
.toc-list-item:not(:last-child) {
margin-bottom: var(--uc-toc-margin);
}

.toc-link {
font-size: 1.14em; /* as h2 */
text-decoration: none;
}
.toc-link::before {
background-color: #eeeeef;
}
.is-active-link::before{
background-color: var(--in-content-accent-color, AccentColor);
}

.toc-list-item:hover:not(:has(> .toc-list:hover)) > .toc-link {
font-weight: 700;
}
.toc-list-item:hover:not(:has(> .toc-list:hover)) > .toc-link:not(.is-active-link)::before {
background-color: #d1d1d6;
}
@media (prefers-color-scheme: dark) {
.toc-link:not(.is-active-link)::before {
background-color: #2c2b32;
}
.toc-list-item:hover:not(:has(> .toc-list:hover)) > .toc-link:not(.is-active-link)::before {
background-color: #57575d;
}
}
Loading

0 comments on commit 23a0e27

Please sign in to comment.