Skip to content

web: let emphasis reach across an inline code span - #172

Merged
adityak74 merged 1 commit into
mainfrom
fix/web-markdown-bold-across-code
Sep 5, 2026
Merged

web: let emphasis reach across an inline code span#172
adityak74 merged 1 commit into
mainfrom
fix/web-markdown-bold-across-code

Conversation

@adityak74

Copy link
Copy Markdown
Contributor

The bug

The browser markdown renderer did not render bold when the bold span contained inline code. An answer like this showed its asterisks on the page:

**874 `.md` files** on disk, but most of those aren't "your" docs:
The number that best answers it: **`git ls-files '*.md'` = 172** and that's what's tracked.

renderInline split the text on backticks first and handed each non-code part to the emphasis pass on its own, so an opening ** and its closing ** never met when a code span sat between them.

The fix

The emphasis pattern now runs over a copy of the text in which every code span and every link is a run of NULs of the same length, and the match indices slice the original. That is what lets emphasis see across a code span without seeing into it.

  • Code still wins inside itself: backticks around **text** show the asterisks and emphasise nothing.
  • A link is hidden for the same reason a code span is: an underscore in its URL is not a delimiter.
  • The run between a matched pair is rendered by recursing over it, so a <strong> or <em> may now hold a <code class="inline-code"> or an <a>. Emphasis inside a link label works as before.
  • Unmatched delimiters stay literal exactly as before.
  • No HTML string is assembled anywhere. Every node is created with createElement and every string lands as a text node or through textContent.

Only web/src/markdown.ts and web/test/markdown.test.ts change. No Rust is touched and no docs/DECISIONS.md entry is needed.

Tests

Seven new cases in web/test/markdown.test.ts: bold containing a code span, bold starting with a code span, italic containing a code span, asterisks inside a code span staying literal next to real emphasis, an unmatched ** followed by a code span staying literal, a link inside bold still rendering as a link, and an underscore in a link URL not being a delimiter. All existing injection cases pass unchanged.

From web/: npm run check, npm test (366 pass, 0 fail; 27 in the markdown suite), npm run build all pass.

https://claude.ai/code/session_01PG2vuux5tMsjnZBLWJzMyp

A model answer like "**874 `.md` files** on disk" showed its asterisks
on the page. renderInline split the text on backticks first and handed
each non-code part to the emphasis pass on its own, so an opening **
and its closing ** never met when a code span sat between them.

The emphasis pattern now runs over a copy of the text in which every
code span and every link is a run of NULs of the same length, and the
match indices slice the original. Code still wins inside itself, so
backticks around **text** show the asterisks and emphasise nothing. A
link is hidden for the same reason a code span is: an underscore in
its URL is not a delimiter. The run between a matched pair is rendered
by recursing over it, so a strong or em may now hold a code span or a
link, and emphasis inside a link label works as before. Unmatched
delimiters stay literal.

No HTML string is assembled anywhere. Every node is created with
createElement and every string lands as a text node or through
textContent, as before.

Claude-Session: https://claude.ai/code/session_01PG2vuux5tMsjnZBLWJzMyp
@adityak74
adityak74 merged commit 2d2f4d8 into main Sep 5, 2026
7 checks passed
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