Skip to content

fix(super-editor): keep comment range markers around unpaired tracked changes (SD-2528)#3239

Open
tupizz wants to merge 1 commit into
mainfrom
tadeu/sd-2528-redline-comment-roundtrip
Open

fix(super-editor): keep comment range markers around unpaired tracked changes (SD-2528)#3239
tupizz wants to merge 1 commit into
mainfrom
tadeu/sd-2528-redline-comment-roundtrip

Conversation

@tupizz
Copy link
Copy Markdown
Contributor

@tupizz tupizz commented May 11, 2026

Summary

When a user comments on redlined text, the exported DOCX put w:commentRangeStart outside the w:del wrapper but w:commentRangeEnd and the w:commentReference run inside it. Re-importing that file separates the comment from the redline (and from itself) instead of restoring a single unified bubble. Customer-reported (Bonterms).

Root cause is in mergeConsecutiveTrackedChanges (translate-paragraph-node.js). The forward scan greedily absorbed every comment marker / comment-reference run it found after a w:ins/w:del, even when no same-id wrapper actually followed to merge with. So a lone tracked change always swallowed its trailing comment markers.

Fix: buffer comment markers during the scan and only commit them inside the wrapper when a same-id merge actually happens. Otherwise emit them as siblings.

  • w:commentRangeStart ... w:del ... w:commentRangeEnd ... w:r/w:commentReference now stays as siblings (SD-2528).
  • SD-1519 same-id merge with comments between is still preserved and now covered by a regression test.

Test plan

  • Unit tests in translate-paragraph-node.test.js cover three cases: SD-2528 (single wrapper + trailing comments), SD-1519 (same-id merge absorbs comments), different-id (no merge, comments stay siblings).
  • Full pnpm --filter super-editor test passes (1008 files, 12711 tests).
  • Round-trip a fixture with a comment on a redline in Word and confirm the unified bubble survives.

… tracked changes (SD-2528)

mergeConsecutiveTrackedChanges greedily absorbed trailing w:commentRangeEnd
and w:r->w:commentReference elements into a w:del/w:ins wrapper even when no
same-id wrapper followed to actually merge into. This produced a lopsided
structure where w:commentRangeStart sat outside the wrapper but
w:commentRangeEnd ended up inside it, breaking comment round-trip on redlined
text.

Buffer comment markers during the forward scan and only commit them inside
the wrapper when a same-id merge actually happens. Otherwise emit them as
siblings, matching Word's expected OOXML.

SD-1519 merge behavior is unchanged and covered by the new tests.
@tupizz tupizz requested a review from a team as a code owner May 11, 2026 22:48
@linear
Copy link
Copy Markdown

linear Bot commented May 11, 2026

SD-2528

@github-actions
Copy link
Copy Markdown
Contributor

Note: The MCP ecma-spec tools were not granted permission, so I'm reviewing against my working knowledge of ECMA-376 Part 1 (WordprocessingML).

Status: PASS

The PR doesn't change the OOXML vocabulary being emitted β€” it only adjusts where comment range markers land relative to a tracked-change wrapper. Quick verification against the spec:

  • w:ins / w:del use CT_RunTrackChange, whose content model permits both EG_RangeMarkupElements (the w:commentRangeStart/End family) and w:r (which is the legal carrier for w:commentReference). So comment markers being inside or outside the wrapper are both spec-valid β€” the fix is about round-trip pairing, not spec legality. (w:ins, w:del)
  • Attributes on the fixtures are clean: w:del carries w:id/w:author/w:date (CT_TrackChange β€” w:id and w:author required, w:date optional βœ“), w:commentRangeStart/End carry the required w:id (CT_MarkupRange βœ“), and w:commentReference carries the required w:id (CT_Markup βœ“). (w:commentRangeStart, w:commentReference)
  • No new attributes or elements are introduced, and no defaults are being assumed.

The AIDEV-NOTE correctly captures the real motivation: the previous behavior could end up with w:commentRangeStart outside the wrapper and w:commentRangeEnd absorbed inside it, which β€” while structurally legal β€” breaks the importer's pairing assumptions. The new behavior preserves the marker siblings when no merge happens, which is the right call.

@tupizz tupizz self-assigned this May 11, 2026
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

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

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

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.

2 participants