fix(parser): close an open <p> for li, dd, dt, listing, plaintext and xmp
YB
14d ago+54+54+01234567890123456789-2-2-0123456789
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
pto the sets thatli,ddanddtclose, so a<p>on top of the stack is closed first and the previous list item is closed after it; - add
listing,plaintextandxmpwithpTag.
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. Withsrc/Parser.tsreverted tomain, the 7 new tests fail with assertion errors such asexpected [ '<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 plainbiome 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).
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.
- Improved HTML parsing so open paragraphs close automatically before