Initial checklist
Affected package
mdast-util-to-markdown 2.1.2, mdast-util-from-markdown 2.0.3, micromark 4.0.2
Steps to reproduce
is stringified as:
the structure of the AST matches, but the URL stored on the link node gains
an extra backslash on the round-trip, so the rendered HTML href changes.
parse
tree₁ has a link node with url: "aa:\\" (one backslash).
Stringify it:
tree₂ has a link node with url: "aa:\\\\" (two backslashes).
Rendered HTML differs:
<!-- tree1 -->
<p><a href="aa:%5C">aa:\</a></p>
<!-- tree2 -->
<p><a href="aa:%5C%5C">aa:\\</a></p>
Minimal reproducer:
import {fromMarkdown} from 'mdast-util-from-markdown'
import {toMarkdown} from 'mdast-util-to-markdown'
const tree1 = fromMarkdown('<aa:\\>')
const text2 = toMarkdown(tree1) // '<aa:\\\\>\n' (backslash doubled)
📓 per CommonMark §6.7, an autolink is delimited by <...> and its
content is interpreted literally — backslash escapes are not processed
inside autolinks. The serializer is escaping the backslash as if it were
inside regular text/link markup.
Larger real-world reproducers that collapse to the same root cause:
<https://example.com?find=\*>, <https://example.com/\[\>.
Actual behavior
Every backslash in the autolink URL is doubled on the round-trip.
Expected behavior
The round-trip preserves the URL. The serializer should emit the autolink
content verbatim (no backslash doubling).
Runtime
node v24.13.1
Package manager
npm 11.8.0
Operating system
Ubuntu (WSL2)
Build and bundle tools
No response
Initial checklist
Affected package
mdast-util-to-markdown 2.1.2, mdast-util-from-markdown 2.0.3, micromark 4.0.2
Steps to reproduce
is stringified as:
the structure of the AST matches, but the URL stored on the
linknode gainsan extra backslash on the round-trip, so the rendered HTML
hrefchanges.parse
tree₁ has a
linknode withurl: "aa:\\"(one backslash).Stringify it:
tree₂ has a
linknode withurl: "aa:\\\\"(two backslashes).Rendered HTML differs:
Minimal reproducer:
📓 per CommonMark §6.7, an autolink is delimited by
<...>and itscontent is interpreted literally — backslash escapes are not processed
inside autolinks. The serializer is escaping the backslash as if it were
inside regular text/link markup.
Larger real-world reproducers that collapse to the same root cause:
<https://example.com?find=\*>,<https://example.com/\[\>.Actual behavior
Every backslash in the autolink URL is doubled on the round-trip.
Expected behavior
The round-trip preserves the URL. The serializer should emit the autolink
content verbatim (no backslash doubling).
Runtime
node v24.13.1
Package manager
npm 11.8.0
Operating system
Ubuntu (WSL2)
Build and bundle tools
No response