Skip to content

Label grammar: six edge cases from 0.47.0 (#70) - #78

Merged
vgururao merged 2 commits into
blygger:mainfrom
aneeshsathe:fix/label-grammar
Oct 20, 2026
Merged

vgururao merged 2 commits into
blygger:mainfrom
aneeshsathe:fix/label-grammar

Conversation

@aneeshsathe

Copy link
Copy Markdown
Contributor

Six edge cases in 0.47.0's label grammar ([[id | text]], #70). They were found while porting the renderer to another client, Blygger Desktop/Burrow, which pins studio output byte for byte. Each one was reproduced on main with a failing test before it was fixed. The tests are kept as regression coverage in test/label-grammar-edge-cases.test.ts.

# Bug Fix
1 A label inside block TK output was escaped twice: a <b> & x showed as a &lt;b&gt; &amp; x, and *em* showed as literal <em>em</em>. Block links were resolved from the block's already-rendered HTML. This only shows with impyrt or generated block scopes, because model output already has links stripped (row 67). Generated blocks now resolve links over their own markdown, the same way the body does. AnnotatedDocument carries blockSources, and renderGeneratedBlock re-renders a block only if it has links. Decoding entities from the HTML can't work, because markdown has already rendered the label's emphasis by then. The now-dead HTML path is removed: the inert parameter, previewInternalLinks' html flag, and htmlCodeRanges.
2 A backtick in one label could open a code span that made a later [[id]] on the same line literal, though no code renders. Code ranges are recomputed with each live link's label blanked (same length, so offsets hold), and only when the label contains a backtick. A code span opened before a link still makes the link inert, as CommonMark does. That case is pinned too.
3 labelText rewrote ]] in one pass, so a]]]b became a] ]]b and re-parsed truncated. /\](?=\]|$)/g → "] ". The trailing ] matters too, because callers append ]] straight after the label. a]]]b, a]]]]b and x]]] all round-trip.
4 A labelled link inside an autolink or bare URL with & in its label left a raw & in href (&copy decodes to ©). escapeHtml(encodeURI(literal)) for the href, and the matching comparison updated.
5 Choosing a passage in a stub rewrote ![[id | label]] to a bare ![[id]], losing the label. findQuote returns the original directive line, and withStubQuote reuses it.
6 directiveOwnLine used [ \t] where DIRECTIVE_LINE uses \s. A form-feed or vertical-tab led own-line directive in TK output was quoted, but publish didn't give the #60 warning. [^\S\n]* at both ends, which is exactly \s without the newline that ends a line. CRLF already agreed, and a control test pins it.

Behaviour beyond the six:

  • labelText can return a label with a trailing space when the text ends in ]. That's needed for the round trip.
  • A generated block containing links is rendered twice: once to annotate it, once after substitution.

No wire, contract or migration changes.

Tests

  • npm run typecheck (both configs): clean.
  • npm test: 1758 passed, 5 skipped.
  • npm run test:ui: 97 passed.
  • e2e: parity, picker, reading-pwa (stub passage quote) and generated-highlight, desktop and mobile: 97 passed, 1 skipped.
  • Mutation suites mapped by ci-scope: the oracle, plus auth-security in both modes (48 + 5 caught). All pass.

🤖 Generated with Claude Code

aneeshsathe and others added 2 commits October 18, 2026 13:39
…ort)

Each test asserts the correct behaviour and fails on 0.47.0 where the bug
is real. No source changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… regressions

- Block TK output: links resolve over each block's markdown and the block
  is rendered again, never over its HTML, where a label had already been
  through markdown (`*em*` -> `<em>`) and escaping. The HTML-source path
  (htmlCodeRanges, the `inert` parameter, previewInternalLinks' html flag)
  is gone.
- A backtick in a live link's label no longer opens a code span that makes
  a later link inert: labels are blanked before code is found again, left
  to right, so a span opened before a link still wins (blygger#54).
- labelText spaces every `]` followed by `]` or by the closing `]]`, so
  `a]]]b`, `a]]]]b` and `x]]]` round-trip through linkSource.
- An autolinked URL holding a link gets its literal HTML-escaped in the
  href (`&` -> `&amp;`).
- withStubQuote keeps the directive line as written, label included.
- directiveOwnLine takes `[^\S\n]` at both ends, DIRECTIVE_LINE's `\s`
  less the newline, so NBSP/FF/VT-led own-line directives in TK output
  are warned about (blygger#60).

test/label-grammar-repros.test.ts becomes label-grammar-edge-cases.test.ts,
with one added case for code-span precedence over a label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vgururao
vgururao merged commit d91afbe into blygger:main Oct 20, 2026
8 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.

2 participants