-
Notifications
You must be signed in to change notification settings - Fork 61
Description
Description
When using SuperDoc in Suggesting Mode (track changes), typing new text after deleting ALL content in a text node results in characters appearing in reverse order.
For example:
- Original text:
TEST - Delete all 4 characters (backspace Γ 4)
- Type:
ABCD - Expected result:
ABCD - Actual result:
DCBA
Reproduction Steps
- Open SuperDoc with collaboration enabled and in suggesting/track changes mode (
documentMode: 'suggesting') - Have some text in the document (e.g., "TEST")
- Delete ALL the text using backspace (all characters get
trackDeletemarks) - Start typing new characters (e.g., "ABCD")
- Observe that characters appear in reverse order
Important Finding
The bug only occurs when ALL content is deleted:
| Scenario | Result |
|---|---|
| Delete 3 of 4 chars, then type ABCD | β
Works correctly: ABCD |
| Delete ALL 4 chars, then type ABCD | β Reversed: DCBA |
This does NOT happen in editing mode - only in suggesting mode with track changes.
Root Cause Analysis
Through debugging with Y.Doc observers, we identified the issue in the Yjs delta operations:
// Expected: retain should increment (1, 2, 3, 4...) as cursor advances
// Actual: retain stays at 1 for every insert
// First keystroke "A":
[XmlFragment Change - TEXT DELTA] {
delta: [
{ retain: 1 }, // Position 1
{ insert: "A", attributes: { trackInsert: {...} } }
]
}
// Second keystroke "B":
[XmlFragment Change - TEXT DELTA] {
delta: [
{ retain: 1 }, // β Still 1, should be 2!
{ insert: "B", attributes: { trackInsert: {...} } }
]
}
// Third keystroke "C":
[XmlFragment Change - TEXT DELTA] {
delta: [
{ retain: 1 }, // β Still 1, should be 3!
{ insert: "C", attributes: { trackInsert: {...} } }
]
}The cursor position (relative position in CRDT) is not advancing after each insert when the text node is "visually empty" (all content has trackDelete marks but still exists in the document).
Additional Observation
We also noticed a large docx-update event (~23KB) being triggered after EVERY keystroke:
[Y.Doc Update] {
origin: { event: 'docx-update', user: {...} },
updateSize: 23799 // Full document sync on every keystroke
}This full document re-sync via updateYdocDocxData() storing the entire DOCX in the Y.Doc meta map after each keystroke may be interfering with cursor position tracking. At minimum, this is a significant performance concern for collaborative editing at scale (thousands of concurrent users).
Environment
- SuperDoc version: 1.8.3 (also reproduced on 1.7.0)
- Browser: Chrome
- Collaboration: Using HocuspocusProvider with Yjs
- y-prosemirror: 1.3.7
- yjs: 13.6.19
- Mode: Suggesting (track changes enabled)
Demo Comparison
We tested on the official SuperDoc demo which uses version 0.20.0-next.13 and could NOT reproduce the issue there. This suggests:
- The bug may have been introduced in a later version, OR
- The demo has different configuration that avoids the issue
Expected Behavior
Characters should appear in the order they are typed, regardless of whether the preceding content was track-deleted.
Suggested Fix Area
The issue is likely in how the track changes extension calculates insert positions relative to track-deleted content. When all visible content is deleted (but still exists with trackDelete marks), the cursor anchor point for new trackInsert content appears to be miscalculated, causing every insert to go to position 1 instead of incrementing.
The docx-update full sync after each keystroke may also be resetting some state that affects cursor positioning.
Screencast.from.2026-01-24.18-07-05.webm
SuperDoc version (if relevant)
1.7.0
Additional context
Please try and confirm if issue exists with the superdoc's latest version. Thanks.