docs/headers.js

88 lines
2.7 KiB
JavaScript

for (const el of document.querySelectorAll("[id]")) {
if (el.tagName === "marker") continue;
el.classList.add("haspara");
const pilcrow = document.createElement("a");
pilcrow.className = "pilcrow";
pilcrow.href = "#" + el.id;
pilcrow.innerHTML = "¶";
el.prepend(pilcrow);
}
const foldable = (root, children) => {
let state = true;
root.addEventListener("click", (e) => {
if (e.target.classList.contains("pilcrow")) state = true;
else state = !state;
if (state) children.classList.remove("closed");
else children.classList.add("closed");
if (state) root.classList.remove("closed");
else root.classList.add("closed");
});
root.classList.add("toggle-root");
};
const make_foldable = (root) => {
const child_stacks = new Array(10).fill(null).map(() => ({ children: [], root: null }));
const flush_header = (this_level, sibling) => {
for (let level = 9; level >= this_level; level--) {
const stack = child_stacks[level];
if (!stack.root) continue;
const new_e = document.createElement("div");
new_e.classList.add("toggle-section");
for (const old_e of stack.children) {
old_e.remove();
new_e.appendChild(old_e);
}
if (stack.root.tagName !== "H1") foldable(stack.root, new_e);
let parent_level;
for (parent_level = level - 1; parent_level > 0; parent_level--) if (child_stacks[parent_level].root) break;
if (parent_level === -1) {
if (sibling) root.insertBefore(new_e, sibling);
else root.appendChild(new_e);
} else {
stack.root.remove();
child_stacks[parent_level].children.push(stack.root);
child_stacks[parent_level].children.push(new_e);
}
stack.root = null;
stack.children.length = 0;
}
};
let end = null;
for (const child of [...root.children]) {
if (child.tagName === "FOOTER") {
end = child;
break;
}
if (/^H\d$/.test(child.tagName)) {
const this_level = parseInt(child.tagName[1]) - 1;
flush_header(this_level, child);
child_stacks[this_level].root = child;
continue;
}
for (let level = 9; level >= 0; level--) {
if (child_stacks[level].root) {
child_stacks[level].children.push(child);
break;
}
}
}
for (let level = 9; level >= 0; level--) {
flush_header(level, end);
}
};
make_foldable(document.body);