Skip to content

feat(word-diff): implement word-level diffing for granular text changes#2817

Merged
harbournick merged 1 commit intomainfrom
andrii/sd-2569-granular-tracked-changes-for-llm-text-replacements
Apr 15, 2026
Merged

feat(word-diff): implement word-level diffing for granular text changes#2817
harbournick merged 1 commit intomainfrom
andrii/sd-2569-granular-tracked-changes-for-llm-text-replacements

Conversation

@andrii-harbour
Copy link
Copy Markdown
Contributor

No description provided.

@andrii-harbour andrii-harbour self-assigned this Apr 15, 2026
@linear
Copy link
Copy Markdown

linear bot commented Apr 15, 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: 38564682d3

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

Comment on lines +907 to +908
const textNode = editor.state.schema.text(trimmedNew, asProseMirrorMarks(marks));
tr.replaceWith(trimmedFrom, trimmedTo, textNode);
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 Avoid creating empty text nodes for delete-only rewrites

In executeTextRewrite, the single-change path always does schema.text(trimmedNew) even when the trimmed diff is a pure deletion. For inputs like removing a word ("The quick fox" β†’ "The fox"), trimmedNew becomes "", and ProseMirror rejects empty text nodes at runtime, aborting the rewrite instead of applying the delete. This regression is introduced by the new prefix/suffix trimming flow and will surface on common delete-only edits.

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

Comment on lines +726 to +727
const segments = this.collectTextSegments(from, to);
const nodes = this.buildTextNodes(from, to, change.newText, segments);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Read replacement marks from transaction doc after remapping

applyGranularChanges remaps later change positions through prior tr.steps, but then calls collectTextSegments(from, to) on this.editor.state.doc (the original document). After an earlier insert/delete changes length, those remapped positions no longer point to the same content in the original doc, so subsequent replacements can inherit marks from the wrong region (or none), causing formatting loss/corruption in multi-change tracked edits.

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

@harbournick harbournick enabled auto-merge April 15, 2026 03:45
@harbournick harbournick disabled auto-merge April 15, 2026 03:45
@harbournick harbournick enabled auto-merge April 15, 2026 03:45
@harbournick harbournick merged commit 5d52db3 into main Apr 15, 2026
49 of 56 checks passed
@harbournick harbournick deleted the andrii/sd-2569-granular-tracked-changes-for-llm-text-replacements branch April 15, 2026 03:45
@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot bot commented Apr 15, 2026

πŸŽ‰ This PR is included in vscode-ext v2.3.0-next.18

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot bot commented Apr 15, 2026

πŸŽ‰ This PR is included in @superdoc-dev/react v1.2.0-next.15

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot bot commented Apr 15, 2026

πŸŽ‰ This PR is included in template-builder v1.5.0-next.18

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot bot commented Apr 15, 2026

πŸŽ‰ This PR is included in esign v2.3.0-next.18

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot bot commented Apr 15, 2026

πŸŽ‰ This PR is included in superdoc v1.26.0-next.18

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot bot commented Apr 15, 2026

πŸŽ‰ This PR is included in superdoc-cli v0.7.0-next.19

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot bot commented Apr 15, 2026

πŸŽ‰ This PR is included in superdoc-sdk v1.6.0-next.16

caio-pizzol added a commit that referenced this pull request Apr 16, 2026
The word-diff executor added in #2817 calls `tr.doc.textBetween(...)` and
`tr.doc.nodesBetween(...)` in the text.rewrite path, but the `tr.doc`
mocks in determinism-stress, executor, and preview-parity tests were
never updated to match. That broke determinism-stress, executeCompiledPlan,
previewPlan, and revision-drift-guard tests on main with `TypeError:
tr.doc.textBetween is not a function` / `doc.nodesBetween is not a function`.
caio-pizzol added a commit that referenced this pull request Apr 16, 2026
* test(superdoc): add unit tests for pdf, comments, and pdf-viewer

Adds test coverage for previously untested files:
- core/pdf/pdf-adapter.js β€” factory, adapter, CDN worker helper
- components/CommentsLayer/use-conversation.js β€” conversation composable
- components/CommentsLayer/use-floating-comment.js β€” floating comment state
- components/CommentsLayer/CommentGroup.vue β€” grouped comment rendering
- components/PdfViewer/PdfViewer.vue β€” top-level viewer with adapter mocks
- components/PdfViewer/PdfViewerDocument.vue β€” page list wrapper
- components/PdfViewer/PdfViewerPage.vue β€” page render + text layer

62 new tests. Lifts filtered coverage from 78.6% to 81.1%.

* test(superdoc): add tests for composables and comments list

- composables/use-field.js β€” useField + sub-handlers (SELECT/IMAGE/CHECKBOX)
- composables/use-ai.js β€” AI writer cursor positioning, fallbacks, tool click
- components/CommentsLayer/commentsList/super-comments-list.js β€” Vue app lifecycle
- components/Whiteboard/use-whiteboard.js β€” event wiring, page ready, teardown

46 new tests. Lifts filtered coverage 81.1% β†’ 83.3%.

* test(superdoc): cover WhiteboardPage canvas interactions

Mock Konva Stage/Layer/Line/Text/Image/Transformer and trigger
stage/text-node event listeners to exercise the interactive code
paths: draw/erase flows, stage click handlers (text + select),
text node selection + drag + Delete, image node events.

38 tests. Lifts WhiteboardPage coverage 40% β†’ 81%, package 83.3% β†’ 88.5%.

* fix(test): add textBetween/nodesBetween to plan-engine tr.doc mocks

The word-diff executor added in #2817 calls `tr.doc.textBetween(...)` and
`tr.doc.nodesBetween(...)` in the text.rewrite path, but the `tr.doc`
mocks in determinism-stress, executor, and preview-parity tests were
never updated to match. That broke determinism-stress, executeCompiledPlan,
previewPlan, and revision-drift-guard tests on main with `TypeError:
tr.doc.textBetween is not a function` / `doc.nodesBetween is not a function`.

* test(superdoc): push coverage past 90%

Add targeted tests to close remaining gaps:
- use-comment extended β€” resolveComment, setIsInternal, setText, mentions
- superdoc-store extended β€” reset, getDocument, handlePageReady, getPageBounds,
  areDocumentsReady, setExceptionHandler, collaboration mode
- Whiteboard extended β€” tool/enabled propagation, opacity clamping, callbacks
- New small files: comment-schemas, DocumentUsers.vue, SuperToolbar.vue,
  use-selection, CommentsLayer/helpers formatDate

Lifts package coverage from 83.3% to 90.1%.
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