@@ -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