Skip to content

feat(editor): expose imperative undo/redo history control - #149

Draft
seonghobae wants to merge 22 commits into
mainfrom
feat/imperative-history-control
Draft

feat(editor): expose imperative undo/redo history control#149
seonghobae wants to merge 22 commits into
mainfrom
feat/imperative-history-control

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Purpose

Implement #148 as a bounded host-control surface for the same undo/redo commands already owned by Inkspan's toolbar/editor history extensions, while making retained host handles consistently fail closed once the underlying TipTap editor has been destroyed and keeping user-facing history commands inert while the editor is read-only.

Test-first lineage

  • Protected base and current live protected tip: main@50ac98cfa0ad9e8dd75f93ca437a5679fed4d804.
  • Initial API RED head 1d08f70210e5abdd68e2d83f4096117eab389973 proved the stable handle lacked canUndo / undo / canRedo / redo while the editor already owned history commands.
  • Lifecycle RED Inkspan: fix build defect, bundle offline multilingual fonts, product branding #1 2fc4d9f83c1405697b23402689546d4a48e880c2, CI 31414556067, build/test 93540362772, proved a retained destroyed-editor handle still returned stale document state.
  • Lifecycle RED Inkspan: AI-authored Word/Excel/PowerPoint #2 554140d40035d5af4f006ad123d3bcdb5b55d261, CI 31415215254, build/test 93542500162, proved revision/evidence/restore paths still retained stale editor authority after destruction.
  • Packaging RED exact head 836a72220ca66f390f660fb3eb71eebfaa84b621, CI 31418632930, build/test 93553758656, failed the strict packed TypeScript consumer because it did not exercise the four new public history operations.
  • Read-only RED exact head d7ead2540d91cfbb0b64319946e554eab1119b44, CI 31422150835, build/test 93565228497, reproduced a real accessibility/behavior defect: after a real edit followed by editable={false}, handle.canUndo() incorrectly remained true and user-facing imperative history could still mutate the document.
  • Root-cause source fix e752891647cfd2341f362a70dcfbc029f8294e4f gates only the four user-facing history operations through an active-and-editable editor; trusted host-control mutators keep their existing programmatic authority.
  • Documentation commit 819415422e1bc67edbf75ece767d3b39f737d7d1 records the read-only/history authority boundary as active-PR truth.
  • Current head e6278289c47a54f97d450e7dad857f1397ebbe7b adds the non-documentation handoff proof that read-only history is not consumed: after editability is restored, the same undo remains available and succeeds.

Implemented boundary

  • expose canUndo, undo, canRedo, and redo through the currently registered TipTap history commands;
  • return false from all four operations while editable={false} without consuming history, then expose the preserved history again when editability returns;
  • preserve collaboration mode's Yjs-aware history rather than enabling duplicate local StarterKit history;
  • centralize editor-lifecycle validity so getEditor() returns null once the editor is destroyed;
  • make retained-handle reads, snapshots, envelope serialization/revisions, selection/text-position evidence, validation, restores, and document/content mutators fail closed or no-op consistently after destruction;
  • compile the four new history operations through the packed public TypeScript declarations; and
  • add no persistence, durable-save, audit, authorization, transport, credential, model, database, provider, room, or host-policy authority.

Exact-head proof

For unchanged exact head e6278289c47a54f97d450e7dad857f1397ebbe7b:

  • CI run 31422683181: success;
  • Security Scan run 31422683243: success;
  • SAST Semgrep run 31422683184: success;
  • CI build/test checked out the exact head, passed 143 test files / 823 tests, and passed the new four-test imperative-history suite including read-only preservation;
  • exact owned-production V8 coverage is 100% statements / 100% branches / 100% functions / 100% lines, including src/components/useEditorHandle.ts;
  • library build, strict packed-package TypeScript/ESM/CommonJS/SSR/subpath consumer verification, demo build, cross-engine Playwright evidence, and Office Python 3.11–3.14 test/branch-coverage/docstring/wheel/package gates passed;
  • fresh formal-review inspection shows no submitted reviews; and
  • fresh review-thread inspection shows no unresolved inline threads.

The build/test log also surfaced the pre-existing collaborative native-form reset React act(...) warning in unchanged test code. It is isolated in Draft PR #153 from protected main as a test-harness quality lane rather than being folded into this feature branch. That diagnostic did not fail this exact-head product test/coverage/package gate.

Automated/model status is not represented as qualifying independent formal approval. Any subsequent head movement invalidates this proof and must be revalidated.

Integration dependency

The implementation is exact-head gate-clean, but protected main@50ac98cfa0ad9e8dd75f93ca437a5679fed4d804 remains the exact 0.6.0 stable release candidate tracked by #118. Keep this PR Draft and do not merge while that registry operational-acceptance boundary remains unresolved, because advancing protected main would invalidate the release workflow's recorded stable-candidate identity. Revalidate live main, release/tag state, exact head, review state, and live policy immediately before any eventual readiness or merge transition.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

CwlEditorHandlecanUndo, undo, canRedo, redo 메서드를 추가했습니다. 구현은 파괴된 편집기를 제외합니다. 편집기가 없으면 관련 메서드는 false를 반환합니다. 단일 편집기와 협업 편집기에서 동작을 검증했습니다.

Changes

Undo/Redo Handle API

Layer / File(s) Summary
Handle 계약 및 구현
src/types.ts, src/components/useEditorHandle.ts
CwlEditorHandle에 undo/redo 상태 조회 및 실행 메서드를 추가했습니다. getEditor는 파괴된 편집기를 반환하지 않습니다. 실행 메서드는 편집기에 포커스를 설정합니다.
핸들 동작 검증
src/components/CwlEditorHistoryHandle.test.tsx
실제 CwlEditor에서 콘텐츠 변경 후 undo와 redo를 검증했습니다. 활성 편집기가 없거나 destroy된 공유 핸들의 메서드가 false를 반환하는지 검증했습니다.
협업 이력 검증
src/collaboration/CollaborativeCwlEditor.test.tsx
두 에디터에서 canUndo, undo, canRedo, redo API를 사용합니다. undo/redo 결과와 추가 undo 가능 상태가 원격 에디터에 전파되는지 검증합니다.

Estimated code review effort: 3 (보통) | ~20분

Possibly related issues

  • ContextualWisdomLab/inkspan 이슈 148 — imperative CwlEditorHandle undo/redo API와 편집기 수명 주기 및 협업 동작 테스트를 다룹니다.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 에디터에 imperative undo/redo history 제어 기능을 공개하는 PR의 주요 변경 사항을 정확하고 간결하게 설명합니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/imperative-history-control

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae
seonghobae marked this pull request as ready for review August 10, 2026 15:13
@seonghobae
seonghobae marked this pull request as draft August 10, 2026 18:01

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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