Skip to content

fix(super-converter): fix table-cell shading export β€” strip # prefix and emit val="clear" (SD-3142)#3312

Open
nazlo90 wants to merge 1 commit into
superdoc-dev:mainfrom
nazlo90:nazlo90/SD-3142-fix-table-cell-shading-export
Open

fix(super-converter): fix table-cell shading export β€” strip # prefix and emit val="clear" (SD-3142)#3312
nazlo90 wants to merge 1 commit into
superdoc-dev:mainfrom
nazlo90:nazlo90/SD-3142-fix-table-cell-shading-export

Conversation

@nazlo90
Copy link
Copy Markdown

@nazlo90 nazlo90 commented May 14, 2026

Partial fix for SD-3142. Addresses the export half of the bug β€” the import half is not fixed in this PR (details below).

Root cause

ECMA-376 Β§17.4.32 requires w:fill to be a bare 6-char uppercase hex string and, for solid fills, w:val="clear". SuperDoc was writing the color from the internal ProseMirror attr as-is, which could include a leading # (e.g. #A1B2C3), and was omitting w:val entirely. LibreOffice treats a missing w:val as nil (transparent) and ignores the fill value, rendering those cells black regardless of color.

What changed

translate-table-cell.js β€” the export path for <w:shd>:

  • Runs normalizeHexColor to strip the # prefix and uppercase the value before writing w:fill.
  • Adds val: 'clear' to every solid-fill shading element.
  • Guards against non-hex values (e.g. "auto") via isValidHexColor: these now produce no <w:shd> rather than invalid markup.

helpers.js (resolveShadingFillColor) β€” used on the import/display path:

  • Adds an isValidHexColor guard so w:fill="auto" (Word's sentinel for "no fill") returns null instead of the string "AUTO", preventing it from being treated as a color downstream.

Tests

11 new assertions in helpers.test.js and translate-table-cell.test.js. Also corrected an existing wrong assertion that expected w:fill as '#FF00FF'; OOXML requires 'FF00FF'. All 12 827 existing tests pass.

pnpm --filter @superdoc/super-editor exec vitest run \
  src/editors/v1/core/super-converter/helpers.test.js \
  src/editors/v1/core/super-converter/v3/handlers/w/tc/helpers/translate-table-cell.test.js

What is NOT fixed

The import side of SD-3142: cells whose background comes from a table style's conditional formatting (e.g. tblStylePr with type="firstRow") currently render as white in SuperDoc's layout engine. The style cascade in style-engine resolves the conditional-format shading, but that value isn't threaded through to the painted cell yet β€” it requires changes in style-engine and pm-adapter and is a separate, larger task.

Related: SD-3142.

…and emit val="clear" (SD-3142)

OOXML requires w:fill to be a bare 6-char hex string and w:val="clear" for solid fills.
The exporter was emitting the color as-is (including a leading #), and omitting w:val
entirely β€” both invalid per ECMA-376 Β§17.4.32. LibreOffice interprets a missing val as
"nil" and renders the cell black regardless of the fill value.

Two changes in the export path:

- `translate-table-cell.js`: strips the # prefix via normalizeHexColor before writing
  w:fill, adds val:"clear" to the shading object, and guards against non-hex values
  (e.g. "auto") so they don't produce invalid markup.
- `helpers.js` (resolveShadingFillColor): adds an isValidHexColor guard so that
  w:fill="auto" β€” a sentinel that Word uses to mean "no fill" β€” returns null instead of
  the string "AUTO", preventing it from being surfaced as a color downstream.

11 new tests across helpers.test.js and translate-table-cell.test.js; corrected an
existing wrong assertion (w:fill was expected as '#FF00FF'; OOXML requires 'FF00FF').
All 12827 existing tests continue to pass.

Not fixed in this PR: the import side of SD-3142 β€” cells with a table-style-inherited
background currently render as white in SuperDoc's layout engine because the style cascade
resolution (style-engine) doesn't yet propagate the conditional-format shading fill through
to the painted cell. That path requires changes in style-engine and pm-adapter and is left
for a follow-up.
@nazlo90 nazlo90 requested a review from a team as a code owner May 14, 2026 21:43
@caio-pizzol caio-pizzol self-assigned this May 15, 2026
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