Chinesezjc
fdcb45b619
fix(web): bound the SGR state and follow real terminal widths
...
Nine findings, one critical. Terminal cases verified in a real terminal first.
CRITICAL: cells held the accumulated SGR history, so every state boundary
re-emitted the whole chain — output switching color without a full reset
emitted O(n^2) characters. Measured: 3200 such cells produced 25 MB, and the
reviewer's ~90 KB alternating-color case is well under bash's own output cap.
State is now a normalized record (foreground, background, attribute set) with
one canonical sequence per boundary, so the emitted text is linear in cells;
the 90 KB case parses in 36 ms. That also makes the attribute closers every
chalk-based tool writes actually close: `\x1b[1mbold\x1b[22mplain` leaves the
following write PLAIN, which a real terminal confirms.
Width follows emoji presentation, not the U+2600-U+27BF block: `A✓B` redrawn
with `XY` shows `XYB`, so the check every progress line writes is ONE column.
Taking the block as wide misaligned exactly the output this card exists for.
Writing over either half of a wide pair blanks the other, since a terminal
cannot leave one cell of a two-cell glyph standing.
`line\n\x1b[0m` does not end in a newline as a string yet its last parsed line
holds nothing visible, so the terminator check now reads the parsed lines — it
had added a blank row and inflated the collapse count.
A line with no cursor movement no longer builds a column buffer at all; only
its SGR is folded, so an `ls -R` or a 5k-line log allocates nothing per
character.
The `.terminalDescription` rule had been inserted into an existing grouped
selector, silently giving `.codeBody` description typography and changing its
bottom margin from 4px to 0 — a pre-existing surface this PR does not own.
Split out, `.codeBody`'s margin restored.
Three comments contradicted their code: the fixture's exit-marker line (still
claiming recovery from a marker deliberately removed), `bash-sample`'s header
(still routing a click to the details panel, and calling the consumer's cap the
block's own), and a DetailsPanel comment stacked above the wrong rule. The
ui-primitives README documented only the CR/BS half of the replay, so a reader
would expect `OK0%` where `100%\r\x1b[KOK` renders `OK`.
2026-07-29 16:42:10 +08:00
..
2026-07-25 01:58:42 +08:00
2026-07-24 23:43:10 +08:00
2026-07-25 01:58:42 +08:00
2026-07-27 14:01:15 +08:00
2026-07-27 14:01:15 +08:00
2026-07-27 14:01:15 +08:00
2026-07-23 19:48:00 +08:00
2026-07-23 19:33:30 +08:00
2026-07-23 19:48:00 +08:00
2026-07-27 21:17:49 +08:00
2026-07-27 21:17:49 +08:00
2026-07-27 21:17:49 +08:00
2026-07-24 16:36:34 +08:00
2026-07-23 00:10:53 +08:00
2026-07-24 16:36:34 +08:00
2026-07-24 13:57:16 +08:00
2026-07-22 23:07:14 +08:00
2026-07-24 13:57:16 +08:00
2026-07-27 18:27:39 +08:00
2026-07-27 18:27:39 +08:00
2026-07-27 18:27:39 +08:00
2026-07-28 17:58:09 +08:00
2026-07-28 17:58:09 +08:00
2026-07-28 17:58:09 +08:00
2026-07-27 17:38:42 +08:00
2026-07-27 17:38:42 +08:00
2026-07-27 17:38:42 +08:00
2026-07-28 14:41:51 +08:00
2026-07-28 14:41:51 +08:00
2026-07-28 14:41:51 +08:00
2026-07-27 17:38:42 +08:00
2026-07-27 17:38:42 +08:00
2026-07-27 17:38:42 +08:00
2026-07-28 14:41:51 +08:00
2026-07-28 14:41:51 +08:00
2026-07-28 14:41:51 +08:00
2026-07-25 01:58:42 +08:00
2026-07-24 23:43:10 +08:00
2026-07-25 01:58:42 +08:00
2026-07-28 00:42:33 +08:00
2026-07-28 00:58:33 +08:00
2026-07-28 00:58:33 +08:00
2026-07-28 21:51:13 +08:00
2026-07-28 21:51:13 +08:00
2026-07-28 21:51:13 +08:00
2026-07-24 13:57:16 +08:00
2026-07-22 23:07:14 +08:00
2026-07-24 13:57:16 +08:00
2026-07-28 21:51:13 +08:00
2026-07-28 21:51:13 +08:00
2026-07-28 21:51:13 +08:00
2026-07-25 01:58:42 +08:00
2026-07-24 23:43:10 +08:00
2026-07-25 01:58:42 +08:00
2026-07-26 02:33:29 +08:00
2026-07-26 02:33:29 +08:00
2026-07-26 02:33:29 +08:00
2026-07-27 21:20:06 +08:00
2026-07-27 21:20:06 +08:00
2026-07-27 21:20:06 +08:00
2026-07-27 04:14:51 +08:00
2026-07-27 04:14:51 +08:00
2026-07-27 04:14:51 +08:00
2026-07-26 02:33:29 +08:00
2026-07-26 02:33:29 +08:00
2026-07-26 02:33:29 +08:00
2026-07-26 23:06:00 +08:00
2026-07-26 23:06:00 +08:00
2026-07-26 23:06:00 +08:00
2026-07-24 17:39:22 +08:00
2026-07-22 23:07:14 +08:00
2026-07-24 17:39:22 +08:00
2026-07-26 02:33:29 +08:00
2026-07-26 02:33:29 +08:00
2026-07-26 02:33:29 +08:00
2026-07-22 21:37:30 +08:00
2026-07-22 21:37:30 +08:00
2026-07-22 21:37:30 +08:00
2026-07-25 16:43:07 +08:00
2026-07-25 16:43:07 +08:00
2026-07-25 16:43:07 +08:00
2026-07-24 01:40:25 +08:00
2026-07-24 01:40:25 +08:00
2026-07-24 01:40:25 +08:00
2026-07-28 14:49:59 +08:00
2026-07-28 14:49:59 +08:00
2026-07-28 14:49:59 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-24 01:40:25 +08:00
2026-07-24 01:40:25 +08:00
2026-07-24 01:40:25 +08:00
2026-07-24 01:40:25 +08:00
2026-07-24 01:40:25 +08:00
2026-07-24 01:40:25 +08:00
2026-07-26 14:29:30 +08:00
2026-07-26 14:05:33 +08:00
2026-07-26 14:05:33 +08:00
2026-07-20 20:35:15 +08:00
2026-07-20 20:35:15 +08:00
2026-07-20 20:35:15 +08:00
2026-07-24 22:12:23 +08:00
2026-07-24 22:12:23 +08:00
2026-07-24 22:12:23 +08:00
2026-07-26 14:29:30 +08:00
2026-07-26 14:05:33 +08:00
2026-07-26 14:05:33 +08:00
2026-07-27 21:20:06 +08:00
2026-07-27 21:20:06 +08:00
2026-07-27 21:20:06 +08:00
2026-07-28 23:13:28 +08:00
2026-07-28 23:13:28 +08:00
2026-07-28 23:13:28 +08:00
2026-07-20 21:16:40 +08:00
2026-07-20 21:16:40 +08:00
2026-07-20 21:16:40 +08:00
2026-07-28 13:58:06 +08:00
2026-07-28 13:58:06 +08:00
2026-07-28 13:58:06 +08:00
2026-07-22 14:29:52 +08:00
2026-07-22 14:29:52 +08:00
2026-07-22 14:29:52 +08:00
2026-07-22 14:29:52 +08:00
2026-07-22 14:29:52 +08:00
2026-07-22 14:29:52 +08:00
2026-07-22 14:29:52 +08:00
2026-07-22 14:29:52 +08:00
2026-07-22 14:29:52 +08:00
2026-07-28 14:41:51 +08:00
2026-07-28 14:41:51 +08:00
2026-07-28 14:41:51 +08:00
2026-07-24 01:29:35 -07:00
2026-07-24 01:29:35 -07:00
2026-07-24 01:29:35 -07:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-28 23:34:19 +08:00
2026-07-28 23:34:19 +08:00
2026-07-28 23:34:19 +08:00
2026-07-22 20:35:38 +08:00
2026-07-22 20:35:38 +08:00
2026-07-22 20:35:38 +08:00
2026-07-27 21:30:28 +08:00
2026-07-27 21:30:28 +08:00
2026-07-27 21:30:28 +08:00
2026-07-23 17:39:30 +08:00
2026-07-23 17:39:30 +08:00
2026-07-23 17:39:30 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 12:04:12 +08:00
2026-07-27 12:04:12 +08:00
2026-07-27 12:04:12 +08:00
2026-07-24 19:15:04 +08:00
2026-07-24 19:15:04 +08:00
2026-07-24 19:15:04 +08:00
2026-07-28 17:58:09 +08:00
2026-07-28 17:58:09 +08:00
2026-07-28 17:58:09 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-25 18:27:39 +08:00
2026-07-25 18:27:39 +08:00
2026-07-25 18:27:39 +08:00
2026-07-26 01:16:41 +08:00
2026-07-26 01:16:41 +08:00
2026-07-26 01:16:41 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 16:12:40 +08:00
2026-07-27 16:12:40 +08:00
2026-07-27 16:12:40 +08:00
2026-07-26 01:30:14 +08:00
2026-07-26 01:30:14 +08:00
2026-07-26 01:30:14 +08:00
2026-07-29 00:39:56 +08:00
2026-07-29 00:39:56 +08:00
2026-07-29 00:39:56 +08:00
2026-07-27 12:38:11 +08:00
2026-07-27 12:38:11 +08:00
2026-07-27 12:38:11 +08:00
2026-07-26 22:53:47 +08:00
2026-07-26 22:53:47 +08:00
2026-07-26 22:53:47 +08:00
2026-07-26 03:29:22 +08:00
2026-07-26 02:43:34 +08:00
2026-07-26 03:29:22 +08:00
2026-07-26 04:24:13 +08:00
2026-07-26 04:02:38 +08:00
2026-07-26 04:24:13 +08:00
2026-07-26 15:26:52 +08:00
2026-07-26 15:26:52 +08:00
2026-07-26 15:26:52 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 03:50:22 -07:00
2026-07-27 03:50:22 -07:00
2026-07-27 03:50:22 -07:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-27 18:55:13 +08:00
2026-07-28 01:41:32 +08:00
2026-07-28 01:41:32 +08:00
2026-07-28 01:41:32 +08:00
2026-07-27 15:52:35 +08:00
2026-07-27 15:52:35 +08:00
2026-07-27 15:52:35 +08:00
2026-07-28 17:36:44 +08:00
2026-07-28 17:36:44 +08:00
2026-07-28 17:36:44 +08:00
2026-07-28 19:43:56 +08:00
2026-07-28 19:43:56 +08:00
2026-07-28 19:43:56 +08:00
2026-07-28 14:24:41 +08:00
2026-07-28 14:24:41 +08:00
2026-07-28 14:24:41 +08:00
2026-07-29 16:42:10 +08:00
2026-07-29 16:42:10 +08:00
2026-07-29 16:42:10 +08:00
2026-07-29 14:21:44 +08:00
2026-07-29 14:21:44 +08:00
2026-07-29 14:21:44 +08:00