Conversation
…SD-1331) Text box borders were invisible because: 1. Color extraction only handled a:schemeClr and a:srgbClr but not a:prstClr (preset colors like "black"). DOCX text boxes commonly use preset colors, so extraction fell through returning null. 2. Stroke width w="0" was treated as invisible, but in OOXML it means "hairline" (~0.75pt in Word). Adds getPresetColor() with all ECMA-376 preset colors and refactors into shared extractColorFromSolidFill() helper.
There was a problem hiding this comment.
Pull request overview
This PR improves DOCX DrawingML color and stroke extraction so text box borders render correctly by adding support for preset colors (a:prstClr) and treating w="0" strokes as hairlines rather than invisible.
Changes:
- Add
getPresetColor()mapping for ECMA-376 preset color names and use it during color extraction. - Introduce
extractColorFromSolidFill()helper to centralize color + modifier + alpha parsing across scheme/sRGB/preset colors. - Treat
a:ln w="0"as a minimum hairline width (0.75) and add/extend related unit tests.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/vector-shape-helpers.js |
Adds preset color lookup, consolidates solid fill parsing, and enforces hairline stroke width behavior. |
packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/vector-shape-helpers.test.js |
Adds tests for preset colors, hairline stroke width, and a:prstClr extraction for stroke/fill. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/vector-shape-helpers.js
Show resolved
Hide resolved
packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/vector-shape-helpers.js
Show resolved
Hide resolved
packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/vector-shape-helpers.js
Show resolved
Hide resolved
packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/vector-shape-helpers.js
Show resolved
Hide resolved
…1838) Page-relative anchored drawings (move object with text = OFF) were invisible because the main layout loop only checked preRegisteredPositions for image blocks, not drawing blocks. The drawing block path called layoutDrawingBlock() which returned early for anchored items, resulting in no fragment being created. Adds the same preRegisteredPositions check that exists for image blocks to the drawing block path, creating a DrawingFragment with the pre-computed position.
@tupizz 👀 |
|
@caio-pizzol The comment is wrong.
That's the whole point of the refactor — the duplicated inline color extraction logic in both |
caio-pizzol
left a comment
There was a problem hiding this comment.
Nice work @tupizz!
Solid fixes, left a few comments feel free to merge after addressing the relevant ones
packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/vector-shape-helpers.js
Outdated
Show resolved
Hide resolved
packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/vector-shape-helpers.js
Outdated
Show resolved
Hide resolved
packages/super-editor/src/core/super-converter/v3/handlers/wp/helpers/vector-shape-helpers.js
Outdated
Show resolved
Hide resolved
- Rename extractColorFromSolidFill → extractColorFromElement (it also handles lnRef/fillRef, not just solidFill) - Extract applyModifiersAndAlpha() helper to deduplicate modifier logic across schemeClr, srgbClr, and prstClr branches - Apply shade/tint/lumMod/lumOff modifiers to srgbClr (previously only alpha was handled, inconsistent with the other two color types)
Visual diffs detectedPixel differences were found in visual tests. This is not blocking — reproduce locally with |
…ement and clipPath invalidation
|
🎉 This PR is included in superdoc v1.15.0-next.2 The release is available on GitHub release |
# [1.15.0](v1.14.0...v1.15.0) (2026-02-20) ### Bug Fixes * **ai-actions:** preserve html/markdown insertion and prevent repeated formatted replacement ([#2117](#2117)) ([9f685e9](9f685e9)) * **ai:** support headless mode in EditorAdapter.applyPatch ([#1859](#1859)) ([cf9275d](cf9275d)) * **collaboration:** memory leaks, Vue stack overflow, and Liveblocks stability (SD-1924) ([#2030](#2030)) ([a6827fd](a6827fd)), closes [#prepareDocumentForExport](https://github.com/superdoc-dev/superdoc/issues/prepareDocumentForExport) * **collab:** prevent stale view when remote Y.js changes bypass sdBlockRev increment ([#2099](#2099)) ([0895a93](0895a93)) * **converter:** handle null list lvlText and always clear numbering cache ([#2113](#2113)) ([336958c](336958c)) * **document-api:** remove search match cap and validate moveComment bounds ([6d3de67](6d3de67)) * export docx blobs with docx mime type ([#1849](#1849)) ([1bc466d](1bc466d)) * **export:** prevent DOCX corruption from entity encoding and orphaned delInstrText (SD-1943) ([#2102](#2102)) ([56e917f](56e917f)), closes [#replaceSpecialCharacters](https://github.com/superdoc-dev/superdoc/issues/replaceSpecialCharacters) [#1988](#1988) * **layout-bridge:** correct cell selection for tables with rowspan ([#1839](#1839)) ([0b782be](0b782be)) * **layout,converter:** text box rendering and page-relative anchor positioning (SD-1331, SD-1838) ([#2034](#2034)) ([3947f39](3947f39)) * **layout:** route list text-start calculations through resolveListTextStartPx ([02b14b8](02b14b8)) * **painter-dom:** use absolute page Y for page-relative anchors in header/footer decorations ([0b9bc72](0b9bc72)) * preserve selection highlight when opening toolbar dropdowns ([#2097](#2097)) ([a33568e](a33568e)) * structured content renders correct on hover and select ([#1843](#1843)) ([dab3f04](dab3f04)) * **super-editor:** add unsupported-content reporting across HTML/Markdown import paths ([#2115](#2115)) ([84880b7](84880b7)) * **super-editor:** handle partial comment file-sets and clean up stale parts on export ([#2123](#2123)) ([f63ae0a](f63ae0a)) * **super-editor:** restore <hr> contentBlock parsing and harden VML HR export fallback ([#2118](#2118)) ([da51b1f](da51b1f)) * table headers are incorrectly imported from html ([#2112](#2112)) ([e8d1480](e8d1480)) * table resizing regression ([#2091](#2091)) ([20ed24e](20ed24e)) * table resizing regression ([#2091](#2091)) ([9a07f1c](9a07f1c)) * **tables:** align tableHeader attrs with tableCell to fix oversized DOCX export widths ([#2114](#2114)) ([38f0430](38f0430)) * **tables:** fix autofit column scaling, cell width overflow, and page break splitting ([#1987](#1987)) ([61a3f6f](61a3f6f)) * **tables:** prevent tblInd double-shrink when using tblGrid widths (SD-1494) ([8750ece](8750ece)) * track changes comment text for formatting changes ([#2013](#2013)) ([b2a43ff](b2a43ff)) * wire DocumentApi to Editor.doc with lifecycle-safe caching ([57326ea](57326ea)) ### Features * cropped images ([#1940](#1940)) ([3767a49](3767a49)) * extend document-api with format, examples, create.heading ([#2092](#2092)) ([fdf8c7c](fdf8c7c)) * **lists:** support hidden list indicators via w:vanish ([#2069](#2069)) ([#2080](#2080)) ([0bed0fd](0bed0fd)) * the document API limited alpha ([#2087](#2087)) ([091c24c](091c24c))
|
🎉 This PR is included in superdoc v1.15.0 The release is available on GitHub release |
Summary & Demo
Fixes two independent bugs that prevented text boxes from rendering correctly:
1. Invisible text box borders — SD-1331
a:prstClrsupport:extractStrokeColor()andextractFillColor()only handleda:schemeClr(theme colors) anda:srgbClr(hex RGB). DOCX text boxes commonly usea:prstClr(preset colors likeblack,white,red), which fell through to the style reference fallback returningnull— no border rendered.w="0"means "hairline" (thinnest visible stroke, ~0.75pt in Word), not zero/invisible.extractStrokeWidth()was returning0, producing an invisible SVG stroke.Changes:
getPresetColor()— new lookup function with all 140+ ECMA-376 preset color namesextractColorFromSolidFill()— shared helper consolidating color + modifier extraction for all three color types (a:schemeClr,a:srgbClr,a:prstClr), eliminating duplicated logic across stroke/fill functionsextractStrokeWidth()returns0.75forw="0"instead of02. Page-relative anchored drawings invisible — SD-1838
Text boxes with "Move object with text" unchecked in Word (
relativeFrom="page") were completely invisible. These page-relative anchored drawings are collected bycollectPreRegisteredAnchors()and their positions pre-computed, but the main layout loop only checkedpreRegisteredPositionsforimageblocks —drawingblocks fell through tolayoutDrawingBlock()which returned early for anchored items, creating no fragment.Changes:
preRegisteredPositionscheck fordrawingblocks in the main layout loop, mirroring the existingimageblock patternDrawingFragmentwith the pre-computed position when a pre-registered anchor is foundTest plan
getPresetColor(), hairline stroke width, and preset color extraction in both stroke and fill pathswrapNoneCloses SD-1331
Closes SD-1838