Skip to content

fix: prevent unwanted block split during IME composition on WKWebView#89

Merged
j4rviscmd merged 3 commits intomainfrom
fix/ime-enter-fix
Mar 27, 2026
Merged

fix: prevent unwanted block split during IME composition on WKWebView#89
j4rviscmd merged 3 commits intomainfrom
fix/ime-enter-fix

Conversation

@j4rviscmd
Copy link
Copy Markdown
Owner

Summary

  • Add imeCompositionGuard BlockNote extension that prevents unwanted line breaks during IME composition on Tauri's WKWebView
  • Block structural ProseMirror transactions (ReplaceStep with structure: true and ReplaceAroundStep) that WebKit generates when it temporarily empties a list item during IME text commitment
  • Clean up orphaned DOM block elements after composition and force ProseMirror to re-render from its authoritative state

Problem

On WKWebView, when the user commits IME text without conversion on an empty list item (e.g., typing "あ" + Enter), the browser temporarily removes the composition text via deleteCompositionText, which empties the paragraph. WebKit then splits the list item (exiting an empty list item). When the committed text is re-inserted via insertFromComposition, it lands in the new block, causing an unwanted block split.

This does not occur when text already exists in the list item, because the paragraph never becomes empty.

Fix

A layered defence approach:

  1. filterTransaction blocks structural steps during composition and also blocks the duplicate text insertion that follows (caused by position mismatch from the blocked structural step)
  2. DOM cleanup on compositionend removes orphaned block container elements and forces ProseMirror to re-render the DOM from its state
  3. contentEditable = 'plaintext-only' during composition prevents block-level element creation (covers "with conversion" case)
  4. keydown capture and handleKeyDown prop block Enter during the composing window as additional safety

Test plan

  • Type "あ" in an empty list item (* ) and press Enter without conversion → no line break, text "あ" is committed
  • Type text in a list item (* こんにちは) and press Enter without conversion → no line break (existing behavior preserved)
  • Select a candidate from IME and press Enter → no line break (existing behavior preserved)
  • Press Enter with IME off → normal block split (existing behavior preserved)
  • Cmd+Enter / Ctrl+Enter → normal behavior (modifier keys not blocked)

🤖 Generated with Claude Code

j4rviscmd and others added 2 commits March 28, 2026 01:24
On WebKit, committing IME text without conversion on an empty list
item triggers a DOM-level block split that ProseMirror's observer
converts into unwanted structural transactions.  A layered defence
blocks those transactions, cleans up orphaned DOM nodes, and forces
ProseMirror to re-render from its authoritative state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@j4rviscmd j4rviscmd added the bug Something isn't working label Mar 27, 2026
Apply biome auto-fixes: sort imports in index.ts and fix formatting
(trailing commas, line wrapping) in imeCompositionGuard.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@j4rviscmd j4rviscmd merged commit 0cd66f6 into main Mar 27, 2026
2 checks passed
@j4rviscmd j4rviscmd deleted the fix/ime-enter-fix branch March 27, 2026 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant