Commit Graph

2 Commits

Author SHA1 Message Date
Yunfei He 97c61363e5 fix(runtime): linearize screen-reader static + drop empty-SR-frame newline (Ink parity, G17) (#45)
* fix(runtime): linearize screen-reader static output + drop empty-SR-frame newline (Ink parity, G17)

(a) The live static channel flushed <Static> via the 2D grid painter
(paintIsolated) even in screen-reader mode, so bordered static items leaked
box glyphs. paintStaticNode now takes an isScreenReaderEnabled flag and
linearizes fresh static children via renderScreenReaderOutput
(skipStaticElements:false) instead — matching Ink's renderer.ts:24, which
renders node.staticNode through renderNodeToScreenReaderOutput. Non-SR static
is unchanged. render.ts commit() and render-to-string.ts thread the flag.

(b) Interactive SR frames went through renderInteractiveFrame, which appends
"\n" even for empty output, leaking a spurious blank line. Ink's SR path writes
the wrapped output directly with lastOutputToRender = wrappedOutput (no appended
newline), so an empty SR frame emits zero lines. We now suppress the trailing
newline for EMPTY SR output only — matching ink.tsx:573-626 — leaving non-SR
and non-empty SR frames untouched.

Follow-up fixes (two review findings):
- renderToString in SR mode no longer DROPS <Static> output: the SR return
  branch now prepends the captured/linearized static output like the non-SR
  path (Ink's SR renderer returns staticOutput when node.staticNode exists,
  renderer.ts:24-33).
- The SR static linearization now honors the <Static>'s resolved flexDirection
  for separator + child order (read from yoga via getFlexDirection), matching
  screen-reader.ts:73-82 (row/row-reverse → space, *-reverse reverses order);
  the default column case is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(parity): ledger — G17 pr-open, reconcile G16 merged

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 04:43:25 +08:00
Yunfei He 34aeb8ec2e fix(runtime): render linear screen-reader output in the live commit path (Ink parity, G03) (#36)
* fix(runtime): render linear screen-reader output in the live commit path (Ink parity, G03)

commit() previously called paint(tuiRoot) (the 2D grid painter) unconditionally
for both the non-interactive and interactive branches, so an app mounted with
isScreenReaderEnabled emitted the visual frame (box-drawing borders, padded
grid) into the live stream instead of flat linearized text. isScreenReaderEnabled
was only consulted to disable commit throttling.

Add a renderFrame(width) helper that branches on isScreenReaderEnabled: when SR
is enabled it linearizes the tree via renderScreenReaderOutput(tuiRoot,
{ skipStaticElements: true }) and wraps it with wrapAnsi(out, width,
{ trim: false, hard: true }), mirroring Ink's onRender SR branch
(ink.tsx:598-603). Both commit branches now call renderFrame() instead of
paint() directly. The non-SR path is byte-for-byte unchanged (renderFrame
returns paint(tuiRoot)). Static output continues to flush through the existing
paintStaticNode path; full SR-static linearization parity is deferred.

render-to-string.ts already used renderScreenReaderOutput and is unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(parity): ledger — G03 pr-open, reconcile G02 merged, track G17 (SR edges)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 01:40:59 +08:00