Skip to content

decode entities and backslash escapes in one pass - #650

Merged
jgm merged 1 commit into
commonmark:masterfrom
zayeem06:single-pass-unescape
Oct 29, 2026
Merged

jgm merged 1 commit into
commonmark:masterfrom
zayeem06:single-pass-unescape

Conversation

@zayeem06

Copy link
Copy Markdown
Contributor

cmark_clean_url and cmark_clean_title in src/inlines.c, and the info string handling in finalize in src/blocks.c, decode entity references first and then strip backslash escapes from the result, so these strings are decoded twice: [a](\©) gives href %5C%C2%A9 instead of ©, and [b](\*) gives href * instead of %5C*, which disagrees with the spec and with commonmark.js 0.31.2. The new cmark_unescape_string handles both kinds of escape in one left-to-right pass and replaces the two-step decode at all three sites, which also covers reference definitions since they go through the same two functions; the info string is still trimmed after decoding, as before. Worth checking: regression cases in test/regression.txt fail before the change and pass after, the spec and roundtrip suites stay green, and cmark_strbuf_unescape no longer has callers but I left it in place to keep the diff small.

Link destinations, link titles and info strings were entity-decoded
first and backslash-unescaped afterwards, so an escaped `&` still
started an entity (`[a](\©)` gave href `%5C%C2%A9`) and an entity
decoding to `\` escaped the next character (`[b](&commonmark#92;&commonmark#42;)` gave
href `*`). Decode both in a single pass, as the spec and commonmark.js
do.
@nwellnhof

Copy link
Copy Markdown
Contributor

houdini_unescape_html and houdini_unescape_html_f also have no callers after the patch, I think. All unused internal functions should be removed, maybe in a separate commit.

@jgm
jgm merged commit a2a5e69 into commonmark:master Oct 29, 2026
15 checks passed
@jgm jgm mentioned this pull request Oct 29, 2026
@jgm

jgm commented Oct 29, 2026

Copy link
Copy Markdown
Member

Thank you! Comments welcome on #652 which removes the unused houdini functions.

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.

3 participants