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) +}