document.addEventListener("DOMContentLoaded", () => {
const tocContainer = document.querySelector("[data-toc-list]");
const tocToggleTrigger = document.querySelector("[data-toc-toggle]");
const globalH1 = document.querySelector("h1");
const articleElement = document.querySelector("article");
if (!articleElement) {
return;
}
const articleHeadingsRaw = Array.from(articleElement.querySelectorAll("h2, h3"));
const showHeadings3 = true;
const articleHeadings = showHeadings3
? articleHeadingsRaw
: articleHeadingsRaw.filter((h) => h.tagName !== "H3");
const headings = articleHeadings;
if (!tocContainer || !headings.length) {
return;
}
const tocLineWidthH2 = "0.5rem";
const tocLineWidthH3 = "0.25rem";
const tocLineWidthH2Mini = "0.5rem";
const tocLineWidthH3Mini = "0.25rem";
const scrollOffset = window.innerHeight * 0.05;
const triggerLine = window.innerHeight * 0.3;
let isMiniMode = localStorage.getItem("tocMiniMode") === "true";
let isHovering = false;
let tocItems = [];
let headingData = [];
let previousActiveIndex = -1;
let recalculatePositionsScheduled = false;
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
const calculateAllHeadingPositions = () => {
headingData.forEach((data) => {
const rect = data.element.getBoundingClientRect();
data.top = rect.top + window.pageYOffset;
});
headingData.sort((a, b) => a.top - b.top);
recalculatePositionsScheduled = false;
};
const schedulePositionRecalculation = debounce(() => {
if (!recalculatePositionsScheduled) {
recalculatePositionsScheduled = true;
requestAnimationFrame(calculateAllHeadingPositions);
}
}, 100);
const updateTocVisuals = (forceMode = null) => {
const currentMode = forceMode !== null ? forceMode : isMiniMode;
tocItems.forEach((item) => {
item.classList.toggle("is-mini", currentMode);
const lineEl = item.querySelector(".blog-post-toc_item-line");
const textEl = item.querySelector("div:last-child");
if (!l