Skip to content

Unwrap <p> inside <li> to prevent nested w:p in OOXML - #212

Open
blshkv wants to merge 4 commits into
senny:masterfrom
blshkv:fix-p-inside-li
Open

Unwrap <p> inside <li> to prevent nested w:p in OOXML#212
blshkv wants to merge 4 commits into
senny:masterfrom
blshkv:fix-p-inside-li

Conversation

@blshkv

@blshkv blshkv commented May 24, 2026

Copy link
Copy Markdown

Problem

Editors such as Trix wrap list item text in <p> tags, producing <li><p>text</p></li>. Since <li> already maps to a w:p paragraph node, the nested <p> (also w:p) creates invalid OOXML that Word silently drops — the list item content is lost entirely.

Root cause

process_child_nodes in AST::List only promoted nested list tags to sibling level. There was no preprocessing to unwrap <p> elements directly inside <li> before AST conversion, so the invalid nesting reached the OOXML output unchanged.

Fix

Unwrap <p> elements that are direct children of <li> in process_child_nodes, replacing each <p> with its own children before the AST is built.

Change: 8 lines in lib/sablon/html/ast.rb + 1 regression test in test/html/ast_test.rb.

blshkv added 4 commits May 24, 2026 09:01
When a list of one type was nested inside a list item of a different
type (e.g. <ul> inside <ol><li>, or <ol> inside <ul><li>), the nested
list items were silently dropped from the generated .docx output.

Two bugs caused this:

1. process_child_nodes in AST::List used XPath `./li/#{@list_tag}`,
   which only promoted nested lists of the same type to sibling level.
   A mixed-type nested list was never promoted, so its items remained
   as children of a <w:p>, producing invalid OOXML that Word drops.
   Fixed by changing the XPath to `./li/ul | ./li/ol`.

2. The allowed_children for ol and ul did not include the other list
   type, so after promotion the structure validator raised:
   "ol is not a valid child element of ul" (and vice versa).
   Fixed by adding ul to ol's allowed_children and ol to ul's.

Fixes senny#197
Editors such as Trix wrap list item text in <p> tags, producing
<li><p>text</p></li>. Since <li> already maps to a w:p paragraph
node, nesting <p> (also w:p) inside it creates invalid OOXML that
Word silently drops, losing the list item content.

Fix by unwrapping <p> elements that are direct children of <li> in
process_child_nodes before AST conversion, replacing each <p> with
its own children — the same pre-processing that the mixed nested list
fix already does for promoted list siblings.
Editors such as Trix wrap list item text in <p> tags, producing
<li><p>text</p></li>. Since <li> already maps to a w:p paragraph
node, nesting <p> (also w:p) inside it creates invalid OOXML that
Word silently drops, losing the list item content entirely.

Fix by unwrapping <p> elements that are direct children of <li> in
process_child_nodes before AST conversion, replacing each <p> with
its own children.
@blshkv
blshkv force-pushed the fix-p-inside-li branch from 823bcba to 4faba38 Compare May 24, 2026 01:19
blshkv added a commit to blshkv/blshkv-overlay that referenced this pull request May 24, 2026
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