MathJax.Hub.Config({
config: ["MMLorHTML.js"],
jax: ["input/TeX", "output/HTML-CSS", "output/NativeMML"],
extensions: ["MathMenu.js", "MathZoom.js"]
});
let indexData = null;
async function loadIndex() {
if (indexData) return indexData;
const res = await fetch("/index.json");
indexData = await res.json();
return indexData;
}
const templates = {
folder: i => `
${i.key}
${i.inner} `,
file: i => `${i.title}`
};
function renderTree(data) {
const items = Object.entries(data).map(([key, note]) => {
if (key === "children") return null;
if (note.children) return { type: "folder", key, inner: renderTree(note.children) };
if (note.folder && note.filename) {
const title = note.title || note.filename.replace(/\.md$/, "");
let href = title + ".html";
if (note.folder !== ".") href = `${note.folder}/${href}`;
href = "/" + href;
return { type: "file", href, title };
}
return null;
}).filter((i) => i !== null);
// Sort: folders first (alphabetically), then files (alphabetically)
// Use natural sorting for numbers (1, 2, 10 instead of 1, 10, 2)
items.sort((a, b) => {
if (a.type !== b.type) return a.type === "folder" ? -1 : 1;
const nameA = (a.type === "folder" ? a.key : a.title);
const nameB = (b.type === "folder" ? b.key : b.title);
return nameA.localeCompare(nameB, undefined, { numeric: true, sensitivity: "base" });
});
return `${items.map(i => templates[i.type](i)).join("")}
`;
}
loadIndex().then(data => {
const sidebar = document.querySelector(".sidebar");
if (sidebar) {
sidebar.innerHTML = renderTree(data);
// Find and highlight the current page link
const currentPath = window.location.pathname;
const links = sidebar.querySelectorAll("a");
for (const link of links) {
const linkPath = new URL(link.href, window.location.origin).pathname;
if (linkPath === currentPath) {
link.classList.add("active");
// Expand all parent elements
let parent = link.parentElement;
while (parent && parent !== sidebar) {
if (parent.tagName === "DETAILS") {
parent.open = true;
}
parent = parent.parentElement;
}
break;
}
}
}
});