import { defineLanguageFacet, foldNodeProp, indentNodeProp, Language, languageDataProp, LanguageDescription, ParseContext } from "@codemirror/language"; import { styleTags, tags as t } from "@codemirror/highlight"; import { Emoji, GFM, MarkdownParser, parser as baseParser, Subscript, Superscript } from "@lezer/markdown"; const data = defineLanguageFacet({ block: { open: "" } }); export const commonmark = baseParser.configure({ props: [ styleTags({ "Blockquote/...": t.quote, HorizontalRule: t.contentSeparator, "ATXHeading1/... SetextHeading1/...": t.heading1, "ATXHeading2/... SetextHeading2/...": t.heading2, "ATXHeading3/...": t.heading3, "ATXHeading4/...": t.heading4, "ATXHeading5/...": t.heading5, "ATXHeading6/...": t.heading6, "Comment CommentBlock": t.comment, Escape: t.escape, Entity: t.character, "Emphasis/...": t.emphasis, "StrongEmphasis/...": t.strong, "Link/... Image/...": t.link, "OrderedList/... BulletList/...": t.list, "InlineCode CodeText": t.monospace, URL: t.url, "HeaderMark HardBreak QuoteMark ListMark LinkMark EmphasisMark CodeMark": t.processingInstruction, "CodeInfo LinkLabel": t.labelName, LinkTitle: t.string, Paragraph: t.content, }), foldNodeProp.add((type) => { if (!type.is("Block") || type.is("Document")) return undefined; return (tree, state) => ({ from: state.doc.lineAt(tree.from).to, to: tree.to, }); }), indentNodeProp.add({ Document: () => null, }), languageDataProp.add({ Document: data, }), ], }); export function mkLang(parser: MarkdownParser) { return new Language( data, parser, parser.nodeSet.types.find((t) => t.name == "Document")! ); } /// Language support for strict CommonMark. export const commonmarkLanguage = mkLang(commonmark); const extended = commonmark.configure([ GFM, Subscript, Superscript, Emoji, { props: [ styleTags({ "TableDelimiter SubscriptMark SuperscriptMark StrikethroughMark": t.processingInstruction, "TableHeader/...": t.heading, "Strikethrough/...": t.strikethrough, TaskMarker: t.atom, Task: t.list, Emoji: t.character, "Subscript Superscript": t.special(t.content), TableCell: t.content, }), ], }, ]); /// Language support for [GFM](https://github.github.com/gfm/) plus /// subscript, superscript, and emoji syntax. export const markdownLanguage = mkLang(extended); export function getCodeParser( languages: readonly LanguageDescription[], defaultLanguage?: Language ) { return (info: string) => { let found = info && LanguageDescription.matchLanguageName(languages, info, true); if (!found) return defaultLanguage ? defaultLanguage.parser : null; if (found.support) return found.support.language.parser; return ParseContext.getSkippingParser(found.load()); }; }