docs/solutions/logic-errors/2026-05-09-block-only-html-paragraphs-must-not-wrap-block-voids.md
Lexical's ImageHTML.test.ts exports a no-caption image as <p></p>.
In Slate v2's paste-html example, image is a block void. Importing that HTML
as a paragraph containing an image creates the wrong document shape.
<p></p>
export shape.Keep the test strict and unwrap paragraph wrappers that only contain block elements:
if (nodeName === 'P') {
const meaningfulChildren = getMeaningfulChildren(children)
if (
meaningfulChildren.length > 0 &&
meaningfulChildren.every(isTopLevelBlock)
) {
return meaningfulChildren
}
}
The browser proof covers both source shapes:
<p></p>
imports as one block image with no text.<figure><figcaption>caption text</figcaption></figure> imports as
one image plus following caption text.HTML <p> is often a source wrapper, not a Slate paragraph contract. When its
meaningful children are already block elements, keeping the paragraph wrapper
turns a valid block into an invalid nested block. Unwrapping only block-only
paragraphs preserves normal text paragraphs while keeping block images at the
right level.
paste-html-import.ts changes, run the focused browser row and the full
paste-html.test.ts file.