Skip to content

fix(direction): only honor inline w:bidiVisual for table visual direction (SD-3171)#3354

Merged
caio-pizzol merged 2 commits into
mainfrom
caio-pizzol/SD-3171-fix-style-cascade-bidivisual
May 17, 2026
Merged

fix(direction): only honor inline w:bidiVisual for table visual direction (SD-3171)#3354
caio-pizzol merged 2 commits into
mainfrom
caio-pizzol/SD-3171-fix-style-cascade-bidivisual

Conversation

@caio-pizzol
Copy link
Copy Markdown
Contributor

Word-parity bug exposed by SD-3138 Phase 1B (#3285). The Phase 1B cascade code layered style-resolved `rightToLeft`/`bidiVisual` into `TableDirectionContext` when no inline value was present. That matches how most cascading properties work, but Word's actual renderer behaves differently for `w:bidiVisual` specifically: it does NOT visually flip cells when the only source is a style. The flip only fires when `w:bidiVisual` is on the table inline.

Empirical verification

Fixture Word's Document.Tables(1).TableDirection Word visual order SuperDoc (before this PR) SuperDoc (after)
Style-cascade bidiVisual only 1 (wdTableDirectionLtr) A B C C B A (wrong) A B C ✓
Inline bidiVisual on w:tbl/w:tblPr 0 (wdTableDirectionRtl) C B A C B A ✓ C B A ✓

Fix

`packages/layout-engine/pm-adapter/src/converters/table.ts`: drop the style fallback when computing `tableDirectionContext.visualDirection`. Style-cascade resolution stays for all other table properties (borders, cell margins, etc.); only the visual cell-flip signal becomes inline-only. Explicit inline `false` continues to honor `??` semantics so `<w:bidiVisual w:val="0"/>` still produces `'ltr'`.

History

PR #3350 (Wave 3 coverage fixture) originally asserted the style-cascade fixture renders C B A — pinning SuperDoc's pre-fix behavior as a test. This PR updates that assertion to A B C (Word parity) and adds an inline-bidiVisual positive control (C B A) so a future regression on either path fails loudly.

Tests

  • pm-adapter `table.test.ts`: SD-3138 Phase 1B describe block updated. "style cascade rightToLeft=true" assertion flips from `'rtl'` to `undefined` (Word-parity). Inline-true, inline-false-overrides, and alias tests still pass. All 63 table.test.ts tests green.
  • Behavior `tests/behavior/tests/tables/rtl-style-derived-bidivisual.spec.ts`: assertion flipped from `['C', 'B', 'A']` to `['A', 'B', 'C']`.
  • Behavior `tests/behavior/tests/tables/rtl-inline-bidivisual.spec.ts` (new): positive control asserts inline `bidiVisual` still flips cells (`['C', 'B', 'A']`).
  • Both behavior specs pass on chromium, firefox, webkit.
  • Targeted package tests: contracts 229, pm-adapter 1838+, layout-bridge 1210, painter-dom 1093. Build sweep clean.

Follow-up

Will upload both fixtures to the R2 corpus as broad layout-compare regression coverage after this lands.

Closes SD-3171.

…tion (SD-3171)

Word-parity bug exposed by SD-3138 Phase 1B. The Phase 1B cascade code
layered style-resolved rightToLeft/bidiVisual into TableDirectionContext
when no inline value was present. That matches how most cascading
properties work, but Word's actual renderer behaves differently for
w:bidiVisual specifically: it does not visually flip cells when the only
source is a style. The flip only fires when w:bidiVisual is on the table
inline.

Empirical verification:
- Style-cascade fixture (bidiVisual in w:style/w:tblPr only):
  Document.Tables(1).TableDirection = 1 (wdTableDirectionLtr), cells
  render A B C in logical order.
- Inline fixture (bidiVisual in w:tbl/w:tblPr): TableDirection = 0
  (wdTableDirectionRtl), cells render C B A flipped.

Fix: drop the style fallback when computing tableDirectionContext.
visualDirection. Style-cascade resolution stays for all other table
properties (borders, cell margins, etc.); only the visual flip signal
becomes inline-only. Explicit inline `false` continues to honor `??`
semantics so an inline bidiVisual w:val="0" still produces 'ltr'.

Tests:
- pm-adapter table.test.ts: "style cascade rightToLeft=true" assertion
  flipped from 'rtl' to undefined (Word-parity contract). Inline-only
  tests and the explicit-false alias test still pass.
- All 63 table.test.ts tests green; layout-bridge / painter-dom / contracts
  unchanged.

Behavior tests updated in a follow-up commit so the rtl-style-derived-
bidivisual.spec.ts assertion matches the corrected contract.

Closes part of SD-3171.
…e cascade (SD-3171)

Update the rtl-style-derived-bidivisual.spec.ts assertion from C B A to
A B C - the Word-parity contract that the pm-adapter fix in the previous
commit installs. The original assertion in PR #3350 pinned SuperDoc's
pre-fix behavior, not Word's.

Add rtl-inline-bidivisual.spec.ts as the positive control: a fixture
where w:bidiVisual is set INLINE on the table's tblPr. Word's renderer
visually flips cells here (TableDirection=wdTableDirectionRtl,
cells render C B A). SuperDoc must match. Both fixtures load a 1x3
table with logical cells A B C.

The pair proves the fix is direction-specific:
- style-cascade source -> no visual flip (Word-parity, both render A B C)
- inline source -> visual flip (Word-parity, both render C B A)

Both specs pass on chromium, firefox, webkit.

Inline fixture includes the default TableNormal style so the super-
converter can anchor its style cascade; the bare custom style version
without TableNormal triggered a docxImporter throw.
@caio-pizzol caio-pizzol requested a review from a team as a code owner May 17, 2026 09:47
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 17, 2026

SD-3171

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@caio-pizzol caio-pizzol merged commit 004eac5 into main May 17, 2026
70 checks passed
@caio-pizzol caio-pizzol deleted the caio-pizzol/SD-3171-fix-style-cascade-bidivisual branch May 17, 2026 10:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants