Was macht GitHub Markdown Mathe: Rendering-Regeln und Workarounds?
GitHub rendert Markdown-Mathematik in zwei Stufen:
- Serverseitig (
cmark-gfm+ Mathe-Sanitizer): findet die$ ... $und$$ ... $$-Grenzen, wendet CommonMark-Backslash-Entschützung auf ASCII-Interpunktion an und lehnt nicht erlaubte LaTeX-Makros ab, bevor es<math-renderer>-Tags ausgibt. - Clientseitig (
<math-renderer>+MathJax.tex2mml): konvertiert TeX in MathML und fügt es in die Seite ein für natives MathML Core-Layout im Browser.
Beide Stufen haben Fehler, die gewöhnliches LaTeX zerstören. Die folgenden Regeln sind Workarounds für diese Fehler.
Wann diese Fähigkeit verwenden
- Schreiben oder Bearbeiten von Mathematik in einer
.md-Datei, die auf GitHub gelesen wird. - Korrigieren von Gleichungen, die auf GitHub gequetscht, rot oder als roher
$$-Text gerendert werden. - Nicht nötig für Dateien, die nur über LaTeX, Pandoc, Jupyter, MkDocs oder VS Code laufen. Wenn eine Datei an beiden Orten gelesen wird, sind die untenstehenden Ersetzungen gewöhnliches TeX/MathJax, sodass sie auch anderswo korrekt gerendert werden.
Arbeitsablauf
- Befolge beim Schreiben die Regeln 1 bis 4 unten.
- Führe vor dem Commit das Prüfskript auf den geänderten Markdown-Dateien aus (siehe Skript). Führe es ohne
--checkaus, um sie direkt zu korrigieren. - Überprüfe das Ergebnis mit
git diff. Das Skript basiert auf regulären Ausdrücken, behandle seine Ausgabe daher als Entwurf. Das Rendern kann nicht lokal überprüft werden; im Zweifelsfall auf GitHub in der Vorschau ansehen.
Kurzreferenz
| Stattdessen | Schreibe | Warum |
|---|---|---|
\tag{2.1} | \qquad\text{(2.1)} | \tag quetscht die Gleichung in einen vertikalen Streifen |
\operatorname{Foo} | \mathrm{Foo} | operatorname wird vom Sanitizer blockiert |
\mathrm{Im} D_t | \mathrm{Im}\thinspace D_t | stellt den Operatorabstand wieder her |
\hbox{...}, {\rm ...} | \text{...}, {\mathrm{...}} | Plain-TeX-Makros werden blockiert |
\{, \} | \lbrace, \rbrace | CommonMark macht aus \{ ein { |
\\ in einer einzelnen Zeile | \cr | CommonMark macht aus \\ ein \ |
\, | \thinspace | CommonMark macht aus \, ein , |
\, | , | würde als doppeltes Komma gerendert |
q_* (mehrere * in einem Block) | q_\ast | gepaarte * werden zu Markdown-Hervorhebung |
1. Niemals \tag{...} verwenden (verhindert vertikales Zerquetschen auf 1 Zeichen)
- Fehler:
MathJax.tex2mmlserialisiert jede Gleichung, die\tag{2.1}enthält, als<mtable displaystyle="true"><mlabeledtr><mtd>.... Die MathML Core-Spezifikation des Browsers hat<mlabeledtr>entfernt, daher behandeln Chromium/Blink und Firefox es nicht als Tabellenzeile und quetschen die Gleichung in eine 1-Zeichen-breite Spalte. - Workaround: setze stattdessen
\qquad\text{(2.1)}an das Ende der Display-Gleichung. Für einen Akzent in der Beschriftung verwende das Unicode-Zeichen′innerhalb von\text{(3.3′)}anstelle eines verschachtelten$\tag{3.3$'$}$.
<!-- Zerstört auf GitHub (zu einer vertikalen Spalte gequetscht) -->
$$
\partial_t \mathcal{Q} + \partial_x \mathcal{J} = 0 \tag{2.1}
$$
<!-- Funktioniert auf GitHub -->
$$
\partial_t \mathcal{Q} + \partial_x \mathcal{J} = 0 \qquad\text{(2.1)}
$$
2. Niemals \operatorname{...}, \hbox{...} oder {\rm ...} verwenden (verhindert Fehler wegen nicht erlaubter Makros)
- Fehler: Der serverseitige Sanitizer von GitHub blockiert
\operatornameund\operatorname*mit der Meldung "The following macros are not allowed: operatorname". - Workaround:
- Ersetze
\operatorname{Foo}durch\mathrm{Foo}. Wenn darauf direkt ein Buchstabe oder ein Backslash-Makro folgt (z.B.\operatorname{Im} D_toder\operatorname{pr} v), füge\thinspacehinzu (\mathrm{Im}\thinspace D_t), um den Operatorabstand zu erhalten. - Ersetze Plain-TeX
\hbox{...}durch\text{...}und{\rm ...}durch{\mathrm{...}}.
- Ersetze
<!-- Zerstört auf GitHub ("The following macros are not allowed: operatorname") -->
$\operatorname{diag}(1, -1)$ and $\operatorname{Im} D_t$
<!-- Funktioniert auf GitHub -->
$\mathrm{diag}(1, -1)$ and $\mathrm{Im}\thinspace D_t$
3. Begrenzer, Abstände und Zeilenumbrüche vor CommonMark-Entschützung schützen
- Fehler: Bevor die Mathematik
<math-renderer>erreicht, wendet der Markdown-Parser von GitHub CommonMark-Entschützung von ASCII-Interpunktion innerhalb von$ ... $und$$ ... $$an:\{wird zu{und\}wird zu}. Dies verursacht "Missing or unrecognized delimiter for \left" bei\left\{und entfernt lautlos die geschweiften Klammern von Poisson-Klammern\{F, G\}.\\(wenn nicht von einem Zeilenumbruch gefolgt) wird zu\. Dies zerbricht einzeilige Matrizen und Fälle wie\begin{pmatrix} 0 & 1 \\ -1 & 0 \end{pmatrix}in\-1und erzeugt rote Fehler wegen undefinierter Makros.\,wird zu,,(ein doppeltes Komma) und\,wird zu,(ein wörtliches Komma vordx).- Gepaarte
*innerhalb eines Mathe-Blocks (z.B.U_+(z - 2q_*), \quad z = w + Dq_*) können als Markdown<em>-Hervorhebung geparst werden.
- Workaround:
- Verwende
\lbraceund\rbraceanstelle von\{und\}(füge ein Leerzeichen hinzu, wenn ein Buchstabe folgt:\lbrace F, G\rbrace). - Verwende
\cranstelle von\\für Zeilenumbrüche in einzeiligen Matrizen und Umgebungen oder setze sofort einen Zeilenumbruch nach\\innerhalb von mehrzeiligen$$...$$-Blöcken. - Verwende
\thinspaceanstelle von\,(mit einem nachfolgenden Leerzeichen vor Buchstaben:dt\thinspace dx) und ersetze\,durch,. - Verwende
\ast(q_\ast) anstelle von*(q_*), wenn eine Gleichung mehrere Sternchen enthält.
- Verwende
<!-- Zerstört auf GitHub -->
Inline Poisson-Klammer $\{F, G\} = 0$, Menge $\left\{ x : x > 0 \right\}$, Integral $\int dx\,dy$, Matrix $\bigl(\begin{smallmatrix} 0 & 1 \\ -1 & 0 \end{smallmatrix}\bigr)$.
<!-- Funktioniert auf GitHub -->
Inline Poisson-Klammer $\lbrace F, G\rbrace = 0$, Menge $\left\lbrace x : x > 0 \right\rbrace$, Integral $\int dx\thinspace dy$, Matrix $\bigl(\begin{smallmatrix} 0 & 1 \cr -1 & 0 \end{smallmatrix}\bigr)$.
4. $$ ... $$-Blockgrenzen für cmark-gfm formatieren
- Fehler: Wenn eine Gleichung mehrere
_- oder*-Zeichen enthält, erkenntcmark-gfm$$ ... $$-Blöcke in drei Situationen nicht, hinterlässt rohen$$-Text und kursiviert den Text zwischen Unterstrichen:$$ ... $$-Blöcke auf oberster Ebene ohne Leerzeilen davor und danach.- Mehrzeilige
$$\begin{aligned} ... \end{aligned}$$-Blöcke, bei denen$$in derselben Zeile wie\begin{aligned}und nicht in einer eigenen Zeile steht. - Mehrzeilige
$$...$$-Blöcke, die in Listenelementen (1. ...oder- ...) oder Blockzitaten (> ...) eingerückt sind.
- Workaround:
-
Display-Mathe auf oberster Ebene: setze das öffnende und schließende
$$in eigenen Zeilen an Spalte 0, mit einer Leerzeile davor und danach:$$ \begin{aligned} a &= b + c, \\ d &= e + f. \end{aligned} \qquad\text{(1.1)} $$ -
Display-Mathe innerhalb von Listenelementen oder Blockzitaten: behalte die gesamte Gleichung in einer einzigen Zeile als
$$\displaystyle ...$$(verwende\crfür Zeilenumbrüche innerhalb von Umgebungen), umgeben von Leerzeilen:1. Innerhalb eines nummerierten Listenelements: $$\displaystyle S_d = \int_{\mathbb{R}} dt\thinspace \mathcal{L}_d(\phi_t, \psi_t) \qquad\text{(1.2)}$$
-
Skript
scripts/fix_github_math.py wendet die obigen Regeln auf Markdown-Dateien an. Es schreibt nur den Inhalt von $...$ und $$...$$ um, lässt Code-Blöcke und Inline-Code in Ruhe, berührt keine Dateien ohne Mathematik und ist idempotent. Führe es von überall aus:
# Prüfen ohne Änderung (beendet sich mit 1, wenn eine Datei Änderungen benötigt; verwendbar in CI oder einem Pre-Commit-Hook)
python3 ~/.claude/skills/github-markdown-math/scripts/fix_github_math.py --check pfad/zu/datei.md
# Direkt korrigieren
python3 ~/.claude/skills/github-markdown-math/scripts/fix_github_math.py pfad/zu/datei.md
Wenn diese Fähigkeit stattdessen in einem Projekt installiert ist (.claude/skills/github-markdown-math/), verwende diesen Pfad.
Einschränkungen
- Es basiert auf regulären Ausdrücken, daher den Diff überprüfen. Es kann auch nicht bestätigen, dass GitHub das Ergebnis korrekt rendert.
\operatorname{...}wird nur konvertiert, wenn sein Argument keine verschachtelten geschweiften Klammern enthält.\thinspacewird nach\mathrm{...}nur für eine feste Liste von Namen hinzugefügt (Im,im,pr,graph,Div,ker,dim,deg,span,spec,End,Re,tr,rank); füge es für andere von Hand hinzu.- Von den Sternchen wird nur
q_*zuq_\astumgeschrieben; überprüfe andere*von Hand (Regel 3). - Gleichungen in Blockzitaten werden eine Ebene tief (
>) behandelt, nicht verschachtelt (> >). - Eine Zeile mit zwei Währungssymbolen (
$5 und $10) kann als Inline-Mathe gelesen werden. Dies ist harmlos, es sei denn, der Text dazwischen enthält eine Backslash-Sequenz, die die Regeln umschreiben. - Die Regeln beschreiben das Verhalten von GitHub, wie es beobachtet wurde. Sollte GitHub einen dieser Fehler beheben, wird der entsprechende Workaround überflüssig.