diff --git a/README.md b/README.md
index 2508d66..8db98e6 100644
--- a/README.md
+++ b/README.md
@@ -36,4 +36,11 @@ The initial implementation of this package was funded by [Braintrust Data](https
parser, extended with
highlighting and indentation information.
-
+
+ yamlFrontmatter(config: {content: Language | LanguageSupport}) → LanguageSupport
+
+Returns language support for a document parsed as config.content
+with an optional YAML "frontmatter" delimited by lines that
+contain three dashes.
+
+
\ No newline at end of file
diff --git a/package.json b/package.json
index e7efa34..4fab931 100644
--- a/package.json
+++ b/package.json
@@ -30,6 +30,7 @@
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@lezer/common": "^1.2.0",
+ "@lezer/highlight": "^1.2.0",
"@lezer/yaml": "^1.0.0"
},
"devDependencies": {
diff --git a/src/README.md b/src/README.md
index 14a7128..fd57b09 100644
--- a/src/README.md
+++ b/src/README.md
@@ -26,3 +26,5 @@ The initial implementation of this package was funded by [Braintrust Data](https
@yaml
@yamlLanguage
+
+@yamlFrontmatter
\ No newline at end of file
diff --git a/src/frontmatter.grammar b/src/frontmatter.grammar
new file mode 100644
index 0000000..6c0b207
--- /dev/null
+++ b/src/frontmatter.grammar
@@ -0,0 +1,14 @@
+@precedence { frontmatter }
+
+@top Document { Frontmatter? Body }
+
+Frontmatter { DashLine FrontmatterContent { line* } DashLine }
+DashLine { !frontmatter dashLine }
+Body { (line | dashLine)* }
+
+@tokens {
+ lineEnd { "\r" | "\n" }
+ dashLine { "---" (lineEnd | @eof) }
+ line { ![\n\r]* lineEnd | ![\n\r]+ @eof }
+ @precedence { dashLine line }
+}
diff --git a/src/frontmatter.grammar.d.ts b/src/frontmatter.grammar.d.ts
new file mode 100644
index 0000000..ab48576
--- /dev/null
+++ b/src/frontmatter.grammar.d.ts
@@ -0,0 +1,2 @@
+import {LRParser} from "@lezer/lr"
+export declare const parser: LRParser
diff --git a/src/yaml.ts b/src/yaml.ts
index d7f02c5..7953c9e 100644
--- a/src/yaml.ts
+++ b/src/yaml.ts
@@ -1,7 +1,9 @@
import {parser} from "@lezer/yaml"
import {LRLanguage, delimitedIndent, indentNodeProp,
- foldNodeProp, foldInside, LanguageSupport} from "@codemirror/language"
-import {SyntaxNode} from "@lezer/common"
+ foldNodeProp, foldInside, Language, LanguageSupport} from "@codemirror/language"
+import {SyntaxNode, parseMixed} from "@lezer/common"
+import {tags, styleTags} from "@lezer/highlight"
+import {parser as frontmatterParser} from "./frontmatter.grammar"
/// A language provider based on the [Lezer YAML
/// parser](https://github.com/lezer-parser/yaml), extended with
@@ -50,3 +52,25 @@ export const yamlLanguage = LRLanguage.define({
export function yaml() {
return new LanguageSupport(yamlLanguage)
}
+
+const frontmatterLanguage = LRLanguage.define({
+ name: "yaml-frontmatter",
+ parser: frontmatterParser.configure({
+ props: [styleTags({DashLine: tags.meta})]
+ })
+})
+
+/// Returns language support for a document parsed as `config.content`
+/// with an optional YAML "frontmatter" delimited by lines that
+/// contain three dashes.
+export function yamlFrontmatter(config: {content: Language | LanguageSupport}) {
+ let {language, support} = config.content instanceof LanguageSupport ? config.content
+ : {language: config.content, support: []}
+ return new LanguageSupport(frontmatterLanguage.configure({
+ wrap: parseMixed(node => {
+ return node.name == "FrontmatterContent" ? {parser: yamlLanguage.parser}
+ : node.name == "Body" ? {parser: language.parser}
+ : null
+ })
+ }), support)
+}