Files
mnote/bugs/05-editor-mainline/done/5-39-block-menu-delete-undo-regression-v1.md
T

3.2 KiB
Raw Blame History

5-39 Block menu 删除后 Ctrl+Z 不恢复目标块

创建时间:2026-05-25 状态:done Owner05-editor-mainline

现象

node scripts/task489-block-menu-delete-undo-smoke.js 连续两次失败。块菜单删除 Beta block 成功,但随后 Control+Z 未恢复目标块,最终等待 Beta block 重新出现超时。

失败证据:

  • tmp/task489-block-menu-delete-undo-smoke/result.json
  • tmp/task489-block-menu-delete-undo-smoke/failure.png

当前 result 摘要:

{
  "ok": false,
  "states": [
    { "step": "opened", "text": "Block Undo\n\nAlpha block\n\nBeta block\n\nGamma block" },
    { "step": "deleted", "text": "Block Undo\n\nAlpha block\n\nGamma block" }
  ],
  "error": "page.waitForFunction: Timeout 30000ms exceeded."
}

初步判断

失败点不是删除动作本身,而是删除后的 undo 历史不可恢复。当前代码已经调用 editor_runtime::history_safe_commands::delete_top_level_block_with_history(&editor, block_index),需要继续核实:

  • delete_range(range) 是否真的进入 Tiptap history。
  • 删除后 sync_persisted_editor_command(...) 是否触发了会清空 undo history 或重建 editor state 的路径。
  • 失败是否与焦点丢失有关;需要用最小浏览器复现确认点击 editor 后再 Control+Z 是否能恢复。

根因

块菜单按钮点击后,删除命令先通过 Tiptap history-safe delete_range 路径删除目标块,history 本身仍可用;浏览器诊断确认删除后点击 editor 再 Control+Z 可以恢复 Beta block。真正断点是删除菜单关闭期间焦点短暂落到 BODY,原 smoke 在焦点恢复前立刻发送 Control+Z,快捷键没有稳定送到 Tiptap editor,表现为删除成功但撤销不恢复。

修复

  • 删除菜单项 mousedown 阶段阻止默认焦点转移,减少按钮卸载后焦点落回 BODY 的窗口。
  • 在块菜单删除成功、关闭菜单状态后,异步补一次 editor.focus(),确保正常用户操作后的键盘撤销进入 ProseMirror。
  • BODY 短暂持有焦点时,只兜底转发 Ctrl/Cmd+ZCtrl/Cmd+YShift+Ctrl/Cmd+Z 到当前 editor,覆盖 smoke 中删除后立即按撤销的竞态。
  • 同批拆出 editor_runtime/block_menu_document.rs,隔离 legacy 顶层块 JSON helper;当前运行路径仍优先使用 history-safe command,不回退到 HTML 整文替换删除。

验收

  • cargo fmt --manifest-path rust/Cargo.toml --all --check 通过。
  • cargo check --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml 通过。
  • cargo build --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml --target wasm32-unknown-unknown --release 通过,并已执行 wasm-bindgen 更新 island wasm。
  • node scripts/task489-block-menu-delete-undo-smoke.js 通过。
  • node scripts/task488-local-attachment-link-delete-undo-smoke.js 通过。
  • 不得回退到 HTML 整文替换删除路径。

未覆盖

  • cargo test --manifest-path rust/spikes/leptos-tiptap-spike/Cargo.toml block_menu_document -- --test-threads=1 当前被既有 STYLE 测试编译错误阻断,错误为 cannot find value STYLE in this scope,未进入本次新增 helper 测试。