Render math in chat messages with KaTeX

Add a marked extension that tokenizes math delimiters and renders them
with KaTeX: `$$ ... $$` / `\[ ... \]` as block, `$ ... $` / `\( ... \)`
and mid-paragraph `$$ ... $$` as inline.

Inline `$ ... $` requires a non-space after the opening `$`, no newline
inside, and a non-digit after the closing `$`, so prose like "$100 から
$200" is left alone; `\$` still escapes a literal dollar sign. Parse
errors fall back to KaTeX's red inline message instead of throwing, and
math whose closing delimiter has not streamed in yet stays plain text.

DOMPurify strips `semantics` and `annotation` by default, which would
leak the raw TeX out of KaTeX's MathML output, so both are allowed
explicitly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-23 20:10:03 +09:00
co-authored by Claude Opus 5
parent 8cac5d0de0
commit 4882d291be
6 changed files with 151 additions and 1 deletions
+7
View File
@@ -201,6 +201,13 @@ frontend/src/
- アシスタントメッセージのみ `marked` で HTML に変換後 `DOMPurify` でサニタイズ
- ストリーミング中(`pending=true`)は未閉じのコードフェンス(` ``` `)を自動補完してから描画
- 数式は `src/utils/math.ts` の marked 拡張が KaTeX で描画する(`mathExtension` / `mathSanitizeConfig`)
- ブロック: 行頭の `$$ ... $$` と `\[ ... \]`。インライン: `$ ... $`、`\( ... \)`、行中の `$$ ... $$`
- `$ ... $` は誤爆防止のため「開き `$` の直後が空白でない」「中身に改行を含まない」「閉じ `$` の直後が数字でない」を満たすものだけを数式にする(`$100 から $200` のような金額表記は素通しする)。リテラルのドル記号は `\$` でエスケープできる
- インラインコード・コードフェンス内の `$` は marked のトークナイザ順により数式にならない
- 構文エラーは例外にせず KaTeX の赤字表示にフォールバックする(`throwOnError: false`)
- KaTeX の MathML 出力に含まれる `semantics` / `annotation` は DOMPurify の既定では許可されないため、`mathSanitizeConfig` で明示的に許可している
- ストリーミング途中で閉じ記号が未到達の数式は、閉じるまでプレーンテキストとして表示される
### Vite プロキシ設定