feat(ooxml): pptx slide size + tables, xlsx merged cells + value types, docx table merges#607
Merged
Merged
Conversation
…s, docx table merges pptx: - read the real slide size from p:presentation/p:sldSz (ECMA-376 default 10in x 7.5in when absent) instead of a hardcoded 11.02in x 8.27in; slide names from p:cSld@name - parse tables: a:tbl sits inside p:graphicFrame/a:graphic/a:graphicData, which the parser never descended into; wire create_table_element + append_column (a:tblGrid/a:gridCol), rows/cells, spans from gridSpan/rowSpan, covered cells from hMerge/vMerge, column widths and row heights, and p:xfrm positioning for graphic frames xlsx: - merged cells: parse mergeCells into anchor span + covered flags on the SheetCell side map; ranges whose anchor cell is absent from sheetData are dropped to keep the renderer's cursor consistent - cell value types: derive number-vs-string from c/@t so numeric cells get the odr-value-type-float class docx: - replace dead ODF-name code in the table adapter: dimensions from w:tblGrid/w:gridCol + w:tr, colspan from w:gridSpan, vMerge continuations report covered and restart cells compute their rowspan by walking following rows at the same grid column - bookmark_name reads w:name instead of ODF's text:name TableCursor: fix a latent infinite loop exposed by xlsx merges — the per-row pending covered ranges were appended unsorted, so handle_rowspan_ missed them when a long-rowspan cell was followed by later rowspan anchors at smaller columns and the sheet renderer never advanced (hung on ruski.xlsx). Insert sorted, skip tolerantly, advance the cursor on the (normally unreachable) covered-cell branch, and add a regression test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KH4XvPFfdUvH7HMp8rmqZT
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f0599f62f1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Table cell text sits under a:tc/a:txBody/a:p, but only p:txBody was registered in the tag dispatch table, so cell text was dropped. Addresses review feedback on #607. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AEvWWwe1EyeWH7ANHoAvPH
andiwand
enabled auto-merge (squash)
July 16, 2026 21:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Generated with Claude Code
A batch of low-hanging fruits from the ooxml module
AGENTS.mdopen-work lists, plus one latent shared-code bug they exposed.pptx
slide_page_layoutreadsp:presentation/p:sldSz(EMUs, resolved once in theDocumentctor; ECMA-376 default 10in × 7.5in when absent) instead of a hardcoded 11.02in × 8.27in. Slide names come fromp:cSld@name.a:tblsits insidep:graphicFrame/a:graphic/a:graphicData, which the parser never descended into — tables were silently absent from the element tree. Now:p:graphicFrame→frame (withp:xfrmpositioning),a:tblwired throughcreate_table_element/append_column(a:tblGrid/a:gridCol), rows/cells froma:tr/a:tc, spans fromgridSpan/rowSpan, covered cells fromhMerge/vMerge, column widths and row heights fromw/hEMUs. The dead ODF-nametable_dimensionscopy-paste is gone.xlsx
mergeCellsis parsed per sheet into anchorspan+is_coveredflags on theSheetCellside map;sheet_cell_span/sheet_cell_is_coveredreport them and merged ranges render ascolspan/rowspan. Ranges whose anchor cell is absent fromsheetDataare dropped to keep the renderer's cursor bookkeeping consistent.sheet_cell_value_typederives number-vs-string fromc/@t(default "n" →float_numberwhen<v>exists), so numeric cells get theodr-value-type-floatclass.docx
w:names (the methods previously queried ODF names and were dead code): dimensions fromw:tblGrid/w:gridCol+w:tr; colspan fromw:gridSpan;w:vMergecontinuations report covered, and the restart cell computes its rowspan by walking following rows at the same grid column.bookmark_namereadsw:nameinstead of ODF'stext:name.TableCursor: latent infinite loop (exposed by xlsx merges, affects ODF too)
handle_rowspan_assumes each row's pending covered ranges are sorted by column, butadd_cellappended them. A long-rowspan cell followed in a later row by new rowspan anchors at smaller columns (e.g.F4:F9thenA6:A7— real pattern inruski.xlsx) produced an unsorted list; the skip missed the covered position andtranslate_sheet's covered-cellcontinuenever advanced the cursor → infinite loop. Fixed with sorted insertion + a tolerant skip, aTableCursorregression test, and a defensive one-column advance on the (normally unreachable) covered branch in the renderer.ruski.xlsxwent from hanging forever to 0.13s.Verification
odr_test: correctcolspan/rowspan, covered cells skipped, float classes, bookmark anchors.style-various-1.pptxrenders its slide-8 table with real column widths; the 16:9 deck renders 10in × 5.625in slides.TableCursor.*.