Current behavior
The chunked transcript renderer breaks code out of enriched at two levels:
- top-level fenced/indented code → native
CodeBlockSegment (shiki highlight, horizontal scroll, themed container)
- code nested in list items → hoisted out via the list-raw line scanner (works around enriched #243, which repeats the list marker on every code line)
Blockquotes are the remaining gap: a fenced block inside a quote stays in the enriched run. It renders correctly (no upstream bug — #243 is list-marker-specific), but inconsistently with every other code block: monochrome (no shiki), no horizontal scroll, enriched's own code container.
Hoisting code OUT of blockquotes was considered and rejected: the quote bar would visually break around the hoisted block (one quote becomes two fragments sandwiching a full-width code block). Unlike ordered lists there is no numbering-continuation mechanism to make the split read naturally.
Plan
Own the blockquote container and recurse:
- Chunker: top-level
blockquote token → new segment kind carrying marked's token.text (the dequoted inner markdown — verified it preserves fences/tables/nested quotes verbatim).
- Renderer:
BlockquoteSegment = left-bar container (borderLeftWidth + blockquoteBorder palette color + padding) wrapping a recursive <ChunkedMarkdown markdown={inner}>. Recursion gives quotes everything for free: fence breakout (shiki inside quotes), list hoist, nested quotes.
- Streaming: mirror the code-segment tail logic — when the last top-level segment is a blockquote and the message is still streaming, thread
streamDone=false into the inner instance so its own tail run does remend.
Open design choice
enriched currently renders quote text muted. Either thread a muted style variant through ChatMarkdown (~20 LOC), or take the opportunity to switch to normal-color text + bar (GitHub / claude.ai style) and skip the variant.
Costs
- Cross-segment selection breaks at quote boundaries (quotes are usually short).
- One nested ChunkedMarkdown instance per quote (low-frequency element; negligible).
Estimated ~70 LOC / half a day, most of it streaming-behavior verification.
Current behavior
The chunked transcript renderer breaks code out of enriched at two levels:
CodeBlockSegment(shiki highlight, horizontal scroll, themed container)Blockquotes are the remaining gap: a fenced block inside a quote stays in the enriched run. It renders correctly (no upstream bug — #243 is list-marker-specific), but inconsistently with every other code block: monochrome (no shiki), no horizontal scroll, enriched's own code container.
Hoisting code OUT of blockquotes was considered and rejected: the quote bar would visually break around the hoisted block (one quote becomes two fragments sandwiching a full-width code block). Unlike ordered lists there is no numbering-continuation mechanism to make the split read naturally.
Plan
Own the blockquote container and recurse:
blockquotetoken → new segment kind carrying marked'stoken.text(the dequoted inner markdown — verified it preserves fences/tables/nested quotes verbatim).BlockquoteSegment= left-bar container (borderLeftWidth+blockquoteBorderpalette color + padding) wrapping a recursive<ChunkedMarkdown markdown={inner}>. Recursion gives quotes everything for free: fence breakout (shiki inside quotes), list hoist, nested quotes.streamDone=falseinto the inner instance so its own tail run does remend.Open design choice
enriched currently renders quote text muted. Either thread a muted style variant through ChatMarkdown (~20 LOC), or take the opportunity to switch to normal-color text + bar (GitHub / claude.ai style) and skip the variant.
Costs
Estimated ~70 LOC / half a day, most of it streaming-behavior verification.