From 82315853a2ce64396f0379d81a96793c0432490e Mon Sep 17 00:00:00 2001 From: xfy Date: Tue, 7 Jul 2026 17:51:06 +0800 Subject: [PATCH] =?UTF-8?q?fix(tiptap):=20slash=20=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E5=8F=AF=E8=BF=90=E8=A1=8C=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=9D=97=E6=97=B6=E6=A8=A1=E6=80=81=E6=A1=86=E8=A2=AB=E7=AB=8B?= =?UTF-8?q?=E5=8D=B3=E5=85=B3=E9=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 斜杠菜单中按 Enter 选择「可运行代码块」时,openRunnableModal 在 同一个 keydown 事件处理中同步调用。模态框的 document keydown 监听 立即注册后,该 Enter 事件继续冒泡到 document 触发模态框的 Enter 处理——insert() → close(),模态框在同一 tick 内创建又销毁,用户 看不到配置弹框。 将 document.addEventListener("keydown", ...) 延迟到 setTimeout(0) 注册,确保触发事件完成传播后才开始监听。 --- libs/tiptap-editor/src/__tests__/runnable-modal.test.ts | 4 +++- libs/tiptap-editor/src/slash-command.ts | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libs/tiptap-editor/src/__tests__/runnable-modal.test.ts b/libs/tiptap-editor/src/__tests__/runnable-modal.test.ts index 51ab95b..6079fbc 100644 --- a/libs/tiptap-editor/src/__tests__/runnable-modal.test.ts +++ b/libs/tiptap-editor/src/__tests__/runnable-modal.test.ts @@ -142,9 +142,11 @@ describe('openRunnableModal', () => { expect(document.querySelector('.tiptap-runnable-modal')).toBeNull(); }); - it('Esc 关闭弹框(不插入)', () => { + it('Esc 关闭弹框(不插入)', async () => { const { editor, calls } = mockEditor(); openRunnableModal(editor); + // keydown 监听延迟注册(setTimeout(0)),需先 flush timer + await new Promise((r) => setTimeout(r, 0)); document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true })); expect(calls).toHaveLength(0); expect(document.querySelector('.tiptap-runnable-modal')).toBeNull(); diff --git a/libs/tiptap-editor/src/slash-command.ts b/libs/tiptap-editor/src/slash-command.ts index 8ab858c..2010c46 100644 --- a/libs/tiptap-editor/src/slash-command.ts +++ b/libs/tiptap-editor/src/slash-command.ts @@ -680,8 +680,12 @@ export function openRunnableModal(editor: Editor, editPos?: number, currentInfo? } } - document.addEventListener('keydown', onKeydown); document.body.appendChild(mask); + // 延迟注册 keydown 监听:openRunnableModal 可能在 slash 命令的 Enter keydown 事件处理中 + // 同步调用。若立即注册,该 Enter 事件继续冒泡到 document 时会被模态框的 onKeydown 捕获, + // 触发 insert() → close()——模态框在同一 tick 内被创建又被销毁,用户看不到。 + // setTimeout(0) 推迟到下一个宏任务,确保触发事件已完成传播。 + setTimeout(() => document.addEventListener('keydown', onKeydown), 0); updatePreview(); updateInsertEnabled(); langSelect.focus();