Skip to content

fix(track-changes): remove ghost TrackFormat on multi-node format cancel#2233

Merged
caio-pizzol merged 7 commits intomainfrom
fix/track-format-cancel-multinode
Mar 2, 2026
Merged

fix(track-changes): remove ghost TrackFormat on multi-node format cancel#2233
caio-pizzol merged 7 commits intomainfrom
fix/track-format-cancel-multinode

Conversation

@caio-pizzol
Copy link
Contributor

@caio-pizzol caio-pizzol commented Mar 2, 2026

Builds on #2212 by @gpardhivvarma (range clamping + sharedWid fixes) and adds the missing cancel logic for nodes with pre-existing marks.

  • When bold is toggled on then off across a multi-node selection (e.g., "Hello " plain + "world" italic), the removeMarkStep cancel path only cleaned up when both before and after were empty
  • This missed nodes like "world" where before=[italic] (a snapshot of pre-existing marks) — leaving a ghost TrackFormat showing "Format: removed italic" even though italic was never touched
  • The fix checks whether all marks in before still exist on the node; if they do, the tracked change is a no-op and the TrackFormat is removed

gpardhivvarma and others added 5 commits February 28, 2026 01:44
…suggestion

Two bugs caused the gold/yellow TrackFormat underline to persist after
reversing a tracked format change:

1. addMarkStep applied TrackFormat using the full step range instead of
   clamped per-node boundaries, leaking wrong before/after arrays onto
   adjacent text nodes.

2. removeMarkStep didn't clean up fully-reversed format changes — when
   a tracked addition was toggled back (after=[] but before had items),
   the TrackFormat mark persisted instead of being removed.
Narrowed the early-exit condition so TrackFormat is only removed when
both arrays are empty (true no-op). Keeps the mark when before has
legitimate tracked removals (e.g. before=[italic], after=[]).
Hoist a sharedWid variable so all inline nodes touched by a single
addMarkStep reuse the same TrackFormat ID. With per-node clamped ranges,
getLiveInlineMarksInRange no longer sees the previous node's TrackFormat,
causing each node to generate a separate UUID. This broke ID-based
reject/accept flows for multi-node selections.
Mirror the sharedWid pattern from addMarkStep. When an existing
formatChangeMark is present, reuse its ID to preserve change grouping.
When creating new TrackFormat marks across multiple nodes, share a
single generated ID so reject/accept treats them as one change.
…des with pre-existing marks

When bold is toggled on then off across multi-node selections where some
nodes have pre-existing marks (e.g., italic), the removeMarkStep cancel
path only cleaned up when both `before` and `after` arrays were empty.
This missed the case where `before` had pre-existing marks that were
never actually removed — leaving a ghost TrackFormat mark showing
"Format: removed italic" even though italic was untouched.

The fix checks whether all marks in `before` still exist on the node.
If they do, the tracked change is a no-op and the TrackFormat is removed.
The isNoop check compared mark snapshots by type name only, ignoring
attributes. For textStyle/highlight marks with differing attrs, this
could incorrectly treat a real change as a no-op. Use the existing
markSnapshotMatchesStepMark helper for full type+attrs comparison.

Also simplifies multi-node test to use the addThenRemoveMark helper.
- Unit tests for sharedWid across runs and range clamping
- Behavior test for toggling bold on/off across mixed-mark nodes
@caio-pizzol caio-pizzol merged commit e925ef9 into main Mar 2, 2026
8 checks passed
@caio-pizzol caio-pizzol deleted the fix/track-format-cancel-multinode branch March 2, 2026 10:52
@superdoc-bot
Copy link
Contributor

superdoc-bot bot commented Mar 2, 2026

🎉 This PR is included in superdoc-cli v0.2.0-next.50

The release is available on GitHub release

@superdoc-bot
Copy link
Contributor

superdoc-bot bot commented Mar 2, 2026

🎉 This PR is included in superdoc v1.17.0-next.56

The release is available on GitHub release

harbournick pushed a commit that referenced this pull request Mar 3, 2026
# [1.17.0](v1.16.0...v1.17.0) (2026-03-03)

### Bug Fixes

* active track change ([#2163](#2163)) ([108c14d](108c14d))
* add currentTotalPages getter and pagination-update event ([#2202](#2202)) ([95b4579](95b4579)), closes [#958](#958)
* always call resolveComment after custom TC bubble handlers (SD-2049) ([#2204](#2204)) ([34fb4e0](34fb4e0))
* backward replace insert text ([#2172](#2172)) ([66f0849](66f0849))
* before paragraph spacing inside table cells ([#1842](#1842)) ([c7efa85](c7efa85))
* **collaboration:** deduplicate updateYdocDocxData during replaceFile (SD-1920) ([#2162](#2162)) ([52962fc](52962fc))
* **comments:** cross-page collision avoidance for floating comment bubbles (SD-1998) ([#2180](#2180)) ([6cfbeca](6cfbeca))
* **comments:** emit empty comment positions so undo clears orphan bubbles ([#2235](#2235)) ([12ba727](12ba727))
* **comments:** improve multiline comment input styling ([#2242](#2242)) ([e6a0dab](e6a0dab))
* **comments:** prevent comment mark from extending to adjacent typed text ([#2241](#2241)) ([07fecd8](07fecd8))
* **comments:** reduce sidebar jitter when clicking comments (SD-2034) ([#2250](#2250)) ([c3568d2](c3568d2))
* **comments:** remove synchronous dispatch from plugin apply() (SD-1940) ([#2157](#2157)) ([887175b](887175b))
* **css:** scope ProseMirror CSS to prevent bleeding into host apps (SD-1850) ([#2134](#2134)) ([b9d98fa](b9d98fa))
* document-api improvements, plan mode, query.match, mutations ([6221580](6221580))
* **document-api:** delete table cell fix ([#2209](#2209)) ([5e5c43f](5e5c43f))
* **document-api:** distribute columns command fixes ([#2207](#2207)) ([8f4eaf7](8f4eaf7))
* **document-api:** fix cell shading in document api ([#2215](#2215)) ([456f60e](456f60e))
* **document-api:** insert table cell ([#2210](#2210)) ([357ee90](357ee90))
* **document-api:** plan-engine reliability fixes and error diagnostics ([#2185](#2185)) ([abfd81b](abfd81b))
* **document-api:** split table cell command ([#2217](#2217)) ([0b3e2b4](0b3e2b4))
* **document-api:** split table command ([#2214](#2214)) ([ec31699](ec31699))
* **editor:** render styles applied inside SDT fields (SD-2011) ([#2188](#2188)) ([9c34be3](9c34be3))
* **editor:** selection highlight flickers when dragging across mark boundaries (SD-2024) ([#2205](#2205)) ([ba03e76](ba03e76))
* extract duplicate block identity normalization from docxImporter ([7f7ff93](7f7ff93))
* improve backspace behavior near run boundaries for tracked changes ([#2175](#2175)) ([6c9c7a3](6c9c7a3))
* **layout:** per-section footer constraints for multi-section docs (SD-1837) ([#2022](#2022)) ([e11acc5](e11acc5))
* markdown block-separator blank lines and heading split style-mark normalization ([e988adc](e988adc))
* normalize review namespace into trackChanges, harden input validation ([33e907b](33e907b))
* outside click for toolbar dropdown ([#2174](#2174)) ([5f859c7](5f859c7))
* prefer full decoration range ([#2239](#2239)) ([ac15e31](ac15e31)), closes [#collectDesiredState](https://github.com/superdoc-dev/superdoc/issues/collectDesiredState) [#resolveEffectiveRanges](https://github.com/superdoc-dev/superdoc/issues/resolveEffectiveRanges) [#setPreviousRanges](https://github.com/superdoc-dev/superdoc/issues/setPreviousRanges)
* preserve line spacing and indentation on Google Docs paste ([#2183](#2183)) ([b9a7357](b9a7357)), closes [#2151](#2151)
* preserve text-align on paste from Google Docs ([#2208](#2208)) ([762231b](762231b))
* rollback comments colors / ui ([#2216](#2216)) ([a99b5ab](a99b5ab))
* **scroll:** wait for virtualized page mount and center text element ([#2221](#2221)) ([95f634e](95f634e))
* **shapes:** render grouped DrawingML shapes with custom geometry (SD-1877) ❇️ ([#2105](#2105)) ([14985a5](14985a5))
* splitting run with header adds empty row ([#2229](#2229)) ([e1965fc](e1965fc))
* **super-converter:** handle empty pic:spPr in image import ([#2254](#2254)) ([2b8dbce](2b8dbce))
* **super-editor:** backspace across run boundaries without splitting list items ([#2258](#2258)) ([27ccb64](27ccb64))
* support cell spacing ([#1879](#1879)) ([1639967](1639967))
* **tables:** defaultTableStyle support, cell fixes ([#2246](#2246)) ([74fca9c](74fca9c))
* **tables:** expand auto-width tables to fill available page width ([#2109](#2109)) ([15f36bc](15f36bc))
* **tables:** preserve TableGrid defaults and style-driven spacing/bor… ([#2230](#2230)) ([b0a482f](b0a482f))
* text highlight on export ([#2189](#2189)) ([9cbd022](9cbd022))
* track highlight changes ([#2192](#2192)) ([e164625](e164625))
* **track-changes:** correct format change description for already-formatted text (SD-2077) ([#2253](#2253)) ([b2ffc0d](b2ffc0d))
* **track-changes:** handle ReplaceAroundStep in tracked changes mode (SD-2061) ([#2225](#2225)) ([8f3cbe4](8f3cbe4))
* **track-changes:** remove ghost TrackFormat on multi-node format cancel ([#2233](#2233)) ([e925ef9](e925ef9))
* undo/redo actions ([#2161](#2161)) ([495e92f](495e92f))
* **virtualization:** correct scroll mapping and viewport sizing at non-100% zoom ([#2171](#2171)) ([84af4c0](84af4c0)), closes [#registryKey](https://github.com/superdoc-dev/superdoc/issues/registryKey)

### Features

* allow custom accept/reject handlers for TC bubbles ([#1921](#1921)) ([e30abf6](e30abf6))
* **comments:** improve floating comments ui ([#2195](#2195)) ([e870cfb](e870cfb))
* **document-api:** add format operations font size alignment color font family ([#2179](#2179)) ([f19c688](f19c688))
* **document-api:** add get markdown to sdks ([e42b56d](e42b56d))
* **document-api:** add plan-based mutation engine with query.match and style capture ([#2160](#2160)) ([365293a](365293a))
* **document-api:** default table style setting ([#2248](#2248)) ([3ad4e9f](3ad4e9f))
* **document-api:** default target-less insert to document end ([#2244](#2244)) ([c717e2b](c717e2b))
* **document-api:** doc default initial styles ([#2184](#2184)) ([f25e41f](f25e41f))
* **document-api:** format.paragraph for w:pPr formatting ([#2218](#2218)) ([32c9991](32c9991))
* **document-api:** history name space ([#2219](#2219)) ([41dea37](41dea37))
* **document-api:** include anchored text in comments list response ([#2177](#2177)) ([b3a2912](b3a2912))
* **document-api:** inline formatting parity core end-to-end ([#2197](#2197)) ([b405b03](b405b03))
* **document-api:** inline formatting rpr parity ([#2198](#2198)) ([41ab771](41ab771))
* **document-api:** lists namespace  ([#2223](#2223)) ([09ebfcb](09ebfcb))
* **document-api:** section commands ([#2199](#2199)) ([ec4abe3](ec4abe3))
* **document-api:** support deleting entire block nodes not only text ([#2181](#2181)) ([2897246](2897246))
* **document-api:** table of contents commands ([#2200](#2200)) ([baa72c4](baa72c4))
* **document-api:** tables namespace and commands ([#2182](#2182)) ([b80ee31](b80ee31))
* **document-api:** toc commands ([#2220](#2220)) ([767e010](767e010))
* **images:** allow drag-and-drop for images in editor ([#2227](#2227)) ([4b36780](4b36780))
* **layout-engine:** render table headers, tblLook support ([#2256](#2256)) ([db6a2ff](db6a2ff))
* **link-popover:** custom link popovers ([#2222](#2222)) ([070190f](070190f))
* **markdown:** add markdown override to sdk, improve conversion ([#2196](#2196)) ([04a1c71](04a1c71))
* preserve w:view setting through DOCX round-trip ([#2190](#2190)) ([48b4210](48b4210)), closes [#2070](#2070)
* real time collab in python sdk ([#2243](#2243)) ([dc3b4fd](dc3b4fd))
* **tables:** allow resizing table rows ([#2226](#2226)) ([2c6da10](2c6da10))
* **tables:** improve cell color application (context), column dragging, table pasting ([#2228](#2228)) ([066b9eb](066b9eb))
* **table:** toggle header row sets both cell types and repeatHeader atomically ([#2245](#2245)) ([2f5899d](2f5899d))
* **track-changes:** clear comment bubbles when bulk accept or reject TCs ([#2159](#2159)) ([27fbe8e](27fbe8e))

### Performance Improvements

* **comments:** batch tracked change comment creation on load ([#2166](#2166)) ([0c2eca5](0c2eca5))
* **comments:** batch tracked change creation and virtualize floating bubbles (SD-1997) ([#2168](#2168)) ([70fd7d9](70fd7d9))
@harbournick
Copy link
Collaborator

🎉 This PR is included in superdoc v1.17.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.

3 participants