fix(core/tree-sitter): render markdown backslash escapes as the escaped character - #1370
Open
3aKHP wants to merge 1 commit into
Open
fix(core/tree-sitter): render markdown backslash escapes as the escaped character#13703aKHP wants to merge 1 commit into
3aKHP wants to merge 1 commit into
Conversation
…ed character
Markdown renderables style paragraph text through the markdown_inline
injection with conceal. The bundled highlight query captures
(backslash_escape) as @string.escape with no conceal rule, so CommonMark
escapes rendered literally with the backslash visible and escape-styled
("\~" displayed as backslash + tilde in the escape color).
The escape cannot be fixed in the query language: the markdown_inline
grammar emits backslash_escape as one atomic regex token spanning both
characters, so no query can capture the backslash separately, and conceal
replaces whole captured ranges with a static literal, so a whole-node
conceal rule would remove the escaped character too.
Fix both halves in the worker's one-shot highlight pipeline:
- processInjections spreads each injected capture node into a plain
pseudo-node; web-tree-sitter's node `type` is a prototype getter, so
the spread dropped it. Carry `type` explicitly so downstream consumers
can dispatch on it.
- getSimpleHighlights splits a backslash_escape capture that has no
query-configured conceal into a one-byte conceal of the backslash and
drops the escape styling from the remainder, so "\~" renders as plain
"~".
The marked-based streaming placeholder path already decoded escapes
(renderInlineToken's escape case), so the two internal render paths now
agree.
Tests: client.test.ts gains a markdown escape test asserting the conceal
tuple covers only the backslash byte and that no full-range
string.escape remains. tree-sitter suites: 63 pass, 1 pre-existing
skip; the only packages/core failure (node-assets manifest) also fails
on the pristine tag without build output and is unrelated.
3aKHP
requested review from
Hona,
kommander,
msmps and
simonklee
as code owners
August 15, 2026 01:55
3aKHP
added a commit
to 3aKHP/opentui
that referenced
this pull request
Aug 15, 2026
anomalyco#1369 (issue) and anomalyco#1370 (PR, branch vesicle/fix-markdown-escape). Also record the 2026-08-15 maintenance posture: the fork is the self-maintained Vesicle baseline; upstream review is courtesy, nothing waits on it.
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1369
Summary
Markdown renderables style paragraph text through the markdown_inline injection with conceal. The bundled highlight query captures
(backslash_escape)as@string.escapewith no conceal rule, so CommonMark escapes rendered literally with the backslash visible and escape-styled (\~displayed as backslash + tilde in the escape color).The escape cannot be fixed in the query language: the markdown_inline grammar emits
backslash_escapeas one atomic regex token spanning both characters, so no query can capture the backslash separately, and conceal replaces whole captured ranges with a static literal, so a whole-node conceal rule would remove the escaped character too.Fix
Both halves in the worker's one-shot highlight pipeline:
processInjectionsspreads each injected capture node into a plain pseudo-node; web-tree-sitter's nodetypeis a prototype getter, so the spread dropped it. Carrytypeexplicitly so downstream consumers can dispatch on it.getSimpleHighlightssplits abackslash_escapecapture that has no query-configured conceal into a one-byte conceal of the backslash and drops the escape styling from the remainder, so\~renders as plain~. An explicit#set! concealon the node set by a query still wins.The marked-based streaming placeholder path already decoded escapes (
renderInlineToken's escape case), so the two internal render paths now agree.Tests
client.test.tsgains a markdown escape test asserting that eachstring.escapehighlight on"Escaped \~ and \* here"collapses to a one-byte conceal tuple covering only the backslash ([8,9)/[15,16),meta.conceal === ""), and that no full-rangestring.escaperemains, so the escaped character renders unstyled.tree-sitter suites: 63 pass, 1 pre-existing skip. The only
packages/corefailure (node-assetsmanifest) also fails on the pristine tag without build output and is unrelated.Out of scope (deliberately)
(hard_line_break)keeps its current literal rendering; it shares the@string.escapecapture but involves line-break semantics rather than character decoding.#offset!-style partial-token conceal (nvim queries use it in commented form) would be a more general engine feature; this fix does not need it.