57 lines
2.8 KiB
TypeScript
57 lines
2.8 KiB
TypeScript
|
import {Prec} from "@codemirror/state"
|
||
|
import {KeyBinding, keymap} from "@codemirror/view"
|
||
|
import {Language, LanguageSupport, LanguageDescription} from "@codemirror/language"
|
||
|
import {MarkdownExtension, MarkdownParser, parseCode} from "@lezer/markdown"
|
||
|
import {html} from "@codemirror/lang-html"
|
||
|
import {commonmarkLanguage, markdownLanguage, mkLang, getCodeParser} from "./markdown"
|
||
|
import {insertNewlineContinueMarkup, deleteMarkupBackward} from "./commands"
|
||
|
export {commonmarkLanguage, markdownLanguage, insertNewlineContinueMarkup, deleteMarkupBackward}
|
||
|
|
||
|
/// A small keymap with Markdown-specific bindings. Binds Enter to
|
||
|
/// [`insertNewlineContinueMarkup`](#lang-markdown.insertNewlineContinueMarkup)
|
||
|
/// and Backspace to
|
||
|
/// [`deleteMarkupBackward`](#lang-markdown.deleteMarkupBackward).
|
||
|
export const markdownKeymap: readonly KeyBinding[] = [
|
||
|
{key: "Enter", run: insertNewlineContinueMarkup},
|
||
|
{key: "Backspace", run: deleteMarkupBackward}
|
||
|
]
|
||
|
|
||
|
const htmlNoMatch = html({matchClosingTags: false})
|
||
|
|
||
|
/// Markdown language support.
|
||
|
export function markdown(config: {
|
||
|
/// When given, this language will be used by default to parse code
|
||
|
/// blocks.
|
||
|
defaultCodeLanguage?: Language | LanguageSupport,
|
||
|
/// A collection of language descriptions to search through for a
|
||
|
/// matching language (with
|
||
|
/// [`LanguageDescription.matchLanguageName`](#language.LanguageDescription^matchLanguageName))
|
||
|
/// when a fenced code block has an info string.
|
||
|
codeLanguages?: readonly LanguageDescription[],
|
||
|
/// Set this to false to disable installation of the Markdown
|
||
|
/// [keymap](#lang-markdown.markdownKeymap).
|
||
|
addKeymap?: boolean,
|
||
|
/// Markdown parser
|
||
|
/// [extensions](https://github.com/lezer-parser/markdown#user-content-markdownextension)
|
||
|
/// to add to the parser.
|
||
|
extensions?: MarkdownExtension,
|
||
|
/// The base language to use. Defaults to
|
||
|
/// [`commonmarkLanguage`](#lang-markdown.commonmarkLanguage).
|
||
|
base?: Language
|
||
|
} = {}) {
|
||
|
let {codeLanguages, defaultCodeLanguage, addKeymap = true, base: {parser} = commonmarkLanguage} = config
|
||
|
if (!(parser instanceof MarkdownParser)) throw new RangeError("Base parser provided to `markdown` should be a Markdown parser")
|
||
|
let extensions = config.extensions ? [config.extensions] : []
|
||
|
let support = [htmlNoMatch.support], defaultCode
|
||
|
if (defaultCodeLanguage instanceof LanguageSupport) {
|
||
|
support.push(defaultCodeLanguage.support)
|
||
|
defaultCode = defaultCodeLanguage.language
|
||
|
} else if (defaultCodeLanguage) {
|
||
|
defaultCode = defaultCodeLanguage
|
||
|
}
|
||
|
let codeParser = codeLanguages || defaultCode ? getCodeParser(codeLanguages || [], defaultCode) : undefined
|
||
|
extensions.push(parseCode({codeParser, htmlParser: htmlNoMatch.language.parser}))
|
||
|
if (addKeymap) support.push(Prec.high(keymap.of(markdownKeymap)))
|
||
|
return new LanguageSupport(mkLang(parser.configure(extensions)), support)
|
||
|
}
|