Skip to content

Listes : numéro de départ, délimiteur « ) », lignes de continuation et imbrication CommonMark - #49

Merged
jmcollin merged 3 commits into
mainfrom
fix/list-items
Oct 8, 2026
Merged

jmcollin merged 3 commits into
mainfrom
fix/list-items

Conversation

@jmcollin

@jmcollin jmcollin commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Problème

Entrée Avant Attendu
3. three <ol> (départ perdu) <ol start="3">
1) a paragraphe liste ordonnée
- item\n continued la liste se ferme, <p>continued</p> <li>item\ncontinued</li>
10. a\n - b b à la profondeur 2 (heuristique floor(indent/2)) b enfant de a
- foo hors liste item de liste bloc de code
para\n2. x liste suite du paragraphe

Correctif (CommonMark §5.2–5.3)

  • Imbrication par colonne de contenu : le lexer maintient la pile des colonnes de contenu des items ouverts. Un item est enfant du dernier item ouvert dont il atteint la colonne. L'heuristique floor(indent / 2) disparaît.
  • Listes ordonnées : le numéro de départ est conservé (ListNode::$start, rendu <ol start="N"> quand N ≠ 1) et le délimiteur ) est accepté (1 à 9 chiffres).
  • Changer de puce (- → +) ou de délimiteur (. → )) démarre une nouvelle liste.
  • Lignes de continuation : une ligne de texte juste après un item, indentée ou paresseuse, prolonge l'item. Une ligne qui ouvre un bloc (titre, séparateur horizontal, fence, citation, autre item…) termine l'item.
  • Hors liste, un marqueur indenté de 4 colonnes ou plus est du code (ou du texte de paragraphe). Un item ordonné qui ne commence pas à 1 ne peut pas interrompre un paragraphe.
  • Performances : les lignes de continuation sont assemblées une seule fois en fin de lexing, et le test « liste ouverte » est mis en cache. 200 000 lignes de continuation ou 500 000 lignes vides restent linéaires (test dédié).
  • README : ligne « Ordered list » mise à jour.

Tests

  • Nouveau tests/Integration/ListItemTest.php (10 cas + 1 test de performance) et 3 nouveaux tests dans LexerTest.
  • 4 tests du lexer vérifiaient la profondeur floor(indent / 2) sur un item indenté seul. Selon CommonMark, - item seul est au niveau 0 et - item seul est du code. Ces tests imbriquent maintenant l'item sous un vrai parent.
  • Spec CommonMark : List items 10/48 → 17/48, Lists 6/26 → 11/26, total 389 → 401/652, sans régression ailleurs.
  • Limite connue : les items à plusieurs blocs (plusieurs paragraphes séparés par une ligne vide, code dans un item) ne sont pas encore gérés. Ils expliquent l'essentiel des échecs restants : il faudrait que les items deviennent des conteneurs de blocs, comme les blockquotes.
  • PHPUnit OK, PHPStan et Psalm sans erreur.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CPcuaaxrCottkeL1ykoSWe


Generated by Claude Code

…d continuation lines

- depth is computed from the open items' content columns (CommonMark
  §5.2) instead of floor(indent / 2): "10. a\n    - b" nests b under a,
  and a lone "  - item" is a top-level item
- ordered lists keep their start number (<ol start="3">) and accept the
  ')' delimiter; changing the bullet char or delimiter starts a new list
- paragraph text right after an item (indented or lazy) continues the
  item instead of ending the list
- outside a list, a marker indented 4+ columns is indented code (or
  paragraph text), and an ordered item not starting at 1 cannot
  interrupt a paragraph
- continuation lines are joined once at the end and the "list open"
  check is cached, so both stay linear

Four lexer tests asserted the old floor(indent / 2) depth for a lone
indented item; they now nest the item under a real parent.

CommonMark spec: List items 10/48 -> 17/48, Lists 6/26 -> 11/26.
Multi-block items (several paragraphs, code inside an item) are not
supported yet and account for most remaining failures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPcuaaxrCottkeL1ykoSWe
claude added 2 commits October 8, 2026 10:06
Conflicts in src/Lexer/Lexer.php with the blockquote laziness change
(#44) and table detection (#45), all side-by-side additions:
- quote pattern from main, list patterns from this branch
- both state blocks (quote laziness, open list columns)
- quote lazy continuation first, then list item continuation
- list item placement before table detection (it may turn an item into
  a paragraph line)

Also drops the PATTERN_TABLE_SEPARATOR reference left by #44 (same
change as #50), without which every blockquote throws on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPcuaaxrCottkeL1ykoSWe
…uation

startsBlock() (lists) duplicated the block-start checks of
isParagraphContinuation() (blockquote laziness, merged meanwhile).
List continuation now uses the shared helper; footnote definitions
still end an item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPcuaaxrCottkeL1ykoSWe
@jmcollin
jmcollin merged commit 044b3f2 into main Oct 8, 2026
6 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