Spaces:
Running
Running
import type { | |
Element, | |
MarkdownExtension, | |
BlockContext, | |
Line | |
} from "@lezer/markdown"; | |
import { parseMixed } from "@lezer/common"; | |
import { yaml } from "@codemirror/legacy-modes/mode/yaml"; | |
import { foldInside, foldNodeProp, StreamLanguage } from "@codemirror/language"; | |
import { styleTags, tags } from "@lezer/highlight"; | |
const frontMatterFence = /^---\s*$/m; | |
export const frontmatter: MarkdownExtension = { | |
defineNodes: [{ name: "Frontmatter", block: true }, "FrontmatterMark"], | |
props: [ | |
styleTags({ | |
Frontmatter: [tags.documentMeta, tags.monospace], | |
FrontmatterMark: tags.processingInstruction | |
}), | |
foldNodeProp.add({ | |
Frontmatter: foldInside, | |
FrontmatterMark: () => null | |
}) | |
], | |
wrap: parseMixed((node) => { | |
const { parser } = StreamLanguage.define(yaml); | |
if (node.type.name === "Frontmatter") { | |
return { | |
parser, | |
overlay: [{ from: node.from + 4, to: node.to - 4 }] | |
}; | |
} | |
return null; | |
}), | |
parseBlock: [ | |
{ | |
name: "Frontmatter", | |
before: "HorizontalRule", | |
parse: (cx: BlockContext, line: Line): boolean => { | |
let end: number | undefined = undefined; | |
const children = new Array<Element>(); | |
if (cx.lineStart === 0 && frontMatterFence.test(line.text)) { | |
children.push(cx.elt("FrontmatterMark", 0, 4)); | |
while (cx.nextLine()) { | |
if (frontMatterFence.test(line.text)) { | |
end = cx.lineStart + 4; | |
break; | |
} | |
} | |
if (end !== undefined) { | |
children.push(cx.elt("FrontmatterMark", end - 4, end)); | |
cx.addElement(cx.elt("Frontmatter", 0, end, children)); | |
} | |
return true; | |
} | |
return false; | |
} | |
} | |
] | |
}; | |