Description
Backslashes inside fenced code blocks in packages/rolldown/src/options/docs/*.md files are rendered as URL-encoded sequences (%5C) on rolldown.rs.
Example: rolldown.rs/reference/InputOptions.external
The regex example:
// Source (.md file)
external: /^[^./](?!:\\)/,
// Rendered on site
external: /^[^./](?!:%5C%5C)/,
%5B = [, %5C = \, %5D = ] — the characters are being URL-encoded instead of rendered literally.
Originally reported by @bddjr in #8780 (comment).
Root Cause
The docs flow is:
external.md contains correct markdown with fenced code blocks
{@include ./docs/external.md} injects the content into a JSDoc comment in input-options.ts
- TypeDoc's comment parser processes the injected content as JSDoc markdown, including the contents of fenced code blocks — backslashes get treated as escape sequences
extract-options-plugin.ts extracts the (already mangled) content
- VitePress renders the mangled output
The issue is that TypeDoc's {@include} does not preserve code block boundaries when processing escape sequences in its block lexer (see blockLexer.ts — it handles \{, \}, \@, \/, \` as escape pairs).
Why codeSplitting docs are not affected: The regex [\\/] in output-code-splitting-example.md survives because \/ is a recognized escape pair that resolves to / — which happens to be correct. But \\ followed by ] does not match any escape pair, so it goes through a different path and gets URL-encoded.
Possible Fixes
-
Best: bypass TypeDoc for doc content — extract-options-plugin.ts already knows which property maps to which docs/*.md file. Instead of extracting the content from TypeDoc's processed output, read the original .md file directly and splice it in. This avoids the TypeDoc parser entirely.
-
Upstream: fix TypeDoc — {@include} should skip escape processing inside fenced code blocks. Correct but depends on TypeDoc team.
-
Workaround: post-process URL decoding — Add section.replace(/%5B/g, "[").replace(/%5C/g, "\\").replace(/%5D/g, "]") in extract-options-plugin.ts. Quick but fragile.
Affected Pages
Any docs/*.md file with backslashes in code blocks that is {@include}'d into a JSDoc comment. Currently:
external.md — regex with \\
Description
Backslashes inside fenced code blocks in
packages/rolldown/src/options/docs/*.mdfiles are rendered as URL-encoded sequences (%5C) on rolldown.rs.Example: rolldown.rs/reference/InputOptions.external
The regex example:
%5B=[,%5C=\,%5D=]— the characters are being URL-encoded instead of rendered literally.Originally reported by @bddjr in #8780 (comment).
Root Cause
The docs flow is:
external.mdcontains correct markdown with fenced code blocks{@include ./docs/external.md}injects the content into a JSDoc comment ininput-options.tsextract-options-plugin.tsextracts the (already mangled) contentThe issue is that TypeDoc's
{@include}does not preserve code block boundaries when processing escape sequences in its block lexer (seeblockLexer.ts— it handles\{,\},\@,\/,\`as escape pairs).Why
codeSplittingdocs are not affected: The regex[\\/]inoutput-code-splitting-example.mdsurvives because\/is a recognized escape pair that resolves to/— which happens to be correct. But\\followed by]does not match any escape pair, so it goes through a different path and gets URL-encoded.Possible Fixes
Best: bypass TypeDoc for doc content —
extract-options-plugin.tsalready knows which property maps to whichdocs/*.mdfile. Instead of extracting the content from TypeDoc's processed output, read the original.mdfile directly and splice it in. This avoids the TypeDoc parser entirely.Upstream: fix TypeDoc —
{@include}should skip escape processing inside fenced code blocks. Correct but depends on TypeDoc team.Workaround: post-process URL decoding — Add
section.replace(/%5B/g, "[").replace(/%5C/g, "\\").replace(/%5D/g, "]")inextract-options-plugin.ts. Quick but fragile.Affected Pages
Any
docs/*.mdfile with backslashes in code blocks that is{@include}'d into a JSDoc comment. Currently:external.md— regex with\\