fix: keep parens in markdown link URLs instead of truncating#871
Conversation
The blog/compare markdown renderer's link regex captured the URL with `[^)]+`, which stops at the first `)`, so a link whose address contains a paren (e.g. a Wikipedia `..._(programming_language)` URL) was cut off and its `href` pointed at a broken address. Allow one level of balanced nested parens in the URL group so the address is captured whole. Add a test with the paren-containing URL.
Address review of the paren-URL fix: - Require at least one char in the URL group (`+` not `*`) so a malformed `[x]()` stays literal text instead of emitting an empty-href anchor, matching the prior behavior. - Make the orphan-paren assertion real (the previous one never matched because of the injected screen-reader span) and add an empty-URL test. - Update the renderer header comment to document balanced-paren URLs.
vivek7405
left a comment
There was a problem hiding this comment.
The regex fix is correct and safe (the unrolled (?:[^()]|\([^()]*\)) form has no ambiguous backtracking, so no ReDoS; no-paren URLs and one-level balanced parens both behave). Three things needed tightening: the group allowed zero reps so a malformed [x]() started emitting an empty-href anchor (now requires at least one char), the test's orphan-paren assertion never actually matched because of the injected sr-only span (now a real check, plus an empty-URL test), and the PR body claimed a header-comment update that had not happened (now the header genuinely documents balanced-paren URLs).
vivek7405
left a comment
There was a problem hiding this comment.
Went back over the regex with the + and the tests. Whole-URL capture with one level of parens holds, [x]() and [a](b) behave, no runaway backtracking, and the header comment matches the actual one-level limit. Nothing left.
Closes #860
What
The shared blog/compare markdown renderer captured link URLs with
[^)]+, which stops at the first). A link whose address legitimately contains a paren (a Wikipedia..._(programming_language)URL, for example) was truncated, so itshrefpointed at a broken address and a stray)leaked as text. This widens the URL group to allow one level of balanced nested parens so the address is captured whole.Change
website/modules/blog/utils/render-post.ts: the link regex URL group becomes((?:[^()]|\([^()]*\))*), capturing a URL that contains a single level of balanced(...).website/test/ssr/compare-ssr.test.tsfor a paren-containing URL, with a counterfactual (fails against the old[^)]+).Scope note
Handles one level of nesting (the realistic case). Deeper nesting (
a_(b_(c))) is still not supported, which matches how many lightweight markdown renderers behave; not worth a full parser here.Docs / surfaces
packages/*public surface changed. The renderer header comment is updated to document balanced-paren URLs.