Skip to content

Commit 568b064

Browse files
committed
better checks for active page in TOC
1 parent b0cf568 commit 568b064

File tree

1 file changed

+71
-14
lines changed

1 file changed

+71
-14
lines changed

src/theme/toc.js.hbs

+71-14
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,95 @@ class MDBookSidebarScrollbox extends HTMLElement {
77
constructor() {
88
super();
99
}
10+
// Set the current, active page, and reveal it if it's hidden
1011
connectedCallback() {
12+
// Helper to compare if 2 link paths are equal:
13+
// - `/foo/`, `/foo/index`, `/foo/index.html` are considered equal
14+
// - `/foo`, `/foo.html` are considered equal
15+
function pathEquals(a, b) {
16+
// safety null checks
17+
if (!a && !b) { return true; }
18+
if (!a || !b) { return false; }
19+
// normalize paths
20+
if (a.endsWith("/")) {
21+
a += "index.html";
22+
} else if (!a.endsWith(".html")) {
23+
a += ".html";
24+
}
25+
if (b.endsWith("/")) {
26+
b += "index.html";
27+
} else if (!b.endsWith(".html")) {
28+
b += ".html";
29+
}
30+
return a === b;
31+
}
32+
33+
// Helper to set a link element in TOC to be active and reveal its parent sections
34+
function setActivePage(link) {
35+
link.classList.add("active");
36+
var parent = link.parentElement;
37+
if (parent && parent.classList.contains("chapter-item")) {
38+
parent.classList.add("expanded");
39+
}
40+
while (parent) {
41+
if (parent.tagName === "LI" && parent.previousElementSibling) {
42+
if (parent.previousElementSibling.classList.contains("chapter-item")) {
43+
parent.previousElementSibling.classList.add("expanded");
44+
}
45+
}
46+
parent = parent.parentElement;
47+
}
48+
}
49+
1150
this.innerHTML = '{{#toc}}{{/toc}}';
12-
// Set the current, active page, and reveal it if it's hidden
1351
let current_page = document.location.href.toString().split("#")[0];
1452
if (current_page.endsWith("/")) {
1553
current_page += "index.html";
1654
}
1755
var links = Array.prototype.slice.call(this.querySelectorAll("a"));
56+
57+
let foundActivePage = false;
1858
var l = links.length;
1959
for (var i = 0; i < l; ++i) {
2060
var link = links[i];
2161
var href = link.getAttribute("href");
2262
if (href && !href.startsWith("#") && !/^(?:[a-z+]+:)?\/\//.test(href)) {
2363
link.href = path_to_root + href;
2464
}
25-
// The "index" page is supposed to alias the first chapter in the book.
26-
if (link.href === current_page || (i === 0 && path_to_root === "" && current_page.endsWith("/index.html"))) {
27-
link.classList.add("active");
28-
var parent = link.parentElement;
29-
if (parent && parent.classList.contains("chapter-item")) {
30-
parent.classList.add("expanded");
31-
}
32-
while (parent) {
33-
if (parent.tagName === "LI" && parent.previousElementSibling) {
34-
if (parent.previousElementSibling.classList.contains("chapter-item")) {
35-
parent.previousElementSibling.classList.add("expanded");
36-
}
65+
if (pathEquals(link.href, current_page)) {
66+
foundActivePage = true;
67+
setActivePage(link);
68+
}
69+
}
70+
71+
if (!foundActivePage) {
72+
// If the current page is not found, there is a possibility
73+
// that the service has redirected /foo/index.html to /foo (without the trailing slash)
74+
// try to find the active page again using this fallback
75+
if (!current_page.endsWith(".html") && !current_page.endsWith("/")) {
76+
let current_page_fallback = current_page + "/index.html";
77+
let l = links.length;
78+
for (let i = 0; i < l; ++i) {
79+
let link = links[i];
80+
if (pathEquals(link.href, current_page_fallback)) {
81+
setActivePage(link);
82+
foundActivePage = true;
83+
break;
3784
}
38-
parent = parent.parentElement;
3985
}
4086
}
4187
}
88+
89+
// In the end, if no active page are marked, check if we are on /index.html,
90+
// which is an alias for the first chapter in the book.
91+
// This is checked in the end because /index.html can be a real path for /index.md or /README.md,
92+
// which may not be the first chapter, and in which case the first chapter will not be aliased to.
93+
if (!foundActivePage) {
94+
if (links[0] && path_to_root === "" && current_page.endsWith("/index.html")) {
95+
setActivePage(links[0]);
96+
}
97+
}
98+
4299
// Track and set sidebar scroll position
43100
this.addEventListener('click', function(e) {
44101
if (e.target.tagName === 'A') {

0 commit comments

Comments
 (0)