-
Notifications
You must be signed in to change notification settings - Fork 63
fix: support cell spacing #1879
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 489b04e27c
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
packages/super-editor/src/core/super-converter/v3/handlers/w/tbl/tbl-translator.js
Outdated
Show resolved
Hide resolved
|
Based on my review of the code and understanding of OOXML specifications, I can now provide a comprehensive review. Let me analyze the key changes: Status: PASS I've reviewed this PR for OOXML spec compliance, focusing on the SummaryThe changes correctly implement table cell spacing according to ECMA-376 specifications. The implementation properly handles the Key Changes Reviewed1. tbl-translator.js:90 - Cell spacing conversion['tableCellSpacing', ({ value, type }) => ({ value: twipsToPixels(value), type })]✅ Correct: The spec defines 2. tbl-translator.test.js:154 - Test expectation updateexpect(result.attrs.tableCellSpacing).toEqual({ value: 0.5, type: 'dxa' });✅ Correct: With input UPDATE: Looking at the diff, the original test returned 3. legacy-handle-table-cell-node.js:58,308 - Border spacing logichasBorderSpacing: !!tableProperties?.tableCellSpacing✅ Correct: According to ECMA-376, when 4. contracts/index.ts - Type definition updatecellSpacing?: CellSpacing;
// where CellSpacing = { type: string; value: number; }✅ Correct: Properly represents OOXML measurement with both value and type (e.g., OOXML Spec ComplianceThe implementation correctly follows ECMA-376 Part 1 §17.4.19 (
For detailed spec information, see: https://ooxml.dev/spec?q=tblCellSpacing No Issues FoundAll attributes, elements, and default values align with the ECMA-376 specification. The conversion logic properly handles the measurement type pattern used consistently across other table properties. |
caio-pizzol
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice work @VladaHarbour!
just a few nit pick comments
| * Resolves table cell spacing to pixels from block attrs (painter fallback when measure has no cellSpacingPx). | ||
| * Editor/store often has value already in px; raw OOXML has twips (dxa). Only convert when value looks like twips. | ||
| */ | ||
| function resolveCellSpacingPx(cellSpacing: CellSpacing | number | null | undefined): number { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe extract to a shared utility to avoid drift?
getCellSpacingPx and resolveCellSpacingPx have identical logic
|
|
||
| // Add body row heights (fromRow to toRow, exclusive) | ||
| const bodyRowCount = fragment.toRow - fragment.fromRow; | ||
| height += sumRowHeights(measure.rows, fragment.fromRow, fragment.toRow); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we add tests for layout-engine coordinate calculations with cell spacing? the logic in calculateFragmentHeight and generateColumnBoundaries is untested
| container.classList.add('superdoc-table-fragment'); | ||
|
|
||
| // Cell spacing in px (border-spacing). Use measure when present, else resolve from block attrs (e.g. stale/cached measure). | ||
| const cellSpacingPx = measure.cellSpacingPx ?? resolveCellSpacingPx(block.attrs?.cellSpacing) ?? 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: trailing ?? 0 is redundant since resolveCellSpacingPx already returns 0 for null/undefined
| }; | ||
|
|
||
| export type CellSpacing = { | ||
| type: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we make this more specific? something like type: 'dxa' | 'px' would help catch the twips/px confusion
| 'tableLayout', | ||
| ['tableIndent', ({ value, type }) => ({ width: twipsToPixels(value), type })], | ||
| ['tableCellSpacing', ({ value, type }) => ({ w: String(value), type })], | ||
| ['tableCellSpacing', ({ value, type }) => ({ value: twipsToPixels(value), type })], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
editor uses tableCellSpacing, layout uses cellSpacing - any reason for the different names?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no particular reason. Nick defined it as cellSpacing in layout engine and I just reuse the existing variable
| borders: { | ||
| default: {}, | ||
| renderDOM({ borders, borderCollapse, tableCellSpacing }) { | ||
| if (!borders && borderCollapse !== 'separate' && !tableCellSpacing) return {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
borders defaults to {} which is truthy, so !borders is always false.
this still works but the intent is unclear - maybe Object.keys(borders).length === 0 instead?
| tableCellSpacing: { | ||
| default: null, | ||
| rendered: false, | ||
| renderDOM({ tableCellSpacing }) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
border-spacing only works when border-collapse: separate is set.
if tableCellSpacing exists but borderCollapse isn't explicitly set, will the spacing render correctly in the editor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We always set borderCollapse as 'separate' in importer when tableCellSpacing is defined for the document. There is no something like borderCollapse in xml
| type ApplyStylesFn = (el: HTMLElement, styles: Partial<CSSStyleDeclaration>) => void; | ||
|
|
||
| /** 15 twips per pixel (96 dpi). Used when resolving raw dxa values in painter fallback. */ | ||
| const TWIPS_PER_PX = 15; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this constant is defined in a few places (measuring/dom, here, pm-adapter).
might be worth exporting from @superdoc/common/layout-constants
Adds cell spacing support