Commit b3fc1f7
authored
fix(ui): render numerals for ordered list items (#520)
* feat(parser): detect ordered list markers and compute display indices
The block parser collapsed `*`, `-`, and `\d+.` markers into a single
`list-item` block type, discarding ordered/unordered status. Add
`ordered` + `orderedStart` to Block, capture the numeric marker in the
list regex, and introduce `computeListIndices()` — a pure helper that
walks a list group and assigns each ordered item a CommonMark-correct
display number (sequential renumbering, streak break/restart on
unordered items, deeper-level state truncation, top-level numbering
preserved across nested children).
21 new unit tests cover both the parser changes and the indexing
helper, including the tricky cases: `1./2./99.` renumbers as 1,2,3;
sub-bullets between ordered items keep the top-level streak alive;
nested ordered sublists number independently and reset between
siblings; numeric checkboxes set both `ordered` and `checked`.
For provenance purposes, this commit was AI assisted.
* feat(ui): render numerals for ordered list items
Branch the list-item marker span on `block.ordered`: render
`${index}.` (with `tabular-nums` and a 1.5rem min-width to keep
columns stable across single- and double-digit numerals) when the
source marker was numeric, otherwise fall through to the existing
`•`/`◦`/`▪` bullet symbols. Indices come from `computeListIndices()`
called once per list group; `groupBlocks` is unchanged so mixed
nested lists still share a single `data-pinpoint-group="list"`
hover wrapper and annotation anchoring is unaffected. Checkbox
items still take precedence over numerals.
Adds a real-world manual fixture (06-ordered-list-plan.md) whose
`## Verification` section exercises a 10-item ordered list, the
case that originally surfaced the bug.
For provenance purposes, this commit was AI assisted.
* fix(parser): merge consecutive blockquote lines into one block
Each `>` line was emitted as its own blockquote block, so the
renderer's `my-4` margin produced visible gaps between every line
of a multi-line quote (the parser had a literal TODO comment:
"Check if previous was blockquote, if so, merge? No, separate for
now"). Fix: append to the previous block when it's a blockquote
and the prior line wasn't blank, mirroring the list-continuation
pattern. A blank line still breaks the quote so two `>` runs
separated by a blank line stay distinct.
Adds 5 unit tests (merge, blank-line break, paragraph boundaries,
single-line) and a manual fixture (07-blockquotes.md) covering the
bug case, the blank-line-break case, sandwich-between-paragraphs,
and inline markdown across merged lines.
For provenance purposes, this commit was AI assisted.
* fix(ui): address code review — diff view, task lists, blockquote paragraphs
Three issues surfaced by PR review #520:
1. **Diff view flattened ordered lists to bullets.** PlanCleanDiffView's
SimpleBlockRenderer duplicated Viewer's list-item JSX with hardcoded
bullet symbols, so a denied+resubmitted plan with numbered steps
showed numerals in the main view but `•` in the diff view — exactly
the screen where "which step changed?" matters most. Fixed by
threading computeListIndices through MarkdownChunk and sharing the
marker rendering via a new ListMarker component used by both
renderers, which also removes the root-cause duplication.
2. **Ordered task lists dropped their numbers.** `1. [ ] step` set both
`ordered=true` and `checked=false` in the parser, but the renderer's
checkbox branch took precedence and the numeral was never shown.
GitHub renders `1. [ ]` as numeral + checkbox side by side; we now
match that by rendering both glyphs in ListMarker when an ordered
task list item appears.
3. **Multi-paragraph blockquotes collapsed.** After the blockquote-merge
fix in the previous commit, `> a\n>\n> b` produced content
`"a\n\nb"` but the renderer passed it straight to InlineMarkdown,
which renders `\n\n` as whitespace — so two quoted paragraphs
mashed into one line. Fixed by splitting blockquote content on
`/\n\n+/` in both Viewer and PlanCleanDiffView and emitting one
`<p>` child per paragraph.
Adds one unit test for the multi-paragraph blockquote content shape and
a manual fixture (08-ordered-edge-cases.md) covering ordered task lists,
multi-paragraph quotes, nested-bullet counter preservation, double-digit
alignment, and start-at-N numbering.
The fourth review comment — loose ordered lists with intervening non-list
blocks restarting numbering — is deferred. It requires parser-level
loose-list detection (CommonMark's indented-continuation rule) and the
bug only fires when users rely on lazy `1./1./1.` markers across a
break. Tracked as a follow-up.
For provenance purposes, this commit was AI assisted.
* fix(parser): don't merge blockquote lines containing block-level markers
Round-two review flagged a regression: `> 1. foo\n> 2. bar\n> 3. baz` was
merging into one blockquote whose content was `"1. foo\n2. bar\n3. baz"`.
The renderer split on `\n\n+` (paragraph breaks), found none, and emitted
a single `<p>` — so `\n` collapsed to whitespace in HTML and the user
saw `"1. foo 2. bar 3. baz"` as one run-on line. Worse than the pre-PR
behavior (which at least kept each line in its own box).
Pragmatic fix: don't merge a `>` line whose stripped content starts with
a block-level marker (`*`, `-`, `\d+.`, `#`, `` ``` ``, `>`). Those stay
as separate blockquote blocks so each marker line is visually distinct
(legible, matching pre-PR behavior for quoted lists). Wrapped prose
quotes — the original motivating case — still merge correctly because
prose lines don't start with markers.
Also check the PREVIOUS block's content for markers so a trailing prose
line after a `> 1. item` doesn't glue onto the list-item block.
7 new unit tests cover: quoted ordered list stays separate, quoted
unordered list stays separate, quoted heading stays separate, quoted
code fence stays separate, nested blockquote stays separate, wrapped
prose quote still merges (regression guard), and mixed prose+list where
prose merges and list lines stay separate.
Adds tests/test-fixtures/09-quoted-list-regression.md as a manual repro.
Known follow-ups (tracked separately, not in this PR):
- Consecutive separate blockquote blocks still get individual `my-4`
margins, so a quoted list shows as stacked boxes with gaps between
lines. The proper fix is recursive blockquote parsing (render the
content as its own Block[] tree with an actual nested list inside
the quote). Deferred — requires `children?: Block[]` on Block,
parser rework, and exportAnnotations traversal changes.
- Clean diff view renumbers ordered lists from the start of each diff
chunk when users rely on CommonMark's lazy `1./1./1.` markers. Same
power-user population as the earlier deferred loose-list case.
- Pure code-hygiene items from the second review (non-list-block
handling in computeListIndices, BULLET_BY_LEVEL modulo cycle,
<ListGroup> extraction, CLAUDE.md Block interface drift,
splitBlockquoteParagraphs helper) — batch into a follow-up cleanup.
For provenance purposes, this commit was AI assisted.1 parent c342ffb commit b3fc1f7
10 files changed
Lines changed: 868 additions & 88 deletions
File tree
- packages/ui
- components
- plan-diff
- utils
- tests/test-fixtures
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
530 | 531 | | |
531 | 532 | | |
532 | 533 | | |
533 | | - | |
534 | | - | |
535 | | - | |
536 | | - | |
537 | | - | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
538 | 553 | | |
539 | 554 | | |
540 | 555 | | |
| |||
967 | 982 | | |
968 | 983 | | |
969 | 984 | | |
970 | | - | |
| 985 | + | |
| 986 | + | |
971 | 987 | | |
972 | 988 | | |
973 | 989 | | |
| |||
979 | 995 | | |
980 | 996 | | |
981 | 997 | | |
982 | | - | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
983 | 1002 | | |
984 | 1003 | | |
985 | 1004 | | |
986 | 1005 | | |
987 | 1006 | | |
988 | | - | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + | |
| 1011 | + | |
989 | 1012 | | |
990 | 1013 | | |
| 1014 | + | |
991 | 1015 | | |
992 | 1016 | | |
993 | 1017 | | |
| |||
1002 | 1026 | | |
1003 | 1027 | | |
1004 | 1028 | | |
1005 | | - | |
1006 | | - | |
1007 | | - | |
1008 | | - | |
1009 | | - | |
1010 | | - | |
1011 | | - | |
1012 | | - | |
1013 | | - | |
1014 | | - | |
1015 | | - | |
1016 | | - | |
1017 | | - | |
1018 | | - | |
1019 | | - | |
1020 | | - | |
1021 | | - | |
1022 | | - | |
1023 | | - | |
1024 | | - | |
1025 | | - | |
1026 | | - | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
1027 | 1037 | | |
1028 | 1038 | | |
1029 | 1039 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | | - | |
| 11 | + | |
| 12 | + | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| |||
409 | 410 | | |
410 | 411 | | |
411 | 412 | | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
412 | 421 | | |
413 | 422 | | |
414 | 423 | | |
415 | | - | |
416 | | - | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
417 | 430 | | |
418 | 431 | | |
419 | 432 | | |
420 | 433 | | |
421 | 434 | | |
422 | | - | |
| 435 | + | |
423 | 436 | | |
424 | 437 | | |
425 | 438 | | |
| |||
437 | 450 | | |
438 | 451 | | |
439 | 452 | | |
440 | | - | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
441 | 457 | | |
442 | 458 | | |
443 | | - | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
444 | 464 | | |
445 | 465 | | |
| 466 | + | |
446 | 467 | | |
447 | 468 | | |
448 | 469 | | |
| |||
452 | 473 | | |
453 | 474 | | |
454 | 475 | | |
455 | | - | |
456 | | - | |
457 | | - | |
458 | | - | |
459 | | - | |
460 | | - | |
461 | | - | |
462 | | - | |
463 | | - | |
464 | | - | |
465 | | - | |
466 | | - | |
467 | | - | |
468 | | - | |
469 | | - | |
470 | | - | |
471 | | - | |
472 | | - | |
473 | | - | |
474 | | - | |
475 | | - | |
476 | | - | |
477 | | - | |
478 | | - | |
479 | | - | |
480 | | - | |
481 | | - | |
482 | | - | |
483 | | - | |
484 | | - | |
485 | | - | |
486 | | - | |
487 | | - | |
488 | | - | |
489 | | - | |
490 | | - | |
491 | | - | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
492 | 482 | | |
493 | 483 | | |
494 | 484 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
| 61 | + | |
| 62 | + | |
61 | 63 | | |
62 | 64 | | |
63 | 65 | | |
| |||
0 commit comments