Skip to content

fix(mdx): stop double-escaping angle brackets inside code - #1243

Closed
nlimpid wants to merge 1 commit into
longbridge:mainfrom
nlimpid:fix/mdx-code-block-escaping
Closed

fix(mdx): stop double-escaping angle brackets inside code#1243
nlimpid wants to merge 1 commit into
longbridge:mainfrom
nlimpid:fix/mdx-code-block-escaping

Conversation

@nlimpid

@nlimpid nlimpid commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Problem

The preflight rewrites in astro.config.ts run over the raw mdx source with code blocks included. Rule 5 turns <iostream> and <token> into &lt;…&gt;, the downstream pipeline escapes that a second time, and the page renders the entity text:

#include &lt;iostream&gt;          ← every C++ SDK example
Bearer &lt;token&gt;              ← every curl example

419 pages are affected. Anyone copying a snippet off the page gets broken code.

It is not only rule 5 — rules 6, 7, 9 and 10 rewrite code-region content too, so fixing a single rule is not enough.

Fix

Stash the code regions before rules 2-10 run, restore them afterwards. Three kinds, and the order matters:

  1. the CliCommand payload built in rule 1.5 (a JSON string that may itself contain backticks, so it goes first)
  2. fenced blocks (before inline spans, or a fence's own backticks get read as a span)
  3. inline code spans

The placeholder uses U+E000 rather than NUL so oxlint's no-control-regex stays quiet.

Verification

Against the dev server:

check result
C++ fence #include <iostream>
curl fence Bearer <token>
inline span <client_id>
all 78 absolute-slug English pages 200, no render failure
rule 9 REST placeholder /v1/content/{symbol}/news unchanged
rule 1.5 CliCommand terminal card unchanged
rule 10 directive callout unchanged
oxlint clean

The regression checks matter most here: had the stash regex over-captured into prose, those placeholders would reach MDX as undefined components and the pages would 500. All 78 returning 200 confirms the prose-side escaping still works.

The preflight rewrites in astro.config.ts run over the raw mdx source with
code blocks included. Rule 5 turned `<iostream>` and `<token>` into
`&lt;…&gt;`, the downstream pipeline escaped that a second time, and 419
pages ended up rendering the entity text: every C++ include and every curl
auth header was broken for anyone copying it off the page.

Stash the code regions — fenced blocks, inline spans, and the CliCommand
payload built in rule 1.5 — before rules 2-10 run, and restore them once
the rewrites are done. The placeholder uses U+E000 rather than NUL so
oxlint's no-control-regex stays quiet.

Verified against the dev server: the three affected shapes now render as
`#include <iostream>`, `Bearer <token>` and `<client_id>`; all 78
absolute-slug English pages still return 200; CliCommand cards, REST brace
placeholders and directive callouts are unchanged.
@nlimpid nlimpid closed this Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant