Skip to content

List continuation marker: attach a block to a list item with +#228

Closed
dereuromark wants to merge 7 commits into
masterfrom
proposal/list-continuation-marker
Closed

List continuation marker: attach a block to a list item with +#228
dereuromark wants to merge 7 commits into
masterfrom
proposal/list-continuation-marker

Conversation

@dereuromark

Copy link
Copy Markdown
Contributor

Draft / proposal / demo. Always-on. A djot-php addition (not canonical djot — djot.js has no + continuation marker). The official djot test suite stays green. Companion to #227 (compact list blocks); this one is the explicit, no-indent variant.

What it does

A lone + on its own line, at the list-marker column, attaches the following block to the current list item — no blank line, list stays tight, and the block body is not indented. (AsciiDoc's list-continuation idiom.)

- Build the image
+
```sh
docker build -t app .
  • Push it
→
```html
<ul>
<li>
Build the image
<pre><code class="language-sh">docker build -t app .
</code></pre>
</li>
<li>
Push it
</li>
</ul>

A quote, table or ::: admonition attaches the same way:

- item
+
> a note attached to the item
- next

<li>\nitem\n<blockquote><p>a note attached to the item</p></blockquote>\n</li> + <li>\nnext\n</li>.

Why — where it beats plain indentation

#227 already lets an indented block stay tight. + adds the no-indent case, which matters when indentation is painful:

  • Pasting code — no re-indenting every line by the marker width.
  • Deep / wide markers — under 10. or three levels deep, the required indent is 4–8 spaces; + keeps the block flush-left.

It adds no new structure (same result is reachable by indenting under the item); it's authoring sugar for the flush-left case.

Collision safety

+ is a bullet marker — but only + + content is a bullet. A bare + is not, so:

  • inside a +-bulleted list it's unambiguous (not an empty sibling item);
  • outside any list a lone + stays ordinary paragraph text (<p>+</p>).

Both pinned in tests.

Implementation

  • The item-content collector stops at a bare + (instead of swallowing it as lazy continuation); the list loop then attaches the following flush-left block(s) to the last item and keeps the list tight.
  • One block per +, up to the next blank line / sibling item / further +.

Tests & docs

  • ListContinuationMarkerTest — attach code/quote, no-loosen, bullet + outside-list non-collision.
  • Full suite 2539 green, official djot suite 250/250.
  • Docs: new "List Continuation Marker" section in guide/syntax.md, flagged as a djot-php addition.

Status / relationship to #227

Independent branch from master. #227 (compact list blocks) is the zero-syntax win for the common case; this PR is the explicit + variant for non-indented blocks. They can land independently or together. Draft for discussion on whether the + sigil is worth carrying in a djot port vs leaving it to dialects.

A lone `+` at the list marker column attaches the following block to the current
item with no blank line, keeping the list tight, without indenting the block
body (AsciiDoc-style continuation). Useful for code blocks, tables, admonitions
and quotes inside tight items -- especially deeply nested or wide-marker lists
where indentation is large or paste-hostile.

A bare `+` is never a bullet (a bullet needs `+ ` + content), so it does not
collide with `+`-bulleted lists; outside a list it stays literal paragraph text.

- BlockParser: the item-content collector stops at a bare `+`, and the list loop
  then attaches the following flush-left block(s) to the last item and keeps the
  list tight.
- Docs: new "List Continuation Marker" section in guide/syntax.md, flagged as a
  djot-php addition (not canonical djot).
- Tests: ListContinuationMarkerTest (attach code/quote, no-loosen, bullet/outside
  non-collision). Full suite + official suite green.

This is authoring sugar, not new structure -- the same result is reachable by
indenting the block under the item.
@codecov

codecov Bot commented Jun 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.91%. Comparing base (d4de671) to head (d72b4ce).

Additional details and impacted files
@@             Coverage Diff              @@
##             master     #228      +/-   ##
============================================
+ Coverage     91.87%   91.91%   +0.04%     
- Complexity     3512     3538      +26     
============================================
  Files           105      105              
  Lines          9944     9995      +51     
============================================
+ Hits           9136     9187      +51     
  Misses          808      808              

☔ 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.

The `+` list-continuation marker was a generic "attach the next block to
the current item" sigil: it consumed the `+` for any following block
(including headings and thematic breaks) and even when a blank line sat
around it, where a detached block could then swallow the next sibling.

Recognize `+` only in the sole valid shape `x` / `+` / `y`: a lone `+` at
the marker column with content immediately before and after it (no blank
line on either side), and only when the following block is a container or
verbatim block (blockquote, fenced code/raw, table, div/admonition).
Anything else leaves the `+` as ordinary text, matching plain parsing.

Add tests for table/div attachment, leaf-block rejection, and the
blank-line-around cases. Document the tight form, the strict attach set,
and the portable canonical alternative (indent the block, use a `:::` div
for callouts).
Add a test for a trailing + with no following block, and simplify opensAttachableContinuationBlock to a single expression so codecov sees every new line exercised.
Add a test where the block after + is indented (not flush at the marker column), exercising the remaining new patch line for codecov.
…kquote

Locks the list-item scoping: + attaches inside a quote only when the quote contains a list, and stays literal text when it does not.
`+` could only attach a block after item text (`x` / `+` / `y`). Starting
an item *with* a block needed an empty item written as `- ` with a
trailing space, which lint rules forbid.

Add the trailing-whitespace-free form `- +` (marker + bare `+`): when the
item's only content is `+` and an attachable container/verbatim block
follows flush-left, attach it as the item's sole content. The lone-`+`
and `- +` paths now share attachContinuationBlock()/nextLineOpensAttachableBlock().

Drop an unreachable dedent guard in the collector (nested lists parse on
sliced arrays, so a line below the marker column never reaches it). Cover
table/quote/code attachment, ordered lists, leaf-block rejection, chained
markers, blank-line termination, and nested-list cases.
@dereuromark

Copy link
Copy Markdown
Contributor Author

Moving to https://github.com/markup-carve/carve for the + bullet point operator collision here (and upstream denied).

@dereuromark dereuromark closed this Jun 7, 2026
@dereuromark dereuromark deleted the proposal/list-continuation-marker branch June 7, 2026 12:39
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.

1 participant