remark-astro-headings
Version:
A plugin for extracting headings out of MDX files and adding them to the frontmatter.
71 lines • 2.6 kB
JavaScript
/// <reference types="mdast-util-mdxjs-esm" />
import GithubSlugger from 'github-slugger';
import { visit } from 'unist-util-visit';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { fromMarkdown } from 'mdast-util-from-markdown';
import { mdxjs } from 'micromark-extension-mdxjs';
import { mdxFromMarkdown } from 'mdast-util-mdx';
const IMPORT_PATH_REGEX = /from\s+['"]([^'"]+)['"]/;
function remarkAstroHeadings(config = {}) {
const configWithDefaults = {
minDepth: 2,
maxDepth: 6,
createSlugger: () => new GithubSlugger(),
...config,
};
return generateHeadings(configWithDefaults);
}
function generateHeadings(config) {
return (root, VFile) => {
if (!VFile.data.astro) {
console.warn(`[remark-astro-headings] No astro data found in VFile: ${VFile.path}`);
return;
}
const slugger = config.createSlugger();
const dir = join(VFile.path, '..');
const headings = visitDeeply(root, { dir, headings: [], slugger, ...config });
// @ts-ignore - If `astro` is present then frontmatter is also present
VFile.data.astro.frontmatter.headings = headings;
};
}
function visitDeeply(root, config) {
visit(root, ['heading', 'mdxjsEsm'], (child) => {
switch (child.type) {
case 'heading': {
const content = 'value' in child.children[0] && child.children[0].value;
if (!content) {
break;
}
const depth = child.depth;
if (depth < config.minDepth || depth > config.maxDepth) {
break;
}
const slug = config.slugger.slug(content);
config.headings.push({
content,
slug,
depth,
});
break;
}
case 'mdxjsEsm': {
const match = child.value.match(IMPORT_PATH_REGEX);
if (!match) {
break;
}
const importPath = match[1];
const file = readFileSync(join(config.dir, importPath), 'utf-8');
const root = fromMarkdown(file, {
extensions: [mdxjs()],
mdastExtensions: [mdxFromMarkdown()],
});
visitDeeply(root, config);
break;
}
}
});
return config.headings;
}
export default remarkAstroHeadings;
//# sourceMappingURL=index.js.map