@tanstack/markdown
Version:
A tiny, fast, deterministic Markdown renderer for blogs and documentation.
52 lines (51 loc) • 2.18 kB
JavaScript
import { plainText } from '../utils.js';
export function headingCollectionExtension(options = {}) {
return {
name: 'heading-collection',
transformDocument(document) {
return {
...document,
headings: collectMarkdownHeadings(document, options),
};
},
};
}
export function collectMarkdownHeadings(document, options = {}) {
const headings = [];
const skip = new Set(options.skipComponentNames ?? ['tabs']);
collectFromBlocks(document.children, headings, undefined, false, skip);
return headings;
}
function collectFromBlocks(blocks, headings, framework, insideSkippedComponent, skipComponentNames) {
for (const block of blocks) {
if (block.type === 'heading') {
if (!insideSkippedComponent && block.id) {
const heading = {
id: block.id,
text: plainText(block.children),
level: block.depth,
};
const headingFramework = block.framework ?? framework;
if (headingFramework)
heading.framework = headingFramework;
headings.push(heading);
}
continue;
}
if (block.type === 'list') {
for (const item of block.items)
collectFromBlocks(item.children, headings, framework, insideSkippedComponent, skipComponentNames);
continue;
}
if (block.type === 'blockquote' || block.type === 'callout') {
collectFromBlocks(block.children, headings, framework, insideSkippedComponent, skipComponentNames);
continue;
}
if (block.type === 'component') {
const name = block.name.toLowerCase();
const nextInsideSkippedComponent = insideSkippedComponent || skipComponentNames.has(name);
const nextFramework = block.tagName === 'md-framework-panel' ? block.properties?.['data-framework'] ?? framework : framework;
collectFromBlocks(block.children, headings, nextFramework, nextInsideSkippedComponent, skipComponentNames);
}
}
}