Repository navigation
Parse a list item's blocks in one piece - #316
Merged
Merged
Conversation
The HTML renderer only stripped the <p> from the first paragraph of a
tight item. A paragraph after a code block, a table or a nested list kept
its tag:
- ```
x
```
para
djot.js renders `para` bare, like the first paragraph. The renderer now
unwraps each direct paragraph child of a tight item. A paragraph with its
own attributes keeps the tag, as the first one already did.
Two tests encoded the old mixed output (`A` bare, `<p>C</p>` in the same
tight item) and now expect the djot.js output.
A list item's first block and the indented lines after a blank line were
parsed separately, so a container the first block opens could not take
them. In
- : t
tail
djot.js puts `tail` in the definition; djot-php closed the definition list
and added a paragraph after it. A note (`- [^n]: para`, blank, indented
`tail`) lost its second paragraph the same way. The item's lines are now
collected and parsed once when the item ends. The syntax description: a
list item is "a list marker followed by a space (or a newline) followed by
one or more lines, indented relative to the list marker".
Any line indented past the marker belongs to the item, so a paragraph
indented less than an earlier one no longer ends the list:
- a
deep
back
Lines keep their columns relative to the item, so a reference definition
continued one column deeper (` [r]: /u`, ` tail`) still continues.
Tightness is decided from the parsed item. "A list is classed as tight if
it does not contain blank lines between items, or between blocks inside an
item", and the example after it keeps a list tight when a blank line comes
before a sublist. For blank lines inside nested containers the text leaves
it open, so this follows djot.js, which gives a blank line to the innermost
open list: one inside a nested definition or note, after a nested list or
note, or before a sublist does not loosen the outer list. Before, any
indented non-marker line after a blank line made the list loose, so
`- : t`, blank, ` para`, `- two` rendered loose.
A test that matched `<p>A</p>` in `- A`, blank, ` - B`, blank, ` P`,
blank, ` C` now expects the djot.js output, a tight outer list.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #316 +/- ##
============================================
+ Coverage 93.07% 93.13% +0.05%
- Complexity 4735 4757 +22
============================================
Files 118 118
Lines 12642 12706 +64
============================================
+ Hits 11767 11834 +67
+ Misses 875 872 -3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This was referenced Oct 16, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The list item restructure left open in #315, plus the renderer change it needs. One commit each.
Parse a list item's blocks in one piece
A list item's first block and the indented lines after a blank line were parsed separately, so a container the first block opened could not take them:
djot.js puts
tailin the definition. djot-php closed the definition list and added a paragraph after it. A note (- [^n]: para, blank, indentedtail) lost its second paragraph the same way. The item's lines are now collected and parsed once when the item ends. The syntax description: a list item is "a list marker followed by a space (or a newline) followed by one or more lines, indented relative to the list marker".Two changes follow from that:
- a, blank,deep, blank,backputbackafter the list).[r]: /ufollowed bytailstill continues the reference definition.Tightness is now decided from the parsed item. The syntax description: "A list is classed as tight if it does not contain blank lines between items, or between blocks inside an item", and its example keeps a list tight when a blank line comes before a sublist. For blank lines inside nested containers the text leaves it open, so this follows djot.js, which gives a blank line to the innermost open list. A blank line inside a nested definition or note, after a nested list or note, or before a sublist does not loosen the outer list. Before, any indented non-marker line after a blank line made the list loose.
Render every paragraph of a tight item without its wrapper
The HTML renderer only unwrapped the first paragraph of a tight item:
djot.js renders
parabare. Each direct paragraph of a tight item is now unwrapped. A paragraph with its own attributes keeps its tag, as the first one already did. With the tightness change above, a tight item can hold more than one paragraph (- A, blank,- B, blank,C), so this commit comes first.Behavior changes
Documents render differently in these cases, hence
bc-breaking:- : t, blank,para,- two;- - x, blank,- b);<p>.Three existing tests encoded the old output and now expect the djot.js output.
Measured against djot.js
On the 4853 generated block-family inputs, djot-php differed from djot.js
9790d4don 978 before, 972 after the renderer commit and 852 after the restructure. One case moved the other way:- [^n]: para, blank, an indented{#x}, thentail. djot.js applies the note's attribute to the paragraph after the list, which looks like the known attribute leak out of a note.On a separate set of 1080 list item bodies (definitions, notes, quotes, code, nested lists, tight and loose, followed by a sibling or by text), matches with djot.js went from 617 to 880, and none of the 617 stopped matching.
Still differing for definitions: djot.js renders
<dd> para </dd>without<p>inside a tight list, because its renderer gives a definition list the outer list's tightness. A definition list on its own renders<p>in both, so djot-php keeps the<p>.