Skip to content

fix: restore popup predictions on Reddit/Lexical contenteditable#274

Merged
bartekplus merged 4 commits intomasterfrom
fix/reddit-popup-stale-caret
Mar 6, 2026
Merged

fix: restore popup predictions on Reddit/Lexical contenteditable#274
bartekplus merged 4 commits intomasterfrom
fix/reddit-popup-stale-caret

Conversation

@bartekplus
Copy link
Owner

Problem

The suggestion popup did not appear on Reddit's Lexical-based editor when typing a character that triggers auto-capitalization (e.g. typing "p" → capitalized to "P"). Without the `capitalizeSentenceStart` grammar rule enabled, the popup worked fine.

Root Causes

1. Premature input event cancels fallback observer

Lexical fires the `input` event before its DOM reconciliation actually produces the text mutation. `shouldDeferContentEditableInputToFallback` now defers the input when text hasn't changed yet but the fallback is still inside its mutation-wait window.

2. Failed grammar edit corrupts selection state

When the grammar rule dispatches `insertReplacementText` `beforeinput`, `ContentEditableAdapter.replaceTextByOffsets` expands the selection to cover the replacement range `[0,1]`. If Lexical `preventDefault()`s without mutating the DOM, the non-collapsed selection is left behind — causing `resolveEditableCursorContext` to see empty `beforeCursor` and `afterCursor`. The original selection anchors are now restored when the host prevents the edit without changing text.

3. Prediction uses lowercase text after blocked grammar edit

When the grammar edit (e.g. capitalize w→W) cannot be applied to the DOM, `processEntryAfterEdit` now applies the intended text transformation and sends the prediction request directly with the capitalized text.

Testing

  • 4 new Reddit-specific tests covering sync/async DOM mutation, grammar + re-entrant input, and grammar + async scenarios
  • All 1088 tests pass across 64 files
  • Build succeeds

@bartekplus bartekplus force-pushed the fix/reddit-popup-stale-caret branch 3 times, most recently from 126b4e4 to 551c532 Compare March 6, 2026 19:40
Three issues prevented the suggestion popup from appearing on Reddit's
Lexical-based editor when typing a single character that triggers
auto-capitalization:

1. Premature input event cancels fallback observer
   Lexical can fire the input event before its DOM reconciliation
   produces the actual text mutation.  shouldDeferContentEditableInputToFallback
   now defers the input when the text hasn't changed yet but the
   fallback is still inside its mutation-wait window.

2. Failed grammar edit corrupts selection state
   When the grammar rule dispatches insertReplacementText beforeinput,
   ContentEditableAdapter.replaceTextByOffsets expands the selection to
   cover the replacement range.  If Lexical preventDefault()s without
   mutating the DOM, the non-collapsed selection is left behind,
   causing resolveEditableCursorContext to see empty beforeCursor and
   afterCursor.  The original selection anchors are now restored when
   the host prevents the edit without changing text.

3. Prediction uses lowercase text after blocked grammar edit
   When the grammar edit (e.g. capitalize w->W) cannot be applied to
   the DOM, processEntryAfterEdit now applies the intended text
   transformation and sends the prediction request directly with the
   capitalized text, bypassing the corrupted cursor-context resolution.
@bartekplus bartekplus force-pushed the fix/reddit-popup-stale-caret branch from 551c532 to a540b4e Compare March 6, 2026 19:42
Pressing Enter in a contenteditable element (e.g. CKEditor) always
moves the caret to a new block, making existing predictions invalid.
Previously the popup lingered until the fallback reconcile timer fired
(~140ms) because:

1. shouldDismissSuggestionsOnKeydown did not include 'Enter'
2. selectionchange fired but reconcileEntrySelection skipped the
   context check (lastKeydownKey was 'Enter', not null)

Fix: in onElementKeyDown, after the standard dismissal check, add an
explicit guard that calls dismissEntry whenever Enter is pressed on a
contenteditable and was not consumed by autocomplete.  The insert-
fallback path still runs so that predictions for the new line are
scheduled normally.

Add E2E regression test: CKEditor popup dismisses immediately when
Enter is pressed.  Also register the new behavior in coverage-matrix
and coverage-baseline-ids.
@bartekplus bartekplus merged commit 46ffb57 into master Mar 6, 2026
13 of 14 checks passed
@bartekplus bartekplus deleted the fix/reddit-popup-stale-caret branch March 6, 2026 20:52
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