Skip to content

πŸ”„ Sync stable β†’ main#3582

Merged
caio-pizzol merged 9 commits into
mainfrom
sync/stable-to-main-20260529-215717
May 29, 2026
Merged

πŸ”„ Sync stable β†’ main#3582
caio-pizzol merged 9 commits into
mainfrom
sync/stable-to-main-20260529-215717

Conversation

@superdoc-bot
Copy link
Copy Markdown
Contributor

@superdoc-bot superdoc-bot Bot commented May 29, 2026

Summary

Merges latest stable patches into main with a real merge commit so stable release tags remain reachable from main.

This keeps @next prerelease version calculation ahead of the latest published stable release.

Merge requirement

This PR must be merged with GitHub's merge-commit option. Squash or rebase merging will discard stable ancestry and break @next version calculation again.

Conflict handling

Merge status: clean.

Version-only release artifact conflicts are auto-resolved to keep stable's already-published versions. Non-version conflicts fail this workflow instead of committing conflict markers.


Auto-created by sync-patches workflow.

harbournick and others added 9 commits May 29, 2026 13:45
### Bug Fixes

- copy-pasted text in suggestion mode (#3576)
- center virtualized matches after mount in find nav (SD-3315)
- stop find navigation jumping to the reverted caret (SD-3315)
- honor the focus() contract + fix dangling docs reference (SD-3312)
- don't re-center visible matches on find navigation (SD-3315)
- report 'zoom' not 'mixed' for a zoom repaint (SD-3311)
- wire pointer-source tracking on all init paths; update export snapshot
- reset state on unload, dedupe + export payload types, add core tests
- skip empty block SDT content selection
- type modules.contentControls exactly (no pass-through index)
- allow block SDT wrapper deletion to follow lock rules
- promote image-bearing inline SDT wrappers to inline-block
- keep block sdt fill behind content
- hide block sdt fills in output modes
- paint block SDT background on chrome layer
- use logical inset for inline SDT label position
- anchor inline SDT label to start of chrome
- route smartTag through export and preserve smartTagPr in SDT flatten (SD-2647)
- include inline SDT chrome width in block SDT bounds
- keep block SDT chrome at full fragment width
- render and round-trip w:smartTag content (SD-2647)
- decouple base64 image helper imports
- preserve block ids during metadata updates
- ignore covered sdt label clicks
- sync block sdt label selection updates
- show empty SDT placeholder text in viewing and print modes
- skip empty sdt scan on arrow right
- preserve permission-only sdt placeholders
- preserve comment-only sdt placeholders
- preserve empty sdt bookmark placeholders
- collapse hidden sdt placeholder text
- keep sdt placeholder pm range atomic
- trust empty sdt paragraph conversion
- keep vanished sdt paragraph side effects
- preserve vanished block sdt paragraphs
- suppress hidden block sdt chrome
- keep remeasured sdt placeholder atomic
- transform sdt placeholder measure
- remeasure sdt placeholders
- hide sdt placeholders in print
- hide sdt placeholders in viewing
- ignore collapsed inline sdt cut
- expose block sdt appearance
- hide empty block sdt placeholder
- align empty block sdt caret
- use measured width for empty SDT placeholders
- size SDT block labels to content width
- collapse selection on sdtContentLocked delete
- allow history transactions through sdt lock
- drop unreachable move fallback
- target marker-only textblock end
- ignore empty block sdt key targets
- cap block sdt label width
- handle sdt marker gaps and block atoms
- skip hidden field annotations in sdt navigation
- skip hidden metadata sdt markers
- skip hidden block sdt markers
- handle marker-only sdt paragraphs
- keep visible atoms in sdt navigation
- skip hidden sdt navigation markers
- target nearest sdt cursor position
- respect inline atoms in sdt navigation
- handle empty block sdt navigation
- avoid restoring dragged block to its source position
- exclude sdt chrome labels from caret position lookup
- keep text-align enabled in locked SDT paragraphs
- block disabled toolbar execution
- guard unlisted locked toolbar commands
- block locked sdt toolbar execution
- reject malformed base64 image data URIs
- reuse colliding data uri media targets
- enforce upload byte cap for data uris
- avoid non-image data uri extensions
- reject raw raster data uri dimensions
- validate oversized async svg images
- register preset raster data uris in place
- narrow sdt metadata overrides
- normalize image data uri extensions
- centralize image data url policy
- reuse target image relationships
- validate in-place svg payloads
- validate field annotation data uri exports
- reject malformed data uri files
- avoid duplicate image rids
- block raw raster data uri exports
- reject malformed svg data uri payloads
- warn on skipped image exports
- reject separatorless data uri files
- block non-image data uri exports
- read svg data uri dimensions
- share data uri media parsing
- skip invalid data uri image targets
- normalize svg data uri filenames
- validate in-place svg image data
- guard non-base64 data uri exports
- export field annotation svgs as svg
- allow non-base64 SVG data URLs in image rendering
- mirror in-place image media to parent
- decode non-base64 data URI exports
- extract shared hash helpers
- reuse data URI image exports
- support non-base64 data URI images in registration
- scope inline SDT placeholder to structuredContent metadata
- register sized SVG data URI images without canvas processing
- persist data URI images set via setPresetContent
- share SDT lock predicates
- version inline image metadata
- align RTL SDT chrome to text
- size SDT chrome for justified lines
- honor ancestor image SDT locks
- dirty inline image SDT changes
- align SDT chrome within paragraph width
- preserve SDT chrome continuation offsets
- offset block SDT chrome for indents
- suppress SDT pseudo hover in viewing mode
- allow top-aligned inline images
- fit block SDT chrome to actual content width
- bottom-align text on lines with inline images
- keep block SDT chrome and inline images out of paragraph geometry
- disable image resize inside content-locked SDTs
- detect inline image run changes in paragraph diff
- mark block SDT selected when contained image is selected
- select inline SDT content as text on Delete
- intercept beforeinput insertText at inline SDT boundaries
- delete contentLocked SDT wrapper in one step
- bump sdBlockRev on ancestors of inline edits
- select inline SDT content as text on Backspace
- select inline SDT on Backspace at start of following run (SD-3165)
- share structured content chrome label set
- resolve block labels at node boundary
- use contract label selectors
- clear label gesture state on cancel
- scope label clicks to owning editor
- defer label selection to mouseup so native drag still fires
- share structured content label classes
- avoid deferred block label retry
- select labels with active editor
- focus editor after label selection
- correct cursor placement and label interactions for structured content
- handle cell-level SDT in vMerge column lookup (SD-3289)
- preserve cell-level SDT wrapping table cells (SD-3289)
- preserve recipient identity attrs on replay (SD-3279)
- accept legacy fingerprints in compare/apply (SD-3279)
- drop misleading pnpm run type-check hint from audit
- structural-fail on missing dist + sync check-jsdoc header
- strip session-local sdBlockId from diff fingerprint (SD-3279)
- autoFit table width overflow from cell preferences (#3522)
- flip public-method-coverage to strict-zero gate (SD-673)
- flip jsdoc-hygiene-ts to strict-zero gate (SD-673)
- rename jsdoc-hygiene-ts self-tests + wire into CI (fixes vitest discovery on #3511)
- jsdoc-hygiene-ts handles private-identifier symbols + README
- more bugs
- add ui for overlapping delete, other fixes
- replacement pair
- remaining collab bugs
- coalesce tracked inserts across run gaps
- restore tracked change comment interactions
- expose tracked mark predicate option
- more cases
- tc fixes
- collab mode bug
- floating comments fixes
- make jsdoc-hygiene-ts baseline key line-independent + update wrapper docs
- preserve tab underline via runProperties fallback in collab

### Changes

- Merge branch 'main' into caio/sd-3315-find-replace-scroll
- Merge pull request #3509 from superdoc-dev/artem/SD-3232
- Merge pull request #3555 from superdoc-dev/luccas/delete-image-content-locked-sdt
- Merge branch 'main' into artem/SD-3159
- Merge pull request #3550 from superdoc-dev/luccas/sd-3302-bug-sdt-in-template-builder-shows-grey-background-highlight
- Merge branch 'main' into artem/SD-3159
- SD-2676 - fix: table selection not providing a feedback (#3508)
- Merge pull request #3549 from superdoc-dev/luccas/left-align-inline-sdt-label
- Merge pull request #3546 from superdoc-dev/caio/sd-2647-bug-render-and-round-trip-content-wrapped-in-wsmarttag
- Merge remote-tracking branch 'origin/stable' into sync/stable-to-main-20260527-230540
- Merge pull request #3539 from superdoc-dev/caio-pizzol/sd-3289-preserve-cell-level-sdt
- Merge pull request #3527 from superdoc-dev/caio-pizzol/sd-3279-strip-sdblockid-from-diff-fingerprint
- Merge branch 'main' into caio-pizzol/SD-js-contract-owner-audit
- Merge pull request #3531 from superdoc-dev/caio-pizzol/SD-docs-snippet-typecheck-2
- Merge pull request #3526 from superdoc-dev/caio-pizzol/SD-runtime-payload-tests
- Merge pull request #3521 from superdoc-dev/caio-pizzol/SD-public-method-coverage-strict-zero
- Merge branch 'stable'
- Merge pull request #3485 from superdoc-dev/artem/SD-3200
- Merge pull request #3517 from superdoc-dev/caio-pizzol/SD-jsdoc-hygiene-zero-flip
- Merge pull request #3513 from superdoc-dev/caio-pizzol/SD-jsdoc-hygiene-cleanup
- Merge branch 'stable'
- Merge pull request #3511 from superdoc-dev/caio-pizzol/SD-jsdoc-hygiene-scanner
- Merge pull request #3435 from superdoc-dev/nick/sd-3220-overlapping-suggestion-contract
- Merge pull request #3429 from superdoc-dev/artem/underlined-tab-collab

### Documentation

- note content controls in entityAt hit types (SD-3313)
- clarify data uri buffer conversion
- document image data uri helpers
- clarify image registration comments
- sync README exit semantics for js contract-owner audit
- clarify wrapper-stages prose + add ts-jsdoc to check:public summary

### Features

- add ui.contentControls.focus to place the caret in a control (SD-3312)
- add ui.viewport.observe geometry-invalidation signal (SD-3311)
- add ui.contentControls.scrollIntoView (SD-3310)
- add activePath (full active stack) to content-control:active-change
- expose public sdt events
- select adjacent block SDT content at textblock boundaries
- inherit run styles in empty block SDT placeholders
- render placeholder text for empty SDTs
- move caret into following block sdt on delete
- move caret into preceding block sdt on backspace
- disable mutation toolbar controls inside content-locked SDTs
- render empty inline SDTs as a visible placeholder
- add modules.contentControls.chrome
- js contract-owner audit, report-only (SD-673)
- add snippet typecheck for editor/superdoc/** + fix stale examples (SD-673)
- add non-hover field color for sdt (#3506)
- comments and tc on small screen (#3446)
- overlapping tracked changes
- add type-bearing JSDoc hygiene gate for .ts source (SD-673)
- add anchored metadata orphan status

### Tests

- resolve handleBase64 source path from package or repo root
- cover locked block SDT Delete selection
- cover nested block SDT boundary selection
- update SDT keymap chain coverage
- cover contentControlsChrome plumbing; clarify chrome-none comment
- assert chrome-none hover suppression and cascade order
- add v2 bridge unit + round-trip behavior coverage (SD-2647)
- assert smartTag child text survives export round-trip (SD-2647)
- cover nested block sdt navigation
- roundtrip mixed image block sdts
- cover image data uri length boundary
- repaint saved sdt images through painter
- cover structured content image edges
- cover inline image diff fields
- cover locked inline SDT beforeinput
- cover inline SDT Cmd+X selection
- cover inline SDT content Delete flow
- clarify inline SDT boundary lock comment
- cover two-step inline SDT Backspace
- cover inline SDT selection meta escape
- use real production payload for list-definitions-change bridge (SD-673)
- tighten list-definitions-change bridge assertion (SD-673)
- pin list-definitions-change bridge and DELETED comments shape (SD-673)
- pin runtime event payload shapes (SD-673)

### Refactoring

- consolidate type imports in dom painter
- share block sdt navigation helpers
- share box model between block and inline sdt labels
- share structured content predicates
- wrap shared tryDecodeDataUriText re-export
- reuse shared data uri export policy
- share image relationship export lookup
- centralize image data uri parsing
- share data uri text decoding
- trim data uri metadata fields
- extract CHECKED_FILES to shared module + drop audit from wrapper
- drop list-item fragment renderer (SD-2851) (#3269)
- drain 85 type-bearing JSDoc entries from .ts source (SD-673)

### Performance

- avoid scanning data uri media

### Chores

- 1.37.0 [skip ci]
- fix import breaking delinstrtext orphans (#3535)
- fix tests (#3533)
- fixes
- more fixes
- run generate:all and fixes
- more fixes
- soec fixes
- type fixes
- ui and more
- fix regression
- type fixes
- more fixes
- more fixes
- ci fixes
- type fixes
- add dispatch test for collab bug
- review fix, type fix
- add tests for metadata issue
- tests for review issues
### What's New

**Content Controls API** β€” Place the caret inside a control, scroll it into view, and track its active state across nesting.

- `ui.contentControls.focus({ id })` β€” Caret placement inside a control. Scrolls to the control first, then navigates inside. Returns `{ success }` with diagnostic failures like `not-ready` and `not-found`.
- `ui.contentControls.scrollIntoView(id)` β€” Scroll-only counterpart. Control position resolves from the document model, so off-screen controls work. Scroll-focused, separate from activation.
- `ui.contentControls.observe()` and events now expose `activePath` β€” Full stack of active controls (innermost first), so nested-aware custom UI only needs one API instead of combining events with observe.

**Viewport geometry observation** β€” Single rAF-coalesced signal for cached coordinates that may have gone stale.

- `ui.viewport.observe(listener)` β€” Fires with `{ reason }` (one of `'layout'`, `'zoom'`, `'scroll'`, `'resize'`, `'mixed'`) whenever getRect() results should be re-queried. Replaces hand-wiring scroll + resize + layout + zoom, which silently misses reflow.

**Responsive comments and tracked changes** β€” Adapt to screen size with automatic or locked display modes.

- Comments and tracked changes switch between sidebar and compact inline popovers based on container width.
- `displayMode: 'auto'` (default) β€” Automatic breakpoint. `'sidebar'` or `'inline'` lock the mode.
- `compactBreakpointPx` β€” Exact pixel width where inline mode activates (default 768px).
- `compactMeasurementSelector` β€” Which container to measure; defaults to the SuperDoc root.
- Inline comment popovers anchor to highlights with overflow-safe bounds and safe margins.

**Smart Tags** β€” Render and round-trip w:smartTag content from Word.

- Smart tag elements (countries, places, dates, names) now render visibly instead of disappearing.
- w:element, w:uri, and w:smartTagPr metadata persist on import and export.

**Cell-level Structured Document Tags** β€” Date pickers and other content controls that wrap table cells now import and export correctly.

- Word's `<w:sdt><w:sdtContent><w:tc>` pattern (ECMA-376 Part 1 Β§17.5.2.32) is now recognized and preserved.
- Vertical merge tracking works correctly with SDT-wrapped continuation cells.

**Non-base64 SVG data URIs** β€” Support inline SVG payloads encoded as URL-safe text.

- `data:image/svg+xml;charset=utf-8,<svg>...` now registers and persists in DOCX output.
- Sized SVG data URIs skip canvas processing and register in place.

### Improvements

**Find and replace** β€” Navigation is now smooth and predictable.

- Virtualized matches center only when off-screen, skip centering for visible results.
- Selection focus returning to the find input no longer jumps the viewport to a stale caret position.
- Copy-paste in suggestion mode now tracks SuperDoc's internal slice correctly.

**Structured content keyboard interactions** β€” Boundary behavior matches Word.

- Backspace/Delete at the start of a block SDT's first paragraph selects its content (one keystroke to confirm, one to delete).
- Backspace at the start of a textblock following a block SDT moves the caret inside the SDT instead of deleting across the boundary.
- Delete at the end of a textblock preceding a block SDT moves the caret inside the SDT.
- Backspace/Delete inside an empty inline SDT now selects and deletes the wrapper according to its lock mode.

**Empty structured content placeholders** β€” Inline and block SDTs now show visible "Click or tap here to enter text" affordances.

- Placeholder runs inherit the paragraph's resolved font, size, and color.
- Caret positioning and input handling work correctly on placeholders.
- Placeholder text is layout-only (no document text), styled via CSS pseudo-element.

**Structured content chrome** β€” Visual rendering is now robust across layouts and nesting.

- Block SDT background moves to a `::before` pseudo-element behind content, preventing field color from blocking hover/click.
- Block SDT borders move to a `::after` pseudo-element with `pointer-events: none`.
- Chrome sizing accounts for inline SDT wrapper chrome and image run geometry.
- RTL text aligns chrome correctly with `inset-inline-start`.
- Justified paragraphs size chrome for the full content width.

**Image-bearing inline SDTs** β€” Now promote to `inline-block` so images and chrome size correctly.

**Toolbar controls inside content-locked SDTs** β€” Mutation commands (format, paragraph, list, table, link, image, track-changes) are now disabled.

- View controls (undo/redo, ruler, zoom, document-mode, formatting marks) remain available.

**Image data URI handling** β€” Validation and persistence are now comprehensive.

- Malformed base64, oversized payloads, and non-image MIME types are rejected before export.
- SVG and raster data URIs register correctly as DOCX media parts.
- In-place SVG data URIs with known dimensions skip canvas processing.
- Non-base64 data URIs are decoded as text and written through on export.

**Diffing across editor instances** β€” Cross-editor handoff now works.

- Session-local `sdBlockId` values no longer cause PRECONDITION_FAILED errors when applying diffs to a second editor instance with the same content.
- Legacy snapshots and payloads from before this fix are accepted with fallback normalization.

**Infrastructure** β€” Type safety and payload correctness are now gated.

- Type-bearing JSDoc in .ts source is now forbidden (gate: strict-zero, no grandfathering).
- Runtime event payload shapes are pinned β€” `onReady`, `onEditorCreate`, `onLocked`, `onAwarenessUpdate`, `onCommentsUpdate` callbacks are verified against their declared types.
- Documentation examples are type-checked β€” All "Full Example" code blocks in the SuperDoc docs are checked with `tsc --strict`.
### What's New

- **Content Controls API** β€” `focus()` places the caret inside a control and scrolls it into view; `scrollIntoView()` scrolls controls to a target; `observe()` exposes `activePath` (full nesting stack for nested controls)
- **Viewport geometry observation** β€” `ui.viewport.observe()` fires when cached coordinates go stale, with reason: layout, zoom, scroll, resize, or mixed
- **Responsive comments and tracked changes** β€” Comments and tracked changes auto-switch between sidebar and inline popovers based on screen width (default breakpoint: 768px); lock to either mode with `displayMode`
- **Smart Tags** β€” w:smartTag elements render visibly instead of disappearing; w:element, w:uri, w:smartTagPr metadata persist through round-trip
- **Cell-level Structured Document Tags** β€” Date pickers and content controls wrapping table cells import and export correctly
- **Non-base64 SVG data URIs** β€” Support inline SVG via `data:image/svg+xml;charset=utf-8,<svg>...` format; sized SVGs skip canvas processing

### Improvements

- **Find and replace** β€” Navigation centers off-screen matches only; visible results no longer jump the viewport
- **Structured content keyboard behavior** β€” Backspace and Delete at SDT boundaries match Word behavior
- **Empty SDT placeholders** β€” Inline and block controls show visible "Click or tap here to enter text" affordances
- **Structured content rendering** β€” Chrome displays robustly across layouts, nesting levels, RTL text, and justified paragraphs
- **Image-bearing inline SDTs** β€” Promoted to inline-block so images and chrome size correctly
- **Content-locked toolbar** β€” Mutation commands disabled inside content-locked SDTs; view controls remain available
- **Image data URI handling** β€” Validate and reject malformed base64, oversized payloads, and non-image MIME types; support non-base64 SVG
- **Cross-editor diffs** β€” Diffs apply correctly across editor instances; session-local sdBlockId no longer causes errors
- **Type system** β€” Type-bearing JSDoc in TypeScript source now forbidden; runtime event payload shapes pinned to types; documentation examples type-checked with tsc
### What's New

- **Content control navigation** β€” ui.contentControls.focus() places the caret inside a control; ui.contentControls.scrollIntoView() scrolls to it
- **Viewport geometry signal** β€” ui.viewport.observe emits a single rAF-coalesced notification when layout/zoom/scroll/resize changes
- **Public content control events** β€” content-control:active-change and content-control:click now include full activation stack and source detection (pointer vs. keyboard)
- **Chrome control** β€” modules.contentControls.chrome option to suppress SDT visual chrome for custom styling
- **Empty SDT placeholders** β€” inline and block controls display "Click or tap here to enter text" with inherited paragraph styling
- **Smart tags** β€” w:smartTag elements now render and round-trip with visible content
- **Overlapping tracked changes** β€” multiple tracked changes can occupy the same range in collaboration
- **Anchored metadata orphans** β€” new orphan status for anchored metadata

### Improvements

- Find navigation no longer re-centers matches already on-screen
- Find navigation stops jumping when focus returns to the search input
- Content control navigation skips hidden markers and atoms
- SDT labels anchor to the leading edge for visual consistency
- Block SDT chrome extends across full fragment width
- Inline images top-align with text at baseline
- Block SDT backgrounds no longer interfere with hover/click placement
- Inline SDT wrappers with images correctly size to content
- Empty block SDT paragraphs inherit surrounding text styles
- RTL SDT chrome aligns using logical positioning
- Paragraph rendering unified between body and table cells
- Image helpers unified across all rendering surfaces

### Fixes

- Copy-pasted text in suggestion mode no longer reverts
- Block SDT deletion respects SDT lock modes
- Inline SDT boundaries now handle Delete correctly
- Backspace at inline SDT boundaries selects content without selecting chrome
- Cell-level SDTs in tables now import, export, and preserve correctly
- Vertical merge cells inside SDTs marked correctly
- Cross-editor diff application now works (sdBlockId stripped from fingerprint)
- Undo/redo works inside content-locked SDTs
- Text-align remains visible in locked SDT paragraphs
- Image data URIs validated before rendering or export
- SVG data URIs work without base64 encoding
- Nested table SDTs preserve chrome across fragments
- Pointer-source tracking works on all editor initialization paths
Perfect! I can see the release summary in the commit message. Let me refine it to match the SuperDoc voice and terminology:

### What's New

- **Content control navigation** β€” `ui.contentControls.focus()` places the caret inside a control; `ui.contentControls.scrollIntoView()` scrolls to it
- **Viewport geometry signal** β€” `ui.viewport.observe` emits when layout, zoom, scroll, or resize changes (single rAF-coalesced notification)
- **Content control events** β€” `content-control:active-change` and `content-control:click` include full activation stack and source detection (pointer vs. keyboard)
- **Content control chrome control** β€” `modules.contentControls.chrome` option suppresses visual styling for custom UI
- **Empty content control placeholders** β€” Inline and block controls display "Click or tap here to enter text" with inherited paragraph styling
- **Smart tags** β€” `w:smartTag` elements render and round-trip with visible content
- **Overlapping tracked changes** β€” Multiple tracked changes can occupy the same range in collaboration
- **Metadata orphan status** β€” Anchored metadata now reports an orphan status

### Improvements

- Find navigation no longer re-centers matches already on-screen
- Find navigation stops jumping when focus returns to search input
- Content control navigation skips hidden markers and atoms
- Content control labels anchor to the leading edge for visual consistency
- Block content control chrome extends across full fragment width
- Inline images top-align with text at baseline
- Block content control backgrounds no longer interfere with hover and click
- Inline content control wrappers with images size correctly to content
- Empty block content control paragraphs inherit surrounding text styles
- RTL content control chrome uses logical positioning
- Paragraph rendering unified between body and table cells
- Image helpers unified across all rendering surfaces

### Fixes

- Copy-pasted text in suggestion mode no longer reverts
- Block content control deletion respects lock modes
- Inline content control boundaries handle Delete correctly
- Backspace at inline content control boundaries selects content without chrome
- Cell-level content controls import, export, and preserve correctly
- Vertical merge cells inside content controls mark correctly
- Cross-editor diff application works (session-local attributes stripped from fingerprint)
- Undo/redo works inside content-locked controls
- Text-align remains visible in locked content control paragraphs
- Image data URIs validated before rendering or export
- SVG data URIs work without base64 encoding
- Nested table content controls preserve chrome across fragments
- Pointer-source tracking works on all editor initialization paths
### What's New

- **Content control navigation API** β€” `ui.contentControls.focus({ id })` places the caret inside a control; `ui.contentControls.scrollIntoView({ id })` scrolls to it.
- **Viewport geometry signal** β€” `ui.viewport.observe` emits a single `requestAnimationFrame`-coalesced notification when layout, zoom, scroll, or resize changes. Payload includes the change reason.
- **Overlapping tracked changes** β€” Multiple tracked changes can now occupy the same range in collaboration scenarios.
- **Enhanced content control events** β€” `content-control:active-change` now includes `activePath` (full activation stack from innermost first) and improved source detection (pointer vs. keyboard).
- **Cell-level SDT support** β€” Content controls wrapping individual table cells import, export, and preserve correctly, including vertical merge handling.
- **Smart tags** β€” `w:smartTag` elements now render with visible content and round-trip with full property metadata.
- **Anchored metadata orphan status** β€” New status indicator for anchored metadata that loses its anchor point.
- **Chrome control option** β€” `modules.contentControls.chrome` lets you suppress built-in visual styling for custom UI responsibility.
- **Empty control placeholders** β€” Inline and block controls display "Click or tap here to enter text" with inherited paragraph styling.

### Improvements

- Find navigation no longer re-centers matches already on-screen, eliminating jarring viewport jumps.
- Find navigation stops jumping when focus returns to the search input during active search.
- Content control navigation skips hidden markers and atoms for more predictable boundary behavior.
- SDT labels anchor to the leading edge instead of center, providing visual consistency.
- Block SDT chrome extends across the full fragment width, maintaining click affordances across line breaks.
- Inline images top-align with text at baseline instead of centering, matching Word's behavior.
- Block SDT backgrounds no longer interfere with hover and click placement.
- Inline SDT wrappers containing images correctly size to content via `inline-block` layout.
- Empty block SDT paragraphs inherit surrounding text styles (font, size, color).
- RTL SDT chrome aligns using logical positioning, respecting document direction.
- Paragraph rendering unified between body and table cells, ensuring consistent behavior across all text containers.
- Image helpers unified across all rendering surfaces (body, tables, fields).
- Copy-pasted text in suggestion mode no longer reverts to previous state.
- Cross-editor diff application now works β€” session-local `sdBlockId` stripped from fingerprint.
- Malformed image data URIs rejected before rendering or export.
- SVG data URIs work without base64 encoding, preserving vector content.
- Non-base64 SVG payloads support URL-encoded alternatives via `charset=utf-8`.
- Inline SDT chrome width included in block SDT bounds, preventing clipping of nested controls.
- Undo/redo now works inside content-locked SDTs via history transaction bypass.
- Text-align state remains visible in locked SDT paragraphs as a read-only indicator.
- Toolbar mutation controls properly disabled inside content-locked SDTs.

### Fixes

- Backspace at inline SDT boundaries selects content without selecting chrome.
- Cell-level SDTs in tables import, export, and preserve correctly across round-trip.
- Vertical merge cells inside SDTs marked correctly during import.
- Block SDT deletion respects SDT lock modes instead of unconditionally blocking.
- Inline SDT content selected as text on Delete, giving explicit confirm-then-delete UX.
- Inline SDT boundaries handle Delete correctly without escaping into surrounding text.
- Nested table SDTs preserve chrome across fragmented content boundaries.
- Pointer-source tracking works on all editor initialization paths, not just deferred loads.
- Malformed base64 image data URIs now validated before creating DOCX media parts.
- Oversized async SVG images validated for export.
- Vertical merge column lookups find cell-level SDT-wrapped cells correctly.
- Diff fingerprint normalization applied uniformly to all block nodes, not just paragraphs.
- Legacy diff fingerprints accepted in compare/apply for backward compatibility with persisted snapshots.
@superdoc-bot superdoc-bot Bot requested a review from a team as a code owner May 29, 2026 21:57
@superdoc-bot superdoc-bot Bot added patch-sync Patch sync from release branch review: quick labels May 29, 2026
Copy link
Copy Markdown

@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: 37a0e04169

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 πŸ‘.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

"name": "superdoc",
"type": "module",
"version": "1.37.0",
"version": "1.38.0",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Regenerate this stable sync as a real merge commit

For this stable→main sync, the commit object has only one parent (63c71beb...), so even if the PR is merged with GitHub's merge-commit option, main will only gain these copied version files and will not gain the stable branch/tag commits as ancestors. In the release path described by this commit, any prerelease calculation based on merged/reachable stable tags will still miss the latest stable release; please recreate the sync commit with stable as a second parent instead of a single-parent version bump.

Useful? React with πŸ‘Β / πŸ‘Ž.

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

βœ… All modified and coverable lines are covered by tests.

πŸ“’ Thoughts on this report? Let us know!

Copy link
Copy Markdown
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.

lgtm

@caio-pizzol caio-pizzol merged commit fa9d733 into main May 29, 2026
75 checks passed
@caio-pizzol caio-pizzol deleted the sync/stable-to-main-20260529-215717 branch May 29, 2026 23:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

patch-sync Patch sync from release branch review: quick

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants