Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,37 @@ describe('Non-collapse rule 2: table w:bidiVisual MUST NOT make cell paragraphs
const paragraphContext = resolveParagraphDirection({}, sectionContext, cellContext);
expect(paragraphContext.inlineDirection).toBeUndefined();
});

// SD-3141: explicit `w:bidiVisual w:val="0"` is a real signal per §17.4.1 +
// §17.17.4 and can override a style-cascade `true`. The resolver must
// distinguish "no signal" (undefined) from "explicit false" (ltr), mirroring
// the paragraph resolver's handling of `w:bidi w:val="0"`.

it('table with explicit rightToLeft:false → visualDirection is ltr', () => {
const sectionContext = resolveSectionDirection(undefined);
const tableContext = resolveTableDirection({ rightToLeft: false }, sectionContext);
expect(tableContext.visualDirection).toBe('ltr');
});

it('table with explicit bidiVisual:false → visualDirection is ltr', () => {
const sectionContext = resolveSectionDirection(undefined);
const tableContext = resolveTableDirection({ bidiVisual: false }, sectionContext);
expect(tableContext.visualDirection).toBe('ltr');
});

it('table with no signal → visualDirection stays undefined', () => {
const sectionContext = resolveSectionDirection(undefined);
const tableContext = resolveTableDirection({}, sectionContext);
expect(tableContext.visualDirection).toBeUndefined();
});

it('table with rightToLeft:true wins when both signals present', () => {
// Mixed shape (one true, one false) should NOT happen in practice but
// the rtl branch is checked first to keep this case explicit. SD-3141.
const sectionContext = resolveSectionDirection(undefined);
const tableContext = resolveTableDirection({ rightToLeft: true, bidiVisual: false }, sectionContext);
expect(tableContext.visualDirection).toBe('rtl');
});
});

describe('Non-collapse rule 3: run-level w:rtl MUST NOT bubble up to paragraph', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ export const resolveTableDirection = (
parentSection: SectionDirectionContext,
): TableDirectionContext => {
let visualDirection: BaseDirection | undefined;
// Mirror the paragraph resolver shape (resolveParagraphDirection): explicit
// false is a real signal and must be distinguished from "no signal." Per
// ECMA-376 §17.4.1 + §17.17.4, w:bidiVisual w:val="0" is an explicit-false
// that can override a style-cascade true. SD-3141.
if (tableProperties?.rightToLeft === true || tableProperties?.bidiVisual === true) {
visualDirection = 'rtl';
} else if (tableProperties?.rightToLeft === false || tableProperties?.bidiVisual === false) {
visualDirection = 'ltr';
}
return { visualDirection, parentSection };
};
Loading