Skip to content

feat: cropped images#1940

Merged
harbournick merged 8 commits intomainfrom
sd-584_cropped-images
Feb 17, 2026
Merged

feat: cropped images#1940
harbournick merged 8 commits intomainfrom
sd-584_cropped-images

Conversation

@VladaHarbour
Copy link
Contributor

Added cropped images support. Renders cropped portion of image in Superdoc and preserves it on export.

Screenshot 2026-02-04 at 19 09 02

@linear
Copy link

linear bot commented Feb 4, 2026

@VladaHarbour VladaHarbour self-assigned this Feb 4, 2026
@VladaHarbour
Copy link
Contributor Author

Hi @chittolinag! Since you added some support for stretch and fillRect maybe you could take a look to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Feb 4, 2026

I'll proceed with my review based on my knowledge of the ECMA-376 specification and code analysis:

Status: PASS

This PR implements image cropping using the a:srcRect element from OOXML. After reviewing the code against ECMA-376 compliance, I found the implementation to be spec-compliant.

What was reviewed

The PR adds support for DOCX image cropping by reading a:srcRect attributes and converting them to CSS clip-path: inset() values.

Handler implementation (encode-image-node-helpers.js:75-108)

The buildClipPathFromSrcRect function reads a:srcRect attributes:

  • l, t, r, b - These are the correct ECMA-376 Part 1 §20.1.8.55 attributes for <a:srcRect>
  • Value interpretation: The code divides by 1000 to convert from percentage thousandths (e.g., 84800 = 84.8%)
  • Spec compliance: ✅ ECMA-376 defines these as ST_Percentage (percentage with 1000x multiplier)

Validation logic

The function correctly:

  • Rejects negative values (line 92-94) - these indicate Word extended the image mapping
  • Clamps values to 0-100% range (line 95)
  • Outputs CSS inset(top% right% bottom% left%) format (line 107)

Output format

The generated clipPath attribute stores values like "inset(0% 84.8% 0% 0%)":

  • This is converted to CSS, not written back to DOCX, so format flexibility is acceptable
  • The rendering layer correctly applies this via CSS clip-path

Test coverage

Tests verify:

  • Positive srcRect values → clipPath generated (encode-image-node-helpers.test.js:770-786)
  • Negative srcRect values → no clipPath (788-804)
  • Edge cases: empty, zero, mixed values

Reference

For details on a:srcRect, see https://ooxml.dev/spec?q=srcRect

No spec violations detected. The implementation correctly interprets ECMA-376 Part 1 §20.1.8.55 <a:srcRect> attributes and converts them appropriately for rendering.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a 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: 611b9f621d

ℹ️ 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".

Copy link
Contributor

@caio-pizzol caio-pizzol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @VladaHarbour!

Please let me know if any of the comments make sense. And also, because this involves rendering, I think it would be nice for us to add visual testing for it.

Copy link
Collaborator

@harbournick harbournick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@github-actions
Copy link
Contributor

github-actions bot commented Feb 17, 2026

Visual diffs detected

Pixel differences were found in visual tests. This is not blocking — reproduce locally with cd tests/visual && pnpm docs:download && pnpm test to review diffs.

Copy link
Contributor

@caio-pizzol caio-pizzol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Feel free to merge after addressing comments (if relevant) and adding a visual rendering test for cropped images. Since this changes both DOCX import and layout engine rendering.

@harbournick
Copy link
Collaborator

harbournick commented Feb 17, 2026

Added sd-584 docx to R2 corpus

# Conflicts:
#	packages/layout-engine/painters/dom/src/renderer.ts
@harbournick harbournick enabled auto-merge (squash) February 17, 2026 21:59
@harbournick harbournick merged commit 3767a49 into main Feb 17, 2026
4 checks passed
@harbournick harbournick deleted the sd-584_cropped-images branch February 17, 2026 22:06
@superdoc-bot
Copy link
Contributor

superdoc-bot bot commented Feb 17, 2026

🎉 This PR is included in superdoc v1.15.0-next.3

The release is available on GitHub release

harbournick pushed a commit that referenced this pull request Feb 20, 2026
# [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))
@harbournick
Copy link
Collaborator

🎉 This PR is included in superdoc v1.15.0

The release is available on GitHub release

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.

4 participants