| | |
| | | import { Root, Element, ElementContent } from "hast" |
| | | import { GlobalConfiguration } from "../cfg" |
| | | import { i18n } from "../i18n" |
| | | import { styleText } from "util" |
| | | |
| | | interface RenderComponents { |
| | | head: QuartzComponent |
| | |
| | | cfg: GlobalConfiguration, |
| | | slug: FullSlug, |
| | | componentData: QuartzComponentProps, |
| | | visited: Set<FullSlug>, |
| | | ) { |
| | | // process transcludes in componentData |
| | | visit(root, "element", (node, _index, _parent) => { |
| | |
| | | if (classNames.includes("transclude")) { |
| | | const inner = node.children[0] as Element |
| | | const transcludeTarget = (inner.properties["data-slug"] ?? slug) as FullSlug |
| | | if (visited.has(transcludeTarget)) { |
| | | console.warn( |
| | | styleText( |
| | | "yellow", |
| | | `Warning: Skipping circular transclusion: ${slug} -> ${transcludeTarget}`, |
| | | ), |
| | | ) |
| | | node.children = [ |
| | | { |
| | | type: "element", |
| | | tagName: "p", |
| | | properties: { style: "color: var(--secondary);" }, |
| | | children: [ |
| | | { |
| | | type: "text", |
| | | value: `Circular transclusion detected: ${transcludeTarget}`, |
| | | }, |
| | | ], |
| | | }, |
| | | ] |
| | | return |
| | | } |
| | | visited.add(transcludeTarget) |
| | | |
| | | const page = componentData.allFiles.find((f) => f.slug === transcludeTarget) |
| | | if (!page) { |
| | | return |
| | |
| | | // make a deep copy of the tree so we don't remove the transclusion references |
| | | // for the file cached in contentMap in build.ts |
| | | const root = clone(componentData.tree) as Root |
| | | renderTranscludes(root, cfg, slug, componentData) |
| | | const visited = new Set<FullSlug>([slug]) |
| | | renderTranscludes(root, cfg, slug, componentData, visited) |
| | | |
| | | // set componentData.tree to the edited html that has transclusions rendered |
| | | componentData.tree = root |