UNPKG

@nuxtjs/mdc

Version:
91 lines (90 loc) 3.43 kB
import { toString } from "hast-util-to-string"; import Slugger from "github-slugger"; import { validateProps } from "./utils/props.js"; export function compileHast(options = {}) { const slugs = new Slugger(); function compileToJSON(node, parent) { if (node.type === "root") { return { type: "root", children: node.children.map((child) => compileToJSON(child, node)).filter(Boolean) }; } const position = node.position?.start?.offset && node.position?.end?.offset ? { start: node.position.start.offset, end: node.position.end.offset } : void 0; if (node.type === "element") { if (node.tagName === "p" && node.children.every((child) => child.type === "text" && /^\s*$/.test(child.value))) { return null; } if (node.tagName === "li") { let hasPreviousParagraph = false; node.children = node.children?.flatMap((child) => { if (child.type === "element" && child.tagName === "p") { if (hasPreviousParagraph) { child.children.unshift({ type: "element", tagName: "br", properties: {}, children: [] }); } hasPreviousParagraph = true; return child.children; } return child; }); } if (node.tagName?.match(/^h\d$/)) { node.properties = node.properties || {}; node.properties.id = String(node.properties?.id || slugs.slug(toString(node))).replace(/-+/g, "-").replace(/^-|-$/g, "").replace(/^(\d)/, "_$1"); } if (node.tagName === "component-slot") { node.tagName = "template"; } const children = (node.tagName === "template" && node.content?.children.length ? node.content.children : node.children).map((child) => compileToJSON(child, node)).filter(Boolean); const result = { type: "element", tag: node.tagName, props: validateProps(node.tagName, node.properties), children }; if (options.keepPosition) { result.position = position; } return result; } if (node.type === "text") { if (!/^\n+$/.test(node.value || "") || parent?.properties?.emptyLinePlaceholder) { return options.keepPosition ? { type: "text", value: node.value, position } : { type: "text", value: node.value }; } } if (options.keepComments && node.type === "comment") { return options.keepPosition ? { type: "comment", value: node.value, position } : { type: "comment", value: node.value }; } return null; } this.Compiler = (tree) => { const body = compileToJSON(tree); let excerpt = void 0; const excerptIndex = tree.children.findIndex((node) => node.type === "comment" && node.value?.trim() === "more"); if (excerptIndex !== -1) { excerpt = compileToJSON({ type: "root", children: tree.children.slice(0, excerptIndex) }); if (excerpt.children.find((node) => node.type === "element" && node.tag === "pre")) { const lastChild = body.children[body.children.length - 1]; if (lastChild.type === "element" && lastChild.tag === "style") { excerpt.children.push(lastChild); } } } body.children = (body.children || []).filter((child) => child.type !== "text"); return { body, excerpt }; }; }