Skip to content

refactor(painters/dom): unify image block rendering (SD-2838)#3328

Open
luccas-harbour wants to merge 14 commits into
luccas/sd-2838-unify-sdt-renderingfrom
luccas/sd-2838-unify-image-block-rendering
Open

refactor(painters/dom): unify image block rendering (SD-2838)#3328
luccas-harbour wants to merge 14 commits into
luccas/sd-2838-unify-sdt-renderingfrom
luccas/sd-2838-unify-image-block-rendering

Conversation

@luccas-harbour
Copy link
Copy Markdown
Contributor

Summary

  • Extracts image <img> creation, clip-path resolution, and hyperlink-anchor wrapping into shared helpers under painters/dom/src/images/, and routes the renderer's block/drawing image paths plus renderTableCell's flowing, drawing, and anchored image paths through them — eliminating five near-identical copies of the same setup (objectFit, cover→left-top, clip-path, filters, hyperlink wrap).
  • Co-locates the remaining image utilities (image-clip-path, image-selectors) under images/ alongside the new modules and shares the inline-style applier + clip-path reader.
  • Repairs version-signature gaps so visual edits actually invalidate: inline image runs (including inside tables), table images, and image hyperlinks now contribute their full visual state to deriveBlockVersion, and raw inline clip paths are hashed rather than dropped.
  • Removes the now-dead deriveBlockVersion-on-render machinery (paragraph/image/drawing/table version hashing, SDT version helpers, list-marker guards) from renderer.ts since image-block rendering no longer derives its own per-block versions.
  • Preserves the srcRect-vs-geometry transform invariant with an AIDEV-NOTE (clip-path scaling stays on the <img>; rotation/flip stays on the fragment wrapper) so future edits don't collapse them onto the same element.

Changes by area

painters/dom/src/images/ (new)

  • image-block.tscreateBlockImageContent (single source of truth for sizing, objectFit, clip-path, filters, hyperlink wrap) + resolveBlockImageClipPath.
  • image-fragment.tsrenderImageFragment + buildImageGeometryTransform / applyImageGeometryTransform, lifted out of renderer.ts.
  • drawing-image.tscreateDrawingImageElement, createShapeGroupImageElement, createShapeTextImageElement.
  • hyperlink.ts — shared buildImageHyperlinkAnchor (sanitized href, target/rel, tooltip, role/tabindex, block vs inline-block display).
  • types.ts — shared BuildImageHyperlinkAnchor anchor type.
  • image-clip-path.ts, image-selectors.ts — moved from utils/.

painters/dom/src/renderer.ts

  • Block image, drawing image, shape-group image, and shape-text image creation delegated to the new modules; renderImageFragment is now a thin call into renderImageFragmentElement.
  • Drops the no-longer-used deriveBlockVersion, paragraph/cell-border hashing, SDT version helpers, list-marker guards, applyImageClipPath, and buildImageFilters imports (~530 lines net reduction in this file).

painters/dom/src/table/renderTableCell.ts

  • Flowing image, table-cell drawing image, and anchored image paths all go through createBlockImageContent with a per-cell buildImageHyperlinkAnchor bound to the cell's document.
  • Forces flowing/table images to display: block regardless of block.display (matches prior renderer behavior).

layout-resolved/src/versionSignature.ts

  • New renderedBlockImageVersion / renderedInlineImageRunVersion capturing src/dims/alt/title/objectFit/display/filters/lum/rotation/flip/hyperlink/clip-path.
  • Image blocks, drawing-image blocks, and inline image runs now hash the full rendered version; raw clipPath on inline image runs is hashed instead of dropped; table cell signatures recurse into nested blocks via deriveBlockVersion.

Tests

  • images/image-block.test.tsresolveBlockImageClipPath precedence and unsupported-value handling; drawing image filters and hyperlink wrapping.
  • table/renderTableCell.test.ts — flowing-image block display, clip-path container overflow: hidden, filters, and hyperlink anchors on both flowing and anchored images.
  • layout-resolved/versionSignature.test.ts — coverage for the new image hashing paths.

Why

Five copies of the img-setup logic had already drifted (e.g., objectPosition: left top for cover was missing from some paths, hyperlinks weren't wrapped in table cells, clip-path container overflow: hidden wasn't always set). Centralizing prevents future drift and lets inline visual edits (hyperlink, luminance, gain/blacklevel, rotation, flip) invalidate caches reliably so re-renders pick them up.

Extract image <img> element creation, clip-path resolution, and
hyperlink-anchor wrapping into shared helpers under `painters/dom/src/images/`,
and route the renderer's block/drawing image paths plus renderTableCell's
flowing, drawing, and anchored image paths through them. Eliminates five
near-identical copies of the same img setup (objectFit, cover→left-top,
clip-path, filters, hyperlink wrap) so behavior stays consistent across all
image surfaces. Adds coverage for clip-path, filters, and hyperlinks on both
flowing and anchored images inside table cells (SD-2838).
Removes the now-dead deriveBlockVersion machinery from renderer.ts
(paragraph/image/drawing/table version hashing, SDT metadata helpers,
list-marker guards) along with renderedBlockImageVersion in
image-block.ts. No remaining call sites consume these helpers after
the image-block rendering unification.
Move image fragment and drawing image creation out of renderer.ts into
dedicated modules under images/. Renderer now delegates:

- renderImageFragment → images/image-fragment.ts (with the
  buildImageGeometryTransform / applyImageGeometryTransform helpers it
  owned)
- createDrawingImageElement, createShapeGroupImageElement, and the
  inline shape-text image element creation → images/drawing-image.ts

No behavior change — pure extraction. Trims ~157 lines from renderer.ts.
Move image-clip-path and image-selectors (plus their tests) from
utils/ into the images/ directory alongside image-block, drawing-image,
hyperlink, and image-fragment. Update import paths in callers. No
behavior change.
@luccas-harbour luccas-harbour requested a review from a team as a code owner May 15, 2026 20:46
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 15, 2026

SD-2838

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.

1 participant