-
Notifications
You must be signed in to change notification settings - Fork 66
fix(super-editor): allow Backspace to delete empty paragraphs in suggesting mode #1966
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(super-editor): allow Backspace to delete empty paragraphs in suggesting mode #1966
Conversation
There was a problem hiding this 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: 9916d6484e
ℹ️ 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".
packages/super-editor/src/extensions/track-changes/trackChangesHelpers/replaceStep.js
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Fixes a track-changes edge case in the super editor where pressing Backspace on a newly created empty paragraph in suggesting mode results in a no-op, by allowing certain “pure deletion” ReplaceSteps to apply directly (untracked) when there’s no inline content to mark as deleted.
Changes:
- Add an early guard in
replaceStep()to directly apply pure-deletion steps when the deleted range contains no inline nodes. - Add a unit test covering Backspace-like deletion of an empty paragraph in suggesting mode.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| packages/super-editor/src/extensions/track-changes/trackChangesHelpers/replaceStep.js | Adds a guard to bypass tracked-change logic for deletions with no inline content, allowing empty paragraph removal. |
| packages/super-editor/src/extensions/track-changes/trackChangesHelpers/replaceStep.test.js | Adds a regression test asserting an empty paragraph is removed when “Backspace deletion” occurs in suggesting mode. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
packages/super-editor/src/extensions/track-changes/trackChangesHelpers/replaceStep.test.js
Show resolved
Hide resolved
packages/super-editor/src/extensions/track-changes/trackChangesHelpers/replaceStep.js
Outdated
Show resolved
Hide resolved
harbournick
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's a bug with: When a user presses Backspace at the start of a non-empty paragraph, the paragraphs are joined, but the delete is applied directly and no deletion mark is created. That makes the edit invisible (not reviewable/rejectable) in Suggesting mode. The direct-delete fast path should only apply to removing a truly empty block node.
see 7ebce03 (I added a test that fails here for this case)
- Introduced a new test suite for keymap history grouping, validating the behavior of the Enter and space keys in creating undo boundaries. - Enhanced the handleEnter and handleBackspace functions to dispatch closeHistory, ensuring proper history management during text input. - Added tests to confirm that undo operations correctly restore text and manage undo group boundaries in various scenarios.
…n suggesting mode
…mode The replaceStep guard now applies any pure deletion with no inline content directly, covering both empty paragraph removal and paragraph joins. markDeletion cannot represent structural changes (block boundary tokens) as inline marks, so these steps were silently swallowed. Fixes the Enter→Enter→Backspace→Backspace flow in suggesting mode where the second Backspace (paragraph join) did nothing.
db51225 to
3d37af6
Compare
We have an existing bug that we don't track new line breaks inside a paragraph, or enters in a document, or backspace in paragraphs. its a separate issue altogether. In that case let's leave it alone in 1966 we can proceed without it. |
caio-pizzol
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking good @tupizz
since it involves browser interactions, let's also write a "interaction story" in @devtools/visual-testing
p.s. there's already a comments-tcs/ category with tracked change stories
.tupizz/docs/sd-1810-backspace-empty-paragraph-suggesting-mode.md
Outdated
Show resolved
Hide resolved
packages/super-editor/src/extensions/track-changes/trackChangesHelpers/replaceStep.js
Show resolved
Hide resolved
packages/super-editor/src/extensions/track-changes/trackChangesHelpers/replaceStep.js
Show resolved
Hide resolved
- Fix editor?.view?.dispatch inconsistency in handleDelete (use view?.dispatch) - Add comments explaining closeHistory no-op edge case in keymap handlers - Add tests for handleBackspace/handleDelete closeHistory behavior - Extract ensureUniqueSdBlockId() helper to deduplicate seenIds logic in block-node - Add comment explaining TrackDelete-only paragraph edge case in replaceStep - Add visual testing story for SD-1810 backspace empty paragraph in suggesting mode
caio-pizzol
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm - let's make sure to add interaction story for this scenario before merging
|
thanks @caio-pizzol |
harbournick
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
🎉 This PR is included in superdoc v1.12.0-next.15 The release is available on GitHub release |
Demo
CleanShot.2026-02-09.at.21.13.12.mp4
Summary
Fixes SD-1810 — Backspace doesn't delete empty paragraph in suggesting mode.
MVP blocker for Ontra (Feb 17 release).
Problem
When a user creates a new paragraph (Enter) in suggesting mode and immediately presses Backspace, nothing happens — the empty paragraph stays.
Root cause
The track changes system intercepts every transaction in suggesting mode via
trackedTransaction→replaceStep()→markDeletion(). The flow:ReplaceStep(from, to, Slice.empty)to remove itreplaceStep()inverts the original step and tries to re-apply it as a tracked changemarkDeletion()iteratesnodesBetween(from, to)looking for inline nodes to mark as deletedFix
Added an early return guard at the top of
replaceStep(). Before entering the full tracked-change flow, it checks:step.slice.content.size === 0(no replacement content)nodesBetweenfinds no inline nodesWhen both are true, the step is applied directly since there's nothing to track as a change. This matches Word behavior — deleting an empty paragraph has no visible "tracked change" to show.
For all other cases (non-empty paragraphs, text content, etc.), the existing tracked-change flow runs unchanged.
Changes
replaceStep.js— 6-line guard clause at function entry (lines 24–42)replaceStep.test.js— new test: creates<p>Hello</p><p></p>, simulates Backspace on empty paragraph, asserts it's removedTest plan
deletes empty paragraph on Backspace in suggesting mode