49 lines
1.2 KiB
JavaScript
Raw Permalink Normal View History

2022-12-24 03:20:02 +09:00
const JSDOM = require("jsdom").JSDOM;
function generateToC(html) {
const dom = JSDOM.fragment(html);
const headings = Array.from(dom.querySelectorAll("h1, h2, h3, h4, h5, h6"))
// Filter headings with ids
.filter((el) => el && el.id)
// {id: string, content: string|null, depth: number}
.map((el) => ({
id: el.id,
content: el.textContent,
depth: Number(el.nodeName.replace("H", "")), // H1 -> 1
}));
let pos = 0;
function genToC(arr, lastDepth) {
const stack = [];
while (pos < arr.length) {
const { depth, id, content } = arr[pos];
if (depth < lastDepth) {
// unwind
pos -= 1;
break;
} else if (depth > lastDepth) {
// nested ToC
stack.push(stack.pop() + genToC(arr, depth));
} else {
// same depth
stack.push(`<a href="#${id}">${content}</a>`);
}
pos += 1;
}
return "<ul>" + stack.map((s) => `<li>${s}</li>`).join("") + "</ul>";
}
return genToC(headings, 1);
}
exports.after_post_render = function (data) {
data.content = data.content.replace("<!-- toc -->", () =>
generateToC(data.content)
);
return data;
};