Skip to content

Inline \(...\) math swallows the preceding whitespace; the custom delimiter regexes also diverge from standard KaTeX #809

Description

@kaleido-jean

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

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:

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:

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions