Markdown 數學公式渲染規則與排查
觸發鏈路:三條保險,避免技能不執行
本技能透過三條鏈路保證在寫公式時被執行:
- 前置觸發:本條 description 聲明「寫任何數學公式之前」即觸發,不等渲染失敗才補救。
- 工作流掛載:倉庫主技能
math-question-skill(D:\math_question\SKILL.md)的強制規則中引用本技能——做題、講解、每日一題都經過這條鏈路。 - 發布前自檢:含公式的輸出定稿前執行
scripts/check_inline_math.py掃描;發現行內$...$必須改成行間公式或純文字後才可發送/寫入。
核心規則(Codex App 內強制)
Codex 桌面 App 只渲染獨立成行的行間公式 $$...$$,不渲染行內 $...$(官方 issue #14985 確認)。公式本身沒錯,是定界符用錯了:
❌ $f(x)=\sqrt[3]{x}$ ← 行內 $...$,App 不渲染
❌ $\dfrac{f(x_0+h)-f(x_0)}{h}$ ← 行內 $...$,App 不渲染
修法——公式獨立成行,用 $$...$$:
✅ 由
$$
f'(x_0)=\lim_{h\to0}\dfrac{f(x_0+h)-f(x_0)}{h}
$$
可導 ⟺ 該極限存在且有限
行內短表達式用 Unicode 數學符號美化,觀感接近渲染結果:
- 上標/下標:
xˣ(U+02E3)、10⁶、2ⁿ、x₀、x₁ - 根號:
√x(U+221A)、∛x(U+221B 三次根號) - 分數上標式:
x¹⁄³(¹ U+00B9 + ⁄ U+2044 + ³ U+00B3) - 導數撇號:
f′(x)(U+2032,不要用直撇') - 運算/關係符:
·、−、±、∞、≠、≤、≥、∈
⚠️ 不要用 ^(...) 程式撰寫寫法:x^(1/3) 觀感像原始碼;改 ∛x 或 x¹⁄³。
複雜的行內式子(分數、根號、極限)拆成塊級 $$...$$,不要硬塞成純文字。
用戶要求「保留行內公式」時怎麼辦(硬規則不變)
對話中用戶可能說「行內公式保留 $...$、只修空格黏連」——這不改變 App 的渲染行為。行內 $...$ 在 Codex App 一律不渲染,補空格只是「原始碼+空格」,觀感更差,仍算失敗(歷史教訓:修完黏連後用戶仍反饋「這些地方仍然有問題」,根因就是行內 $...$ 未 Unicode 化)。因此:
- 定稿前仍按硬規則執行:行內短式改 Unicode,複雜式拆獨立成行的
$$...$$; - 若用戶明確堅持保留行內
$...$,先說明後果(App 顯示原始碼),並在輸出末尾附「渲染提醒」; - 不要因用戶要求保留而跳過
check_inline_math.py自檢;[FAIL]必須清零才算完成。
行內公式 → Unicode 速查表
| 場景 | 行內 LaTeX(禁止) | Unicode 修法 |
|---|---|---|
| 單字母變數 | $f$、$g$、$A$ | f、g、A(純文字) |
| 上標/下標 | $x^n$、$x_0$、$a_n$ | xⁿ、x₀、aₙ |
| 根式 | $\sqrt{x}$、$\sqrt[3]{x}$ | √x、∛x |
| 分數 | $\frac1n$、$\frac{x^n}{1+x}$ | 短式 1/n;複雜式拆 $$...$$ 塊 |
| 極限 | $\lim_{n\to\infty}a_n$ | lim(n→∞) aₙ(Unicode 無下標箭頭,趨近條件用括號併入 lim;複雜式拆塊) |
| 積分 | $\int_0^1 f(x)\,dx$ | 複雜式拆 $$...$$ 塊,不硬塞行內 |
| 絕對值 | $\lvert x\rvert$ | ` |
| 集合/關係 | $x\in[0,1]$、$f\le g$ | x∈[0,1]、f ≤ g |
| 箭頭 | $x\to0$、$n\to\infty$ | x→0、n→∞ |
| 省略號 | $a_1+\cdots+a_k$ | a₁+…+aₖ |
表格裡的公式(Codex App 第二高發場景)
表格儲存格內 $...$ 不渲染;而 $$...$$ 獨立成行會拆散表格行。表格儲存格裡一律不放公式定界符:
| 做法 | 說明 |
|---|---|
❌ 儲存格寫 $x^{1/3}$ | 行內不渲染,顯示成原始碼 |
❌ 儲存格寫 $$x^{1/3}$$ | 多行定界符拆散表格 |
| ✅ 儲存格只放純文字/Unicode | ∛x、` |
| ✅ 公式放表格下方 | 每個公式獨立成行 $$...$$,跟在表格後 |
| ✅ 內容以公式為主 | 改用結構化列表(小標題 + $$...$$),不用表格 |
範例——三個不可導例子:
| 函數 | x = 0 處失敗模式 |
|---|---|
| ∛x | 垂直切線,差商 → +∞ |
| x·sin(1/x) | 劇烈振盪,極限不存在 |
表格下方放公式:
$$ \lim_{h\to0}\frac{h^{1/3}}{h}=+\infty $$
發布前自檢(30 秒,定稿必做)
⚠️ 先設控制檯編碼為 UTF-8:Windows 預設控制檯是 GBK,腳本輸出含中文或 emoji(如 ✅)時會報 UnicodeEncodeError 或亂碼。跑校驗前先執行:
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
$env:PYTHONIOENCODING = 'utf-8'
聊天回覆草稿:
python "D:\math_question\.agents\skills\markdown-math-render\scripts\check_inline_math.py" - < 草稿.txt
檢查已寫入的檔案:
python "D:\math_question\.agents\skills\markdown-math-render\scripts\check_inline_math.py" "D:\math_question\目標檔案.md"
- 退出碼 0(輸出
[OK])→ 乾淨,可發送/寫入 - 退出碼 0 +
[STYLE]提示 → 有^(...)原始碼式上標(如x^(1/3)),觀感像程式碼,建議改∛x/x¹⁄³或塊級公式(風格建議,不阻塞) - 退出碼 1(輸出
[FAIL]及行號)→ 兩類問題:行內$...$(改成獨立成行的$$...$$或 Unicode 純文字);$$...$$未獨立成行(把$$所在行行首/行尾的文字挪走)。按行號改完重跑直到無[FAIL]
確認公式本身沒壞(30 秒)
倉庫自帶 KaTeX CLI,驗證 TeX 語法:
@'
\dfrac{f(x_0+h)-f(x_0)}{h}
'@ | node scripts/node_modules/katex/cli.js
- 輸出含
<annotation ...>且退出碼 0 → 公式沒問題,是定界符/渲染器問題 - 拋 ParseError → TeX 語法錯,先改公式
一句話原則
在 Codex App 裡,公式一律獨立成行用
$$...$$;行內短式用 Unicode 上/下標美化(xˣ、f′(x));表格儲存格裡不放公式,公式放表格下方;定稿前跑check_inline_math.py兜底,禁止行內$...$。