Skip to content

HTML import: table widths, cell colours, spans, borders and layout tables (#1878) - #1893

Merged
yeroo merged 4 commits into
mainfrom
issue-1878-html-import-table-widths-cell-co
Nov 5, 2026
Merged

yeroo merged 4 commits into
mainfrom
issue-1878-html-import-table-widths-cell-co

Conversation

@yeroo

@yeroo yeroo commented Nov 5, 2026 •

Copy link
Copy Markdown
Owner

HTML import tables now look like the page: nested tables stay nested, spans, widths, cell colours, vertical alignment, and the table's border/padding/spacing/alignment attributes come through. Layout tables (the HTML-email shape: nested, border=0) import with no visible borders.

Closes #1878

What changed

  • docxcore/src/import/html_table.rs (new): an HTML table is read as a RawTable (cells with their specs) and laid out when the outermost table ends, so a nested table is laid out top-down in its cell's width (less its stated side margins). colspan/rowspan → gridSpan/vMerge over a browser-style slot grid (a rowspan clipped at its row group; rowspan=0 to its group's end); ragged rows padded; MAX_COLUMNS respected.
  • Widths: width attribute (px, %) and CSS width on table/td/th → tblGrid, tblW (dxa / pct / auto) and every cell's tcW. Unknown columns share what is left; over-full widths widen the grid; percentages scale to 100.
  • Cell shading from the cell's bgcolor / CSS background, else its row's, row group's or table's (background: none|transparent clears a part's own fill).
  • valign / vertical-align on cells, rows and row groups → vAlign (inherited; a cell with none is center, the browser default).
  • border=N → tblBorders (outer N px, inside 1 px); border=0/absent → none. cellpadding → tblCellMar (0 writes four zeros), a cell's CSS padding → tcMar, cellspacing → tblCellSpacing (half the HTML gap, unmeasured against Word), <table align> → jc, <tr align> aligns its cells' text.
  • Builder (import/mod.rs) holds a stack of tables; nesting kept to 8 levels (deeper flattens into the enclosing cell as before). An open empty cell (spacer cells) is kept. RTF's table path is unchanged.
  • CLAUDE.md: "HTML import tables (HTML import: table widths, cell colours, spans, borders and layout tables #1878)".

Tests

  • cargo test -p docxcore: 2266 passed, 0 failed; cargo clippy -p docxcore --all-targets -- -D warnings and cargo fmt --all clean.
  • New: html_table unit tests; html.rs tests for spans, widths, over-full widths, shading fallback, valign, border/cellpadding/cellspacing/align, nesting (incl. past 8 and 300 unclosed), a nested 100% table filling its cell, an unclosed spacer cell, a rowspan ending with its row group, and a DOCX round trip (serialize → load: same grid, spans, vMerge, tcPr/tblPr, nesting).
  • New fixture docxcore/tests/fixtures/html/newsletter-tables.html with a_newsletter_table_layout_keeps_widths_spans_and_shading (html_css.rs), and in the every-prefix test.
  • Updated: an_omitted_cell_or_row_end_is_implied (its nested case now asserts a nested table, not a flattened cell).

Review record

  • Plan agreed in 2 rounds with the implementer (v1 critique: nested widths were resolved before the outer layout; empty open cells were dropped; both fixed in v2).
  • revmux round 1 (4 Claude reviewers, none degraded): 0 Major, 2 Minor — rowspan clipped at the table end rather than its row group (fixed, bc51f21), a stale doc comment (fixed). None disputed or deferred.
  • review stopped: round 1 had no Major; all findings fixed

Out of scope (follow-ups filed in #1894): CSS borders on tables/cells, row heights / col widths / max-width, <center>/margin:0 auto table centring, th default bold, page/body background.

🤖 Generated with Claude Code

yeroo and others added 4 commits November 5, 2026 06:37
…lls (#1878)

An HTML table is now read into a RawTable (its cells' blocks and specs) and
laid out when the outermost table ends (import/html_table.rs): colspan and
rowspan as gridSpan and vMerge over a slot grid, column widths from the
table's and cells' width, cell shading, vAlign and tcMar, and the table's
border, cellpadding, cellspacing and align as tblPr. A nested table waits in
its cell at a placeholder and is laid out in that cell's width, so a 100%
table inside a column fills the column, not the outer table.

The Builder holds a stack of tables; RTF keeps its one table and today's
even grid. A begun HTML cell is ended by its row's or table's end even when
it is empty, so an unclosed spacer cell keeps its width and shading.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ting (#1878)

Updates an_omitted_cell_or_row_end_is_implied: its nested case now keeps
the inner table as a table in the outer cell instead of flattening it,
which is the point of #1878; the outer cell's own text is pinned exactly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ented (#1878)

newsletter-tables.html is the HTML-email shape: a 100% wrapper, a centred
600px borderless container, a colspan header, 200/400 columns, a nested card
with class backgrounds, a rowspan cell and a bordered data table.
a_newsletter_table_layout_keeps_widths_spans_and_shading pins its widths,
spans, shading, vAlign, nesting and borders; the fixture joins the
every-prefix test. CLAUDE.md gains an HTML import tables section; the import
bounds table lists the attributes read and the table stack and layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A browser's table model clips a rowspan (and rowspan=0) at the end of its
row group, so a thead cell's rowspan=2 never reaches the body. RawTable now
records where row groups start (a thead/tbody/tfoot open or close; a bare
tr after a closed group is a group of its own) and place() clips at the
cell's group. Also rewords the stale presentational() doc comment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 98.62903% with 17 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
docxcore/src/import/html_table.rs 98.66% 8 Missing ⚠️
docxcore/src/import/html.rs 98.85% 6 Missing ⚠️
docxcore/src/import/mod.rs 97.39% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

@yeroo
yeroo merged commit 1083e19 into main Nov 5, 2026
14 checks passed
@yeroo
yeroo deleted the issue-1878-html-import-table-widths-cell-co branch November 5, 2026 03:41
@yeroo

yeroo commented Nov 5, 2026

Copy link
Copy Markdown
Owner Author

Merged automatically (auto-merge is on for this checkout): review stopped: round 1 had no Major; all findings fixed; merge rounds: none; whole suite green on bc51f21 (11840 tests: cargo test --workspace + suite lib/bins; html-export built by CI, the wasm target is not on this machine); CI 14/14 green; merge-check ok.

Follow-ups (plan out of scope, all Minor): #1894 — CSS borders on tables and cells; row heights / col widths / max-width; table centring under center / div align / margin:0 auto; th default bold/centre and page/image backgrounds. No review finding was deferred or disputed.

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.

HTML import: table widths, cell colours, spans, borders and layout tables

2 participants