(function() {
'use strict';
var tocToggle = document.querySelector('.toc-toggle');
var book = document.querySelector('.book');
var pageToc = document.querySelector('.page-toc');
function isMobileToc() {
return window.innerWidth <= 768;
}
if (tocToggle && book && pageToc) {
if (!isMobileToc()) {
var tocHidden = localStorage.getItem('guidebook-toc-hidden') === 'true';
if (tocHidden) {
book.classList.add('toc-hidden');
}
}
tocToggle.addEventListener('click', function() {
if (!isMobileToc()) {
book.classList.toggle('toc-hidden');
var isHidden = book.classList.contains('toc-hidden');
localStorage.setItem('guidebook-toc-hidden', isHidden);
}
});
window.addEventListener('resize', function() {
if (isMobileToc()) {
} else {
var tocHidden = localStorage.getItem('guidebook-toc-hidden') === 'true';
if (tocHidden) {
book.classList.add('toc-hidden');
} else {
book.classList.remove('toc-hidden');
}
}
});
}
function setupTocScrollSpy() {
var tocLinks = document.querySelectorAll('.page-toc .toc-list a');
if (tocLinks.length === 0) return;
var headings = [];
tocLinks.forEach(function(link) {
var href = link.getAttribute('href');
if (href && href.startsWith('#')) {
var id = href.substring(1);
try {
id = decodeURIComponent(id);
} catch (e) {}
var heading = document.getElementById(id);
if (heading) {
headings.push({ element: heading, link: link });
}
}
});
if (headings.length === 0) return;
function updateActiveLink() {
var scrollTop = window.scrollY + 100; var activeIndex = 0;
for (var i = 0; i < headings.length; i++) {
if (headings[i].element.offsetTop <= scrollTop) {
activeIndex = i;
}
}
tocLinks.forEach(function(link) {
link.parentElement.classList.remove('active');
});
headings[activeIndex].link.parentElement.classList.add('active');
}
window.addEventListener('scroll', updateActiveLink);
updateActiveLink(); }
setupTocScrollSpy();
function setupTocLinks() {
var pageToc = document.querySelector('.page-toc');
if (!pageToc) return;
pageToc.addEventListener('click', function(e) {
var link = e.target.closest('a');
if (!link) return;
var href = link.getAttribute('href');
if (!href || !href.startsWith('#')) return;
e.preventDefault();
var id = href.substring(1);
try {
id = decodeURIComponent(id);
} catch (ex) {}
var target = document.getElementById(id);
if (target) {
target.scrollIntoView({ behavior: 'smooth' });
history.pushState(null, '', href);
}
});
}
setupTocLinks();
var backToTop = document.querySelector('.back-to-top');
if (backToTop) {
window.addEventListener('scroll', function() {
if (window.scrollY > 300) {
backToTop.classList.add('visible');
} else {
backToTop.classList.remove('visible');
}
});
backToTop.addEventListener('click', function(e) {
e.preventDefault();
window.scrollTo({ top: 0, behavior: 'smooth' });
});
}
var sidebarToggle = document.querySelector('.sidebar-toggle');
var book = document.querySelector('.book');
var bookSummary = document.querySelector('.book-summary');
function isMobile() {
return window.innerWidth <= 768;
}
var wasMobile = isMobile();
if (sidebarToggle && book && bookSummary) {
if (!isMobile()) {
var sidebarHidden = localStorage.getItem('guidebook-sidebar-hidden') === 'true';
if (sidebarHidden) {
book.classList.add('sidebar-hidden');
}
}
sidebarToggle.addEventListener('click', function() {
if (isMobile()) {
bookSummary.classList.toggle('open');
} else {
book.classList.add('sidebar-toggling');
book.classList.toggle('sidebar-hidden');
var isHidden = book.classList.contains('sidebar-hidden');
localStorage.setItem('guidebook-sidebar-hidden', isHidden);
setTimeout(function() {
book.classList.remove('sidebar-toggling');
}, 350);
}
});
document.addEventListener('click', function(e) {
if (isMobile() && bookSummary.classList.contains('open')) {
if (!bookSummary.contains(e.target) && !sidebarToggle.contains(e.target)) {
bookSummary.classList.remove('open');
}
}
});
window.addEventListener('resize', function() {
var nowMobile = isMobile();
if (wasMobile !== nowMobile) {
if (nowMobile) {
book.classList.remove('sidebar-hidden');
book.classList.remove('sidebar-toggling');
bookSummary.classList.remove('open');
} else {
bookSummary.classList.remove('open');
var sidebarHidden = localStorage.getItem('guidebook-sidebar-hidden') === 'true';
if (sidebarHidden) {
book.classList.add('sidebar-hidden');
} else {
book.classList.remove('sidebar-hidden');
}
}
wasMobile = nowMobile;
}
});
}
document.querySelectorAll('a[href*="#"]').forEach(function(anchor) {
anchor.addEventListener('click', function(e) {
var href = this.getAttribute('href');
var hashIndex = href.indexOf('#');
if (hashIndex === -1) return;
var hash = href.substring(hashIndex + 1);
try {
hash = decodeURIComponent(hash);
} catch (ex) {
}
var target = document.getElementById(hash);
if (target) {
e.preventDefault();
target.scrollIntoView({ behavior: 'smooth' });
history.pushState(null, '', '#' + encodeURIComponent(hash));
}
});
});
var baseUrl = (function() {
var base = document.querySelector('base');
if (base && base.href) {
return base.href;
}
return window.location.href.replace(/[^/]*$/, '');
})();
var isNavigating = false;
function normalizeSidebarHrefs() {
var sidebar = document.querySelector('.book-summary');
if (!sidebar) return;
sidebar.querySelectorAll('a[href]').forEach(function(link) {
var href = link.getAttribute('href');
if (!href || href.startsWith('#') || href.startsWith('http') || href.startsWith('/')) return;
var absoluteUrl = new URL(href, baseUrl).href;
link.setAttribute('href', absoluteUrl);
});
}
function setupSpaNavigation() {
var sidebar = document.querySelector('.book-summary');
if (!sidebar) return;
normalizeSidebarHrefs();
sidebar.addEventListener('click', function(e) {
var link = e.target.closest('a');
if (!link) return;
var href = link.getAttribute('href');
if (!href || href.startsWith('#')) return;
if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) {
return;
}
if (href.startsWith('http') && !href.startsWith(window.location.origin)) {
return;
}
e.preventDefault();
if (isNavigating) return;
loadPage(href, link);
});
}
function setupPageNavigation() {
document.querySelectorAll('.page-nav').forEach(function(nav) {
nav.addEventListener('click', function(e) {
if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) {
return;
}
e.preventDefault();
if (isNavigating) return;
var href = this.getAttribute('href');
if (!href) return;
loadPage(href, null);
});
});
}
function loadPage(url, clickedLink) {
if (isNavigating) return;
isNavigating = true;
document.body.classList.add('loading');
var absoluteUrl = new URL(url, baseUrl).href;
var hashIndex = url.indexOf('#');
var hash = hashIndex !== -1 ? url.substring(hashIndex + 1) : null;
fetch(absoluteUrl)
.then(function(response) {
if (!response.ok) throw new Error('Page not found');
return response.text();
})
.then(function(html) {
var parser = new DOMParser();
var doc = parser.parseFromString(html, 'text/html');
var newContent = doc.querySelector('.markdown-section');
var currentContent = document.querySelector('.markdown-section');
if (newContent && currentContent) {
currentContent.innerHTML = newContent.innerHTML;
}
var newTitle = doc.querySelector('title');
if (newTitle) {
document.title = newTitle.textContent;
}
document.querySelectorAll('.book-summary .chapter.active').forEach(function(ch) {
ch.classList.remove('active');
});
var newActiveHref = url.replace(/^\.\//, '').split('#')[0];
document.querySelectorAll('.book-summary .chapter a').forEach(function(link) {
var href = link.getAttribute('href');
if (href === newActiveHref || href === './' + newActiveHref) {
var chapter = link.closest('.chapter');
if (chapter) {
chapter.classList.add('active');
var parent = chapter.parentElement;
while (parent) {
if (parent.classList && parent.classList.contains('chapter')) {
parent.classList.add('expanded');
}
parent = parent.parentElement;
}
}
}
});
history.pushState(null, '', absoluteUrl);
if (hash) {
try {
var decodedHash = decodeURIComponent(hash);
var target = document.getElementById(decodedHash);
if (target) {
setTimeout(function() {
target.scrollIntoView({ behavior: 'auto' });
}, 50);
} else {
window.scrollTo(0, 0);
}
} catch (ex) {
window.scrollTo(0, 0);
}
} else {
window.scrollTo(0, 0);
}
if (typeof mermaid !== 'undefined') {
mermaid.init(undefined, '.markdown-section .mermaid');
}
if (typeof hljs !== 'undefined') {
document.querySelectorAll('.markdown-section pre code').forEach(function(block) {
hljs.highlightElement(block);
});
}
if (window.guidebookFontsettings && window.guidebookFontsettings.reapply) {
window.guidebookFontsettings.reapply();
}
var newToc = doc.querySelector('.page-toc');
var currentToc = document.querySelector('.page-toc');
var newTocToggle = doc.querySelector('.toc-toggle');
var currentTocToggle = document.querySelector('.toc-toggle');
if (currentToc) currentToc.remove();
if (currentTocToggle) currentTocToggle.remove();
if (newToc) {
var bookBody = document.querySelector('.book-body');
if (bookBody) {
var tocClone = newToc.cloneNode(true);
bookBody.insertBefore(tocClone, bookBody.querySelector('.body-inner'));
if (newTocToggle) {
var toggleClone = newTocToggle.cloneNode(true);
bookBody.insertBefore(toggleClone, tocClone);
toggleClone.addEventListener('click', function() {
if (window.innerWidth > 768) {
document.querySelector('.book').classList.toggle('toc-hidden');
var isHidden = document.querySelector('.book').classList.contains('toc-hidden');
localStorage.setItem('guidebook-toc-hidden', isHidden);
}
});
}
setupTocScrollSpy();
setupTocLinks();
}
}
var newPrev = doc.querySelector('.page-nav.prev');
var newNext = doc.querySelector('.page-nav.next');
var currentPrev = document.querySelector('.page-nav.prev');
var currentNext = document.querySelector('.page-nav.next');
if (currentPrev) currentPrev.remove();
if (currentNext) currentNext.remove();
var bodyInner = document.querySelector('.body-inner');
if (bodyInner) {
if (newPrev) {
var prevClone = newPrev.cloneNode(true);
bodyInner.insertBefore(prevClone, bodyInner.firstChild);
}
if (newNext) {
var nextClone = newNext.cloneNode(true);
bodyInner.insertBefore(nextClone, bodyInner.querySelector('.page-wrapper'));
}
setupPageNavigation();
}
isNavigating = false;
document.body.classList.remove('loading');
})
.catch(function(err) {
console.error('Navigation error:', err);
isNavigating = false;
document.body.classList.remove('loading');
window.location.href = url;
});
}
window.addEventListener('popstate', function() {
loadPage(location.pathname + location.hash, null);
});
setupSpaNavigation();
setupPageNavigation();
function scrollToHashOnLoad() {
if (!window.location.hash) return;
var hash = window.location.hash.substring(1);
try {
hash = decodeURIComponent(hash);
} catch (ex) {
}
var target = document.getElementById(hash);
if (target) {
setTimeout(function() {
target.scrollIntoView({ behavior: 'auto' });
}, 100);
}
}
if (document.readyState === 'complete') {
scrollToHashOnLoad();
} else {
window.addEventListener('load', scrollToHashOnLoad);
}
if (typeof hljs !== 'undefined') {
hljs.highlightAll();
}
})();