huggingface / huggingface/doc-builder
Inline `\(...\)` math swallows the preceding whitespace; the custom delimiter regexes also diverge from standard KaTeX
- Dominant language
- Python
- Stars
- 144
- Forks
- 59
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 13
Description
The Markdown preprocessor renders math by extracting it with hand-written regexes (`markKatex` in `kit/preprocessors/mdsvex/index.js`) before Markdown runs, then rendering the stashed TeX with `katex.renderToString`. There is a concrete bug in that extraction, plus a broader issue: the custom delimiter rules diverge from standard KaTeX in ways that silently bite contributors.
## 1. Bug: inline `\(...\)` eats the whitespace before it
```js
const REGEX_LATEX_INLINE = /\s\\\\\(([\s\S]+?)\\\\\)/g;
// ...
.replace(REGEX_LATEX_INLINE, (_, tex) => {
const marker = `KATEXPARSE${counter++}MARKER`;
markedKatex[marker] = { tex, displayMode: false };
return marker; // the leading \s that was matched is never restored
});
```
The regex matches a leading `\s`, but the replacement returns only `marker`, so that whitespace character is consumed and dropped. Two visible effects:
- **A space between text and an inline formula disappears:** `... one step \(S_{t+1}\)` renders as `one stepS_{t+1}` (glued).
- **Standalone equations run together:** when the eaten character is the newline separating two `\(...\)` lines, the blank-line paragraph break collapses and consecutive equations jam onto one line.
The `$...$` branch a few lines below handles this correctly — it captures the surrounding whitespace and re-emits it (`return spaceBefore + marker + spaceAfter`). The `\(` branch (and the `$$` branch, which eats a leading `\n`) do not.
**Fix** — assert the boundary without consuming it, or capture-and-restore:
```js
const REGEX_LATEX_INLINE = /(?<=\s)\\\\\(([\s\S]+?)\\\\\)/g; // lookbehind
// or: /(\s)\\\\\(([\s\S]+?)\\\\\)/g -> return spaceBefore + marker;
```
## 2. The delimiter rules are inconsistent
| Syntax | Rule in `markKatex` |
|---|---|
| `\(...\)` inline | requires (and eats) one leading whitespace |
| `$...$` inline | requires whitespace on **both** sides |
| `$$...$$` display | requires (and eats) a leading newline |
| `\[...\]` display | **not handled at all** |
There is no consistent mental model, and the natural display counterpart of `\(...\)` — `\[...\]` — is not supported (you must use `$$`).
## 3. The real cost: standard KaTeX syntax silently fails
Contributors will reach for standard KaTeX syntax, but much of it does not render here — it silently becomes literal text instead of math. Examples that fail:
- `$x$` right before punctuation or markup, e.g. `$x$.` or `**$x$**`
- `\[ ... \]` display math — not handled at all
- `\(...\)` at the start of a line — no leading space for the regex to match
We hit this while fixing one page in the Deep RL course: using standard `$...$` and `\[...\]` silently broke ~20 formulas, and it took reading this file to find out why.
**Suggestion:** handle math with the standard toolchain — `remark-math` + `rehype-katex`, or KaTeX's `auto-render` — instead of hand-written regexes, so standard syntax just works and the issues above go away together.
## Where it shows
Live example on the Deep RL course: https://huggingface.co/learn/deep-rl-course/unit2/mc-vs-td (source `units/en/unit2/mc-vs-td.mdx`). Before/after below:
Contributor guide
No contributing guide indexed for this repository
Research direction
Read kit/preprocessors/mdsvex/index.js, focusing on markKatex and its delimiter branches. Reproduce the whitespace cases and standard-syntax examples from the issue, then verify that inline and display math—including \(...\), $...$, $$...$$, and \[...\]—renders without lost whitespace or literal-text fallbacks.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- documentation, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100