From 6054ca12176e6998cffa7304a2d97dd90c827f7b Mon Sep 17 00:00:00 2001 From: JasonOA888 Date: Tue, 10 Mar 2026 20:03:10 +0800 Subject: [PATCH] docs(page-controller): document contenteditable limitations and execCommand fallback ## Changes Based on @gaomeng1900's comprehensive testing feedback: 1. **Document known limitations** - Slate.js and Draft.js do not work with synthetic events - Draft.js: Cannot be supported via DOM manipulation (by design, unmaintained) - Monaco/CodeMirror: Require direct JS instance access 2. **Clarify tested editors** - Works: Quill, LinkedIn, simple contenteditable editors - Does not work: Slate.js, Draft.js 3. **Preserve execCommand as fallback** - execCommand works better for LinkedIn, Quill, and Draft.js - Kept as commented fallback (deprecated API) - Users can uncomment if synthetic events don't work Co-authored-by: gaomeng1900 --- packages/page-controller/src/actions.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/page-controller/src/actions.ts b/packages/page-controller/src/actions.ts index 9e0e339..707c7ea 100644 --- a/packages/page-controller/src/actions.ts +++ b/packages/page-controller/src/actions.ts @@ -114,7 +114,15 @@ export async function inputTextElement(element: HTMLElement, text: string) { await clickElement(element) if (isContentEditable) { - // (keydown) -> beforeinput -> mutation -> input -> (keyup) -> change + // For contenteditable elements, dispatch proper events to trigger framework listeners. + // + // IMPORTANT: This approach works for Quill, LinkedIn, and simple contenteditable editors, + // but does NOT work for Slate.js or Draft.js which require framework-specific handling. + // - Draft.js: Cannot be supported via DOM manipulation (by design, unmaintained) + // - Slate.js: Uses internal state that doesn't sync with DOM changes + // - Monaco/CodeMirror: Require direct JS instance access, not contenteditable path + // + // Event sequence: beforeinput -> mutation -> input -> change -> blur // Dispatch beforeinput + mutation + input for clearing if ( @@ -163,11 +171,16 @@ export async function inputTextElement(element: HTMLElement, text: string) { // blur() dispatches its own focusout event, so we don't need a duplicate element.blur() - // // Plan B: execCommand — triggers trusted native events for rich text editors + // Plan B: execCommand (deprecated but works better for some editors) + // Uncomment if synthetic events don't work for your use case. + // Tested to work with: LinkedIn, Quill, Draft.js + // Note: execCommand is deprecated and may be removed in future browsers. + // // element.focus() // document.execCommand('selectAll') // document.execCommand('delete') // document.execCommand('insertText', false, text) + // document.execCommand('insertText', false, text) } else if (element instanceof HTMLTextAreaElement) { nativeTextAreaValueSetter.call(element, text) } else {