Skip to content

End list items at block lines, keep nested indentation, footnotes in items - #312

Merged
dereuromark merged 4 commits into
masterfrom
fix/container-lazy-lines
Oct 16, 2026
Merged

dereuromark merged 4 commits into
masterfrom
fix/container-lazy-lines

Conversation

@dereuromark

Copy link
Copy Markdown
Contributor

Four list and definition list differences from djot.js 9790d4d, one commit each.

Unindented block line after a list item

- para
# H

djot.js ends the list and parses the heading after it. djot-php gave one item with the text para # H. Same for * * *, > tail, | a | and ::: at column 0.

The syntax description does not settle this. Block quotes call the prefix optional only on "regular paragraph lines", and jgm/djot#290 states the rule djot.js follows: "If a line would not start any other kind of block (besides a paragraph), and the last open container is a paragraph, then it gets added to that paragraph." jgm/djot#416 asks for that in the doc and jgm/djot#413 proposes the other reading, so this follows djot.js until upstream decides. djot-php already used the rule for block quotes (#309) and definition lists; #309 left the list case open for this reason. The syntax guide gets a short section on it, next to the block quote one.

One existing test changed: testNestedListsOptionIsSmallerSubset put a quote line after a compact sublist. That line now ends the sublist instead of joining its text, so the test checks the sublist case and the quote case separately. The quote still does not interrupt the item's paragraph.

Continuation lines keep their indentation

- - a
    - b

djot.js: one inner item with the text a - b. djot-php: a and b as two inner items. The outer item stripped all leading whitespace from its continuation lines, so the inner list could not see that - b sat after its paragraph text. Doc (List item): "an indented list marker on the line directly after paragraph text does not begin a sublist; it is taken as lazy continuation of the paragraph." Lines now lose only the item's content indentation. This commit is also what keeps the first change from splitting nested items.

Footnote in a list item

- [^p]: n
lazy

djot.js: note text n lazy. djot-php: lazy became a top-level paragraph, because the list tracker read the note line as a reference definition. Doc: "The contents of the note are parsed as block-level content."

Definition body indented by one space

: t

 x

djot.js keeps x in the definition; djot-php needed two spaces and put it after the list. Doc (List item): "followed by one or more lines, indented relative to the list marker".

Measured against djot.js

On the 4853 generated block-family inputs, djot-php differed from djot.js on 1282 before (after #311) and 1077 after: 1246, 1127, 1123 and 1077 after each commit. 220 cases moved to matching and 15 the other way. Most of those 15 come from the one-space body: an attribute line indented by one space at the end of a definition now goes to the dd, as a two-space one already did ("Definition List Attributes (Extension)"), where djot.js applies it to the block after the list. The rest are a reference URL continued inside a definition and a quote nested in a list nested in a definition.

Not in this PR: a term continued on the next line (: t, then tail) is a separate change to how existing documents render, so it gets its own PR.

A text continuation line of a list item lost all its leading whitespace
before the item's content was parsed again. A container nested in the item
then could not tell whether the line reached its own content column, so

    - - a
        - b

turned `- b` into a second item of the inner list, where djot.js keeps it
as paragraph text ("an indented list marker on the line directly after
paragraph text does not begin a sublist"). A line in a footnote inside an
item lost its place in the note the same way.

Continuation lines now lose only the item's content indentation, as fence
and div content already did.
An unindented line after a list item's paragraph was always taken as lazy
text, so `- para` followed by `# H` gave one item with the text "para # H".
djot.js ends the list there and parses the heading after it, the same rule
djot-php already used for block quotes and definition lists: a lazy line
only continues a paragraph when it would not start another block.

The nestedListsWithoutBlankLine option test used a quote line after a
compact sublist. That line now ends the sublist instead of joining its text,
so the test checks the sublist and the quote case separately.
The list item tracker read `[^p]: n` as a reference definition, which has
no paragraph to extend, so in

    - [^p]: n
    lazy

`lazy` ended the list and became a top-level paragraph. djot.js continues
the note's paragraph (note text "n lazy"). The tracker now follows the
note's content like a list marker's.

The note's paragraph is the one that is open, so a line that opens a block
and is not indented past the note's marker closes the note before the item
looks at it: `1. [^n]: para`, ` | a |`, `tail` keeps the table in the item
and `tail` after the list, as before.
A definition body line needed two spaces of indentation; with one it fell
out of the list, so `: t`, blank, ` x` put `x` in a paragraph after the
list. djot.js keeps it in the definition: the syntax description's list item
rule is "followed by one or more lines, indented relative to the list
marker", and the `:` marker sits in column 0.
@dereuromark dereuromark added bug Something isn't working bc-breaking labels Oct 16, 2026
@codecov

codecov Bot commented Oct 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.06%. Comparing base (c3e8319) to head (776a799).

Additional details and impacted files
@@             Coverage Diff              @@
##             master     #312      +/-   ##
============================================
- Coverage     93.07%   93.06%   -0.01%     
- Complexity     4721     4729       +8     
============================================
  Files           118      118              
  Lines         12631    12635       +4     
============================================
+ Hits          11756    11759       +3     
- Misses          875      876       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bc-breaking bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant