Skip to content

HTML writer: keep <p> in loose list items (Pandoc parity) - #1193

Open
cscheid wants to merge 3 commits into
mainfrom
bugfix/bd-nnvvomg6-loose-list-item-para
Open

cscheid wants to merge 3 commits into
mainfrom
bugfix/bd-nnvvomg6-loose-list-item-para

Conversation

@cscheid

@cscheid cscheid commented Nov 12, 2026

Copy link
Copy Markdown
Member

Loose list items rendered by q2 render lose their <p>. A loose list (blank lines between items) is made of Para items, as in Pandoc, but the HTML writer wrote any item with a single block inline. So - a blank - b rendered <li>a</li>, where Pandoc, Quarto 1, and q2 preview produce <li><p>a</p></li>. Loose task lists were affected the same way. Found during the #892 triage (bd-2ydvebkc); strand bd-nnvvomg6.

Changes

  • Writer fix (crates/pampa/src/writers/html.rs, write_blocks_inline): only a lone Plain item is written inline. A Para keeps its <p>, which matches Pandoc, since its writer also decides from the block kind alone. Unchanged: tight lists; the \n</li> whitespace after a multi-block item; and a trailing {.class}, which stays hoisted onto the <li>.
  • lmd fixture and docs. A {=: … :=} block fragment is a Para, so a list built from one fragment per item is loose. The bug was hiding that. The lmd-blog test fixture and the example in docs/guides/authoring/components.qmd now use pandoc.Plain({=[ … ]=}), as lmd.qmd already recommends for tight lists. lmd.qmd also gains a sentence saying that block-fragment items make a loose list.

The fixture and docs commit comes first, and rendered output doesn't change at that commit. As a result, no snapshot files change in this PR.

User-visible effect

Loose lists now get paragraph spacing between items in q2 render, matching Pandoc and Quarto 1. Loose task items render <li class="task-list-item"><p><label><input …/>…</label></p></li>. The checkbox-hang rule from #1191 already targets li.task-list-item > p:first-child > label > input.

Tests

  • New crates/pampa/tests/integration/test_html_list_item_para.rs: loose bullet, loose ordered, a single-Para item in a loose list, tight (unchanged), and a hoisted attr on a loose item.
  • test_task_list.rs: a loose task item.
  • New crates/quarto/tests/integration/loose_list_render.rs: an end-to-end q2 render test.

Each test except the tight-list guard was written first and failed on main. cargo xtask verify --skip-hub-build passes locally.

End-to-end: I rendered claude-notes/plans/loose-list-item-para-investigation/repro.qmd with q2 render and read the output: loose items render <li><p>…, and tight items render <li>a</li>. I didn't do a visual comparison in a browser.

Plan: claude-notes/plans/2026-11-12-loose-list-item-para.md

🤖 Generated with Claude Code

cscheid and others added 3 commits November 12, 2026 12:53
Plan skeleton + Pandoc 3.13 vs pampa repro. AST already matches Pandoc;
only write_blocks_inline is wrong. Throwaway fix measured 1 snapshot of
churn (lmd blog fixture, whose {=: :=} items are Para).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A {=: :=} block fragment is a Para, so a list built from one per item
is loose. The HTML writer currently hides that by dropping the <p>;
the next commit fixes the writer. Switch the lmd-blog fixture and the
components guide to pandoc.Plain({=[ ]=}) (as lmd.qmd already teaches
for tight lists) and say in lmd.qmd that block-fragment items make a
loose list. No rendered output changes at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
write_blocks_inline unwrapped any single-block list item, so a loose
item (Para) rendered <li>a</li> where Pandoc emits <li><p>a</p></li>.
Key on the block kind instead: only a lone Plain is written inline.
Loose task items now render <li class="task-list-item"><p><label>…,
which the existing p:first-child checkbox rule already styles, and
render now agrees with q2 preview. Multi-block whitespace and the
hoisted trailing attr (stays on the <li>) are unchanged.

Tests: test_html_list_item_para (new), a loose task-list case, and an
end-to-end q2 render test (loose_list_render). No snapshot changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@posit-snyk-bot

posit-snyk-bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

This branch has not been deployed

No deployments
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