UNPKG

@valaxyjs/utils

Version:

A utility library for Valaxy

83 lines (81 loc) 2.85 kB
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 };