fix(app): only allow \(...\) syntax for inline latex (#34850)

This commit is contained in:
Brendan Allan
2026-07-02 13:02:17 +08:00
committed by GitHub
parent a0d64b12c9
commit 5fecf7ae9e
+55 -9
View File
@@ -1,5 +1,4 @@
import { marked } from "marked"
import markedKatex from "marked-katex-extension"
import { marked, type MarkedExtension, type Tokens } from "marked"
import markedShiki from "marked-shiki"
import katex from "katex"
import { bundledLanguages, type BundledLanguage } from "shiki"
@@ -395,8 +394,8 @@ function renderMathInText(text: string): string {
}
})
// Inline math: $...$
const inlineMathRegex = /(?<!\$)\$(?!\$)((?:[^$\\]|\\.)+?)\$(?!\$)/g
// Inline math: \(...\)
const inlineMathRegex = /\\\(((?:\\.|[^\\\n])*?)\\\)/g
result = result.replace(inlineMathRegex, (_, math) => {
try {
return katex.renderToString(math, {
@@ -404,13 +403,63 @@ function renderMathInText(text: string): string {
throwOnError: false,
})
} catch {
return `$${math}$`
return `\\(${math}\\)`
}
})
return result
}
const inlineMathRegex = /^\\\(((?:\\.|[^\\\n])*?)\\\)/
const blockMathRegex = /^\$\$\n([\s\S]+?)\n\$\$(?:\n|$)/
const katexExtension: MarkedExtension = {
extensions: [
{
name: "inlineKatex",
level: "inline",
start(src) {
const index = src.indexOf("\\(")
if (index === -1) return
return index
},
tokenizer(src) {
const match = src.match(inlineMathRegex)
if (!match) return
return {
type: "inlineKatex",
raw: match[0],
text: match[1].trim(),
displayMode: false,
}
},
renderer: renderKatexToken,
},
{
name: "blockKatex",
level: "block",
tokenizer(src) {
const match = src.match(blockMathRegex)
if (!match) return
return {
type: "blockKatex",
raw: match[0],
text: match[1].trim(),
displayMode: true,
}
},
renderer: renderKatexToken,
},
],
}
function renderKatexToken(token: Tokens.Generic) {
return katex.renderToString(typeof token.text === "string" ? token.text : "", {
displayMode: token.displayMode === true,
throwOnError: false,
})
}
function renderMathExpressions(html: string): string {
// Split on code/pre/kbd tags to avoid processing their contents
const codeBlockPattern = /(<(?:pre|code|kbd)[^>]*>[\s\S]*?<\/(?:pre|code|kbd)>)/gi
@@ -480,10 +529,7 @@ export const { use: useMarked, provider: MarkedProvider } = createSimpleContext(
},
},
},
markedKatex({
throwOnError: false,
nonStandard: true,
}),
katexExtension,
markedShiki({
async highlight(code, lang) {
const highlighter = await getSharedHighlighter({