Skip to content

feat(core): group undo steps by browser task - #203

Draft
ilyamore88 wants to merge 2 commits into
claude/undo-grouping-proposalfrom
claude/undo-group-by-task-impl
Draft

ilyamore88 wants to merge 2 commits into
claude/undo-grouping-proposalfrom
claude/undo-group-by-task-impl

Conversation

@ilyamore88

@ilyamore88 ilyamore88 commented Oct 10, 2026 •

Copy link
Copy Markdown
Member

What

This PR implements undo-group-by-task, proposed in #201. It is the middle of the stack: #201 (proposal) ← this ← #191 (clipboard paste proposal).

UndoRedoManager (core)

  • Task buffering. Local model events are buffered for the current browser task. The task end is detected with setTimeout(0), which runs after the task and its microtasks.
    • One event in the task (a keystroke) uses the existing consecutive-text batching, so typing is unchanged.
    • Several events in the task (Enter split, paste) close the open batch and start a new step together. Typing after such a step may still continue it under the text rule, so "replace selection and keep typing" is one step. Typing before it never merges in.
  • Buffer handling. undo() and redo() record buffered events first. destroy() clears the task timer and drops the buffer.
  • Fix: block undo/redo. Block-level events carry a single serialized block, but EditorDocument.insertData/removeData expect a list for a BlockIndex. Undoing or redoing any block add or remove threw data.forEach is not a function. #apply now wraps the block in a one-item list.

Tests

  • Unit tests for every spec scenario.
  • The existing "should NOT batch …" tests now call endTask() between events that model separate user actions.
  • UndoRedoManager.integration.spec.ts (real model and BlocksManager): a mid-paragraph Enter undoes in one step, and a split that adds a block undoes and redoes without AlreadyExistingKeyError.

Docs

  • docs/collaboration.md and docs/diagrams/undo-redo-flow.mmd describe task grouping, and note that collaboration-manager doesn't group by task yet.

tasks.md is fully checked in this PR.

Verification

  • packages/core: 197 tests pass, lint:ci is clean, and the build succeeds.
  • Stryker on UndoRedoManager.ts scores 86%.
    • The one survivor in the new code is equivalent: scheduling the task timer on every event behaves the same as scheduling it once.
    • The other survivors are in code this PR doesn't change.
  • Root yarn lint passes. Root yarn test passes except collaboration-manager/CollaborationManager.spec.ts, which fails to load locally on Node 20.9 (WebSocket is not defined). That package doesn't depend on core.

Notes for reviewers

  • Archive gate. The OpenSpec archive gate will fail here until the change is archived, because tasks.md is complete. Archive it before merging, or label the PR openspec:defer-archive while the stack is under review.
  • Behaviour change. Any action that makes several model changes in one task now undoes in one step.

UndoRedoManager buffers the local model events of the current browser task
and records them when the task ends (setTimeout 0). A single event keeps the
consecutive-text batching, so typing is unchanged; several events from one
task (Enter split, paste) close the open batch and start a new step together.
undo()/redo() record buffered events first, destroy() drops them.

Also wrap block-level event data in a list when re-applying it: block events
carry one serialized block while the model inserts/removes blocks as lists,
so undoing or redoing any block add/remove used to throw.
@ilyamore88
ilyamore88 added this pull request to stack #204 October 10, 2026 12:26
@ilyamore88 ilyamore88 changed the title claude/undo group by task impl feat(core): group undo steps by browser task Oct 10, 2026
@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Unit Tests

Package Coverage Delta
@editorjs/core 73.87% +0.73% 🟢
@editorjs/editorjs 100% 0% ⚪️

Mutation Tests

Package Mutation score Dashboard URL
@editorjs/core 86.14% 🟢 Dashboard

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant