UNPKG

@astrojs/markdoc

Version:
63 lines (62 loc) 2 kB
import Markdoc, { } from "@markdoc/markdoc"; import Slugger from "github-slugger"; import { getTextContent } from "./runtime.js"; import { MarkdocError } from "./utils.js"; function getSlug(attributes, children, headingSlugger, experimentalHeadingIdCompat) { if (attributes.id && typeof attributes.id === "string") { return attributes.id; } const textContent = attributes.content ?? getTextContent(children); let slug = headingSlugger.slug(textContent); if (!experimentalHeadingIdCompat) { if (slug.endsWith("-")) slug = slug.slice(0, -1); } return slug; } const heading = { children: ["inline"], attributes: { id: { type: String }, level: { type: Number, required: true, default: 1 } }, transform(node, config) { const { level, ...attributes } = node.transformAttributes(config); const children = node.transformChildren(config); if (!config.ctx?.headingSlugger) { throw new MarkdocError({ message: "Unexpected problem adding heading IDs to Markdoc file. Did you modify the `ctx.headingSlugger` property in your Markdoc config?" }); } const slug = getSlug( attributes, children, config.ctx.headingSlugger, config.ctx.experimentalHeadingIdCompat ); const render = config.nodes?.heading?.render ?? `h${level}`; const tagProps = ( // For components, pass down `level` as a prop, // alongside `__collectHeading` for our `headings` collector. // Avoid accidentally rendering `level` as an HTML attribute otherwise! typeof render === "string" ? { ...attributes, id: slug } : { ...attributes, id: slug, __collectHeading: true, level } ); return new Markdoc.Tag(render, tagProps, children); } }; function setupHeadingConfig(experimentalHeadingIdCompat) { const headingSlugger = new Slugger(); return { ctx: { headingSlugger, experimentalHeadingIdCompat }, nodes: { heading } }; } export { heading, setupHeadingConfig };