mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-12 13:13:45 +01:00
Add support for rendering math in Markdown with MathJax
GitOrigin-RevId: dd1c1c72237a5364c642e46c66e08ea7a6977662
This commit is contained in:
committed by
Copybot
parent
ef05288f81
commit
63a605484c
@@ -2,6 +2,7 @@ import { markdown as markdownLanguage } from '@codemirror/lang-markdown'
|
||||
import { shortcuts } from './shortcuts'
|
||||
import { languages } from '../index'
|
||||
import { Strikethrough, Table } from '@lezer/markdown'
|
||||
import { Math } from './math'
|
||||
import {
|
||||
HighlightStyle,
|
||||
LanguageSupport,
|
||||
@@ -12,7 +13,7 @@ import { tags } from '@lezer/highlight'
|
||||
export const markdown = () => {
|
||||
const { language, support } = markdownLanguage({
|
||||
codeLanguages: languages,
|
||||
extensions: [Strikethrough, Table],
|
||||
extensions: [Strikethrough, Table, Math],
|
||||
})
|
||||
|
||||
return new LanguageSupport(language, [
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import { InlineContext, MarkdownConfig, InlineParser } from '@lezer/markdown'
|
||||
|
||||
const DOLLAR = 36 /* '$' */
|
||||
|
||||
// Whitespace (including the start/end of the inline section, where `char`
|
||||
// returns -1).
|
||||
const isSpace = (code: number) =>
|
||||
code === -1 || code === 32 || code === 9 || code === 10 || code === 13
|
||||
|
||||
const isDigit = (code: number) => code >= 48 && code <= 57
|
||||
|
||||
const InlineMathDelim = { resolve: 'InlineMath', mark: 'InlineMathMark' }
|
||||
const BlockMathDelim = { resolve: 'BlockMath', mark: 'BlockMathMark' }
|
||||
|
||||
// Inline parsing runs over the whole paragraph, so `$$…$$` handles multi-line
|
||||
// equations as long as there is no blank line inside them.
|
||||
const blockMathParser: InlineParser = {
|
||||
name: 'BlockMath',
|
||||
parse(cx: InlineContext, next: number, pos: number) {
|
||||
if (next !== DOLLAR || cx.char(pos + 1) !== DOLLAR) {
|
||||
return -1
|
||||
}
|
||||
return cx.addDelimiter(BlockMathDelim, pos, pos + 2, true, true)
|
||||
},
|
||||
// Run before the default `Emphasis` parser, and (via `InlineMath`'s `after`)
|
||||
// before the single-dollar inline parser, so `$$` is matched as a display
|
||||
// delimiter rather than two empty inline ones.
|
||||
before: 'Emphasis',
|
||||
}
|
||||
|
||||
const inlineMathParser: InlineParser = {
|
||||
name: 'InlineMath',
|
||||
parse(cx: InlineContext, next: number, pos: number) {
|
||||
if (next !== DOLLAR) {
|
||||
return -1
|
||||
}
|
||||
const before = cx.char(pos - 1)
|
||||
const after = cx.char(pos + 1)
|
||||
const canOpen = !isSpace(after)
|
||||
const canClose = !isSpace(before) && !isDigit(after)
|
||||
if (!canOpen && !canClose) {
|
||||
return -1
|
||||
}
|
||||
return cx.addDelimiter(InlineMathDelim, pos, pos + 1, canOpen, canClose)
|
||||
},
|
||||
// Run after `BlockMath` so `$$` is tried as a display delimiter first, but
|
||||
// still before `Emphasis`. The default `Escape` parser consumes `\$` first.
|
||||
after: 'BlockMath',
|
||||
}
|
||||
|
||||
export const Math: MarkdownConfig = {
|
||||
// No `style` is set on these nodes: math is rendered by the visual editor
|
||||
// (which slices the raw source), so the grammar change stays inert for
|
||||
// source-mode syntax highlighting and non-experiment users.
|
||||
defineNodes: ['InlineMath', 'InlineMathMark', 'BlockMath', 'BlockMathMark'],
|
||||
parseInline: [blockMathParser, inlineMathParser],
|
||||
}
|
||||
Reference in New Issue
Block a user