@valaxyjs/utils
Version:
A utility library for Valaxy
83 lines (81 loc) • 2.85 kB
JavaScript
const resolvedHeaders = [];
function buildTree(data, min, max) {
resolvedHeaders.length = 0;
const result = [];
const stack = [];
data.forEach((item) => {
const node = { ...item, children: [] };
let parent = stack[stack.length - 1];
while (parent && parent.level >= node.level) {
stack.pop();
parent = stack[stack.length - 1];
}
if (node.element.classList.contains("ignore-header") || parent && "shouldIgnore" in parent) {
stack.push({ level: node.level, shouldIgnore: true });
return;
}
if (node.level > max || node.level < min)
return;
resolvedHeaders.push({ element: node.element, link: node.link });
if (parent)
parent.children.push(node);
else result.push(node);
stack.push(node);
});
return result;
}
function addToParent(currIndex, headers, levelsRange) {
if (currIndex === 0)
return true;
const currentHeader = headers[currIndex];
for (let index = currIndex - 1; index >= 0; index--) {
const header = headers[index];
if (header.level < currentHeader.level && header.level >= levelsRange[0] && header.level <= levelsRange[1]) {
if (header.children == null)
header.children = [];
header.children.push(currentHeader);
return false;
}
}
return true;
}
function resolveHeaders(headers, range = [2, 4]) {
const levelsRange = (typeof range === "object" && !Array.isArray(range) ? range.level : range) || 2;
const [high, low] = typeof levelsRange === "number" ? [levelsRange, levelsRange] : levelsRange === "deep" ? [2, 6] : levelsRange;
return buildTree(headers, high, low);
}
function serializeHeader(h) {
let ret = "";
for (const node of Array.from(h.childNodes)) {
if (node.nodeType === 1) {
if (node.classList.contains("VABadge") || node.classList.contains("header-anchor")) {
continue;
}
ret += node.textContent;
} else if (node.nodeType === 3) {
ret += node.textContent;
}
}
return ret.trim();
}
function getHeaders(options = {
range: [2, 4],
selector: ".markdown-body"
}) {
const mdBodySelector = options.selector || ".markdown-body";
const markdownBodyElements = document.querySelectorAll(mdBodySelector);
const markdownBody = markdownBodyElements[markdownBodyElements.length - 1];
const headers = Array.from(markdownBody?.querySelectorAll(`${mdBodySelector} :where(h1,h2,h3,h4,h5,h6)`) || []).filter((el) => options.filter ? options.filter(el) : true).map((el) => {
const level = Number(el.tagName[1]);
return {
element: el,
title: serializeHeader(el),
link: `#${el.id}`,
level,
// @ts-expect-error lang
lang: el.lang
};
});
return resolveHeaders(headers, options.range);
}
export { addToParent, buildTree, getHeaders, resolveHeaders, resolvedHeaders, serializeHeader };