Skip to content

fix(parser): close an open <p> for li, dd, dt, listing, plaintext and xmp - #2547

Open
ybai08 wants to merge 1 commit into
fb55:masterfrom
ybai08:fix/p-closed-by-list-items
Open

ybai08 wants to merge 1 commit into
fb55:masterfrom
ybai08:fix/p-closed-by-list-items

Conversation

@ybai08

@ybai08 ybai08 commented Oct 18, 2026 •

Copy link
Copy Markdown

Follow-up to #2493. In the WHATWG "in body" insertion mode, the li, dd, dt, listing, plaintext and xmp start tags also close a <p> in button scope (spec). They were still missing from openImpliesClose, so htmlparser2 nested them inside the open <p>.

This matters most for list items that contain a paragraph:

Input Before After (matches browsers)
<ul><li><p>a<li>b</ul> <ul><li><p>a<li>b</li></p></li></ul> <ul><li><p>a</p></li><li>b</li></ul>
<dl><dt><p>a<dd>b</dl> <dl><dt><p>a<dd>b</dd></p></dt></dl> <dl><dt><p>a</p></dt><dd>b</dd></dl>
<p>a<xmp>b</xmp> <p>a<xmp>b</xmp></p> <p>a</p><xmp>b</xmp>

Changes:

  • add p to the sets that li, dd and dt close, so a <p> on top of the stack is closed first and the previous list item is closed after it;
  • add listing, plaintext and xmp with pTag.

Unchanged: <div><li> and <p><button><li> (the <p> is not in button scope there).

Tests: added cases to src/Parser.spec.ts that check the order of open and close events.

The suite was run:

  • npx vitest run: 208 passed. With src/Parser.ts reverted to main, the 7 new tests fail with assertion errors such as expected [ '<p>', '<li>', '</li>', '</p>' ] to deeply equal [ '<p>', '</p>', '<li>', '</li>' ].
  • npm run lint:es, npm run lint:ts, npm run build: pass.
  • biome check src package.json README.md biome.json: clean. A plain biome check . processed no files in the local checkout because its path contains a dot-directory, which the !**/.* include pattern excludes.

Not run: tests in downstream packages (domhandler, cheerio).

View guided diff

Summary by CodeRabbit

  • Bug Fixes
    • Improved HTML parsing so open paragraphs close automatically before <li>, <dd>, <dt>, <listing>, <plaintext>, and <xmp> elements.
    • When a paragraph closes before a new list or description item, the preceding <li> or <dt> is now closed first, keeping tag events in the expected order.

… xmp

Per the WHATWG tree construction rules for "in body", the start tags
li, dd, dt, listing, plaintext and xmp close a <p> element in button
scope, the same as the block elements already in openImpliesClose.
htmlparser2 nested these elements inside the open <p> instead.

This also fixes list items that contain a paragraph:
`<ul><li><p>a<li>b</ul>` previously nested the second <li> inside the
first <p>; it now closes the <p> and the previous <li>, as browsers do.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-18T08:38:00.810138Z 86b3187 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 937c5d48-cf93-404d-996c-055899378cba
📥 Commits

Reviewing files that changed from the base of the PR and between a4c60b8 and 86b3187.

📒 Files selected for processing: 2
  • src/Parser.spec.ts
  • src/Parser.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

📝 Walkthrough

The parser now implicitly closes an open <p> before <dd>, <dt>, <li>, <listing>, <plaintext>, and <xmp>. Tests check tag event order for these cases and for closing an open <li> or <dt>.

Changes: Paragraph implied-closing rules

Layer / File(s) Summary
Update implied-closing rules
src/Parser.ts, src/Parser.spec.ts
The implied-close rules now include the specified tags. Tests check paragraph closure and the order of closing an open <li> or <dt> before the next item opens.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix

Suggested reviewers: fb55

Merge Risk: ⚪ Minimal · up to 86b31

The change makes list items, description items, and listing/plaintext/xmp tags close an open paragraph, matching the existing parser behavior for other block tags. No merge-blocking risk remains.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main parser fix. It identifies the affected HTML tags and matches the changeset.
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit checks each tag in line
As paragraphs close at the proper time
List items follow, events in view
Description terms close neatly too
The parser hops through markup anew

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/Parser.ts">

<violation number="1" location="src/Parser.ts:26">
P2: This is a top-of-stack check, not a button-scope check: `<p><span>x<li>` still nests the list item under the paragraph, while `<button><p>x<li>` closes a paragraph outside button scope. Use a scope-aware close routine for these start tags.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Comment thread src/Parser.ts
["body", new Set(["head", "link", "script"])],
["a", new Set(["a"])],
["li", new Set(["li"])],
["li", new Set(["li", "p"])],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This is a top-of-stack check, not a button-scope check: <p><span>x<li> still nests the list item under the paragraph, while <button><p>x<li> closes a paragraph outside button scope. Use a scope-aware close routine for these start tags.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/Parser.ts, line 26:

<comment>This is a top-of-stack check, not a button-scope check: `<p><span>x<li>` still nests the list item under the paragraph, while `<button><p>x<li>` closes a paragraph outside button scope. Use a scope-aware close routine for these start tags.</comment>

<file context>
@@ -23,7 +23,7 @@ const openImpliesClose = new Map<string, Set<string>>([
     ["body", new Set(["head", "link", "script"])],
     ["a", new Set(["a"])],
-    ["li", new Set(["li"])],
+    ["li", new Set(["li", "p"])],
     ["p", pTag],
     ["h1", headingTags],
</file context>

@greptile-apps

greptile-apps Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge.

Summary

Adds paragraph-closing rules for li, dd, dt, listing, plaintext, and xmp.

  • These six tags now close an open paragraph before they open.

Reviews (1) · Last reviewed commit: "fix(parser): close an open <p> for li, d..." · Reviewed by Greptile

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.

1 participant