Communityコーディング&開発github.com

gustavdelius/github-markdown-math

GitHub の Markdown で表示する LaTeX 数式($...$ と $$...$$)を、垂直方向に潰れた式、 ag による不具合、 operatorname の許可エラー、 CommonMark によるバックスラッシュの消失などから修正・監査・記述します。README、Issue、Pull Request、Wiki、リポジトリ内のノート向けです。GitHub 上で数式が赤くなったり、異常表示される場合にも使用します。LaTeX、Pandoc、Jupyter、VS Code の出力では不要です。

github-markdown-math とは?

このスキルは、GitHub 上の Markdown ファイル(README、Issue、Pull Request、Wiki、リポジトリ内のノートなど)において、LaTeX 数式($...$ および $$...$$)が正しくレンダリングされるようにするためのルールとスクリプトを提供します。 GitHub の数学レンダリングは、サーバーサイド(cmark-gfm + math sanitizer)とクライアントサイド(MathJax.tex2mml + MathML Core)の2段階で行われますが、それぞれにバグがあり、通常の LaTeX コードが壊れる原因となります。このスキルでは、`\tag` の代わりに `\qquad\text{...}` を使う、`\operatorname` の代わりに `\mathrm` を使う、CommonMark によるバックスラッシュ除去を回避するための `\lbrace` や `\cr` の使用といった具体的なワークアラウンドを提供します。 また、修正を自動化する Python スクリプト(`fix_github_math.py`)が付属しており、`--check` オプションで CI や pre-commit フックとして利用可能です。このスクリプトは正規表現ベースですが、差分を確認することで安全に使用できます。 対応プラットフォームは GitHub のみで、LaTeX、Pandoc、Jupyter、VS Code では不要です。

対応✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/gustavdelius/claude-skills/tree/HEAD/github-markdown-math

Installed? Explore more コーディング&開発 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

GitHub Markdown 数式:レンダリングルールと回避策

GitHub は Markdown の数式を2段階でレンダリングします:

  1. サーバーサイド(cmark-gfm + math sanitizer):$ ... $ と $$ ... $$ の境界を見つけ、CommonMark のバックスラッシュ解除を ASCII 句読点に適用し、許可されていない LaTeX マクロを拒否してから <math-renderer> タグを出力します。
  2. **クライアントサイド(<math-renderer> + MathJax.tex2mml):**TeX を MathML に変換し、ネイティブブラウザの MathML Core レイアウトのためにページに注入します。

両方の段階にバグがあり、通常の LaTeX が壊れる原因となります。以下のルールは、それらのバグに対する回避策です。

このスキルを使うべき時

  • GitHub で読まれる .md ファイルに数式を書いたり編集したりするとき。
  • GitHub 上で数式が潰れて表示されたり、赤くなったり、生の $$ テキストとして表示される場合の修正。
  • LaTeX、Pandoc、Jupyter、MkDocs、VS Code のみを通すファイルでは不要です。ファイルが両方の場所で読まれる場合、以下の置き換えは通常の TeX/MathJax であるため、他の場所でもレンダリングされます。

ワークフロー

  1. 記述中は、以下のルール1〜4に従います。
  2. コミット前に、変更された Markdown ファイルに対してチェックスクリプトを実行します(スクリプトを参照)。--check なしで実行すると、その場で修正します。
  3. git diff で結果を確認します。スクリプトは正規表現ベースなので、出力は下書きとして扱います。レンダリングはローカルでは確認できません。不明な場合は GitHub でプレビューします。

クイックリファレンス

代わりに使用しないもの代わりに使用するもの理由
\tag{2.1}\qquad\text{(2.1)}\tag は数式を垂直方向の細い帯に潰します
\operatorname{Foo}\mathrm{Foo}operatorname はサニタイザーによってブロックされます
\mathrm{Im} D_t\mathrm{Im}\thinspace D_t演算子の間隔を復元します
\hbox{...}、{\rm ...}\text{...}、{\mathrm{...}}プレーン TeX マクロはブロックされます
\{、\}\lbrace、\rbraceCommonMark は \{ を { に変換します
1行の \\\crCommonMark は \\ を \ に変換します
\,\thinspaceCommonMark は \, を , に変換します
\, は, 二重カンマとしてレンダリングされる可能性があります
q_*(1つのブロック内に複数の *)q_\astペアになった * は Markdown の強調になります

1. \tag{...} を使用しないでください(1文字の垂直方向の潰れを防ぐ)

  • バグ:MathJax.tex2mml は、\tag{2.1} を含む数式を <mtable displaystyle="true"><mlabeledtr><mtd>... としてシリアル化します。ブラウザの MathML Core 仕様は <mlabeledtr> を削除したため、Chromium/Blink と Firefox はそれをテーブル行として扱わず、数式を1文字幅の列に押し込みます。
  • **回避策:**代わりに、\qquad\text{(2.1)} をディスプレイ数式の最後に置きます。ラベルにプライムが必要な場合は、ネストされた $\tag{3.3$'$}$ ではなく、Unicode の ′ を \text{(3.3′)} 内で使用します。
<!-- GitHub では壊れます(垂直方向の列に潰れます) -->
$$
\partial_t \mathcal{Q} + \partial_x \mathcal{J} = 0 \tag{2.1}
$$

<!-- GitHub では機能します -->
$$
\partial_t \mathcal{Q} + \partial_x \mathcal{J} = 0 \qquad\text{(2.1)}
$$

2. \operatorname{...}、\hbox{...}、{\rm ...} を使用しないでください(許可されていないマクロエラーを防ぐ)

  • **バグ:**GitHub のサーバーサイドサニタイザーは、\operatorname と \operatorname* を「次のマクロは許可されていません:operatorname」というバナーでブロックします。
  • 回避策:
    • \operatorname{Foo} を \mathrm{Foo} に置き換えます。直後に文字やバックスラッシュマクロが続く場合(例:\operatorname{Im} D_t や \operatorname{pr} v)、\thinspace を追加して(\mathrm{Im}\thinspace D_t)演算子の間隔を維持します。
    • プレーン TeX の \hbox{...} を \text{...} に置き換え、{\rm ...} を {\mathrm{...}} に置き換えます。
<!-- GitHub では壊れます(「次のマクロは許可されていません:operatorname」) -->
$\operatorname{diag}(1, -1)$ and $\operatorname{Im} D_t$

<!-- GitHub では機能します -->
$\mathrm{diag}(1, -1)$ and $\mathrm{Im}\thinspace D_t$

3. 区切り文字、スペース、改行が CommonMark のアンエスケープを生き残るようにする

  • **バグ:**数式が <math-renderer> に到達する前に、GitHub の Markdown パーサーは $ ... $ と $$ ... $$ の内部で CommonMark の ASCII 句読点アンエスケープを適用します:
    • \{ は { に、\} は } になります。これにより、\left\{ で「Missing or unrecognized delimiter for \left」が発生し、ポアソン括弧 \{F, G\} から中括弧が静かに削除されます。
    • \\(改行が続かない場合)は \ になります。これにより、単一行の行列とケース(例:\begin{pmatrix} 0 & 1 \\ -1 & 0 \end{pmatrix})が \-1 に壊れ、赤い未定義マクロエラーが発生します。
    • \, は ,,(二重カンマ)になり、\, は ,(dx の前のリテラルカンマ)になります。
    • 数式ブロック内でペアになった *(例:U_+(z - 2q_*), \quad z = w + Dq_*)は、Markdown の <em> 強調として解析される可能性があります。
  • 回避策:
    • \{ と \} の代わりに \lbrace と \rbrace を使用します(文字が続く場合はスペースを追加:\lbrace F, G\rbrace)。
    • 単一行の行列や環境での改行には \\ の代わりに \cr を使用するか、複数行の $$ ... $$ ブロック内では \\ の直後に改行を入れます。
    • \, の代わりに \thinspace を使用し(文字の前に末尾スペース:dt\thinspace dx)、\, は , に置き換えます。
    • 数式に複数のアスタリスクが含まれる場合は、*(q_*)の代わりに \ast(q_\ast)を使用します。
<!-- GitHub では壊れます -->
インラインポアソン括弧 $\{F, G\} = 0$、集合 $\left\{ x : x > 0 \right\}$、積分 $\int dx\,dy$、行列 $\bigl(\begin{smallmatrix} 0 & 1 \\ -1 & 0 \end{smallmatrix}\bigr)$。

<!-- GitHub では機能します -->
インラインポアソン括弧 $\lbrace F, G\rbrace = 0$、集合 $\left\lbrace x : x > 0 \right\rbrace$、積分 $\int dx\thinspace dy$、行列 $\bigl(\begin{smallmatrix} 0 & 1 \cr -1 & 0 \end{smallmatrix}\bigr)$。

4. cmark-gfm のために $$ ... $$ ブロックの境界をフォーマットする

  • **バグ:**数式に複数の _ や * 文字が含まれる場合、cmark-gfm は3つの状況で $$ ... $$ ブロックを認識できず、生の $$ テキストを残し、アンダースコア間のテキストをイタリック体にします:
    1. 前後に空白行がないトップレベルの $$ ... $$ ブロック。
    2. $$ が \begin{aligned} と同じ行にある複数行の $$\begin{aligned} ... \end{aligned}$$ ブロック。
    3. リストアイテム(1. ... または - ...)やブロッククォート(> ...)内でインデントされた複数行の $$ ... $$ ブロック。
  • 回避策:
    • **トップレベルのディスプレイ数式:**開始と終了の $$ をそれぞれ列0の独自の行に置き、前後に空白行を挿入します:

      
      $$
      \begin{aligned}
      a &= b + c, \\
      d &= e + f.
      \end{aligned} \qquad\text{(1.1)}
      $$
      
      
    • **リストアイテムまたはブロッククォート内のディスプレイ数式:**数式全体を 1行 に $$\displaystyle ...$$ として保持し(環境内の改行には \cr を使用)、前後に空白行で囲みます:

      1. 番号付きリストアイテム内:
      
         $$\displaystyle S_d = \int_{\mathbb{R}} dt\thinspace \mathcal{L}_d(\phi_t, \psi_t) \qquad\text{(1.2)}$$
      
      

スクリプト

scripts/fix_github_math.py は上記のルールを Markdown ファイルに適用します。$...$ と $$...$$ の内容のみを書き換え、フェンスコードとインラインコードはそのままにし、数式のないファイルには触れず、冪等です。任意の場所から実行できます:

# 変更せずにチェック(変更が必要なファイルがある場合は終了コード1を返します。CI や pre-commit フックで使用可能)
python3 ~/.claude/skills/github-markdown-math/scripts/fix_github_math.py --check path/to/file.md

# その場で修正
python3 ~/.claude/skills/github-markdown-math/scripts/fix_github_math.py path/to/file.md

このスキルがプロジェクトにインストールされている場合(.claude/skills/github-markdown-math/)、そのパスを使用します。

制限

  • 正規表現ベースなので、差分を確認してください。また、GitHub が結果を正しくレンダリングすることを確認できません。
  • \operatorname{...} は、引数にネストされた括弧がない場合のみ変換されます。\thinspace は、固定リスト(Im、im、pr、graph、Div、ker、dim、deg、span、spec、End、Re、tr、rank)の名前に対してのみ \mathrm{...} の後に追加されます。他の名前は手動で追加してください。
  • アスタリスクのうち、q_* のみが q_\ast に書き換えられます。他の * は手動で確認してください(ルール3)。
  • ブロッククォートの数式は1レベルの深さ(> )まで処理され、ネスト(> > )は処理されません。
  • 2つの通貨記号を含む行($5 and $10)はインライン数式として読み取られる可能性があります。これは、その間のテキストにルールが書き換えるバックスラッシュシーケンスが含まれていない限り無害です。
  • これらのルールは観察された GitHub の動作を説明しています。GitHub がこれらのバグのいずれかを修正した場合、対応する回避策は不要になります。

関連スキル