Unexpected behavior when pressing Enter - Safari, mobile

Hello! I found this unexpected behavior when I tested my app on mobile in the safari browser. iPhone 11 pro

Steps for reproducing: 1. add a heading(H1, H2, H3, etc) 2. Add some text or leave it blank 3. Press enter

Expected behavior: 1. creating a new line 2. cursor should stay at the newly created line

What happened: 1. new line was created 2. cursor moved to the start of next line after newly created

This bug you can reproduce on your example editor on the main site.

On this gif, you can see Xcode emulator iPhone 11 pro but on real the real iPhone 11 pro the same behavior

Is there a chance this will be fixed?


I can confirm this can also be reproduced in Mac safari by entering the responsive mode and selecting iPhone 8 Plus.

I tried this in Safari responsive mode, but couldn’t reproduce it there. Haven’t tried on an actual iPhone yet.

I noticed this behavior that seems to have been introduced in iOS 14, but have only been able to reproduce it in our application-specific nodes, not in the basic ProseMirror schema’s nodes.

It seems like the selection gets updated in the browser differently than it used to, resulting in ProseMirror reading the selection change and emitting that transaction before detecting an enter being inserted (using custom iOS enter handling).

I’ve been working around it by ignoring the transaction that sets the selection too soon:

const shouldSkipIosEnterTransaction = (view, transaction) => {
  if (!isIOS14OrLater) return false;

  return view && transaction.selectionSet && !transaction.docChanged &&
    // This matches the checks in prosemirror-view, where an lastIOSEnter is set along with a 200ms
    // timer that fires the handleKeyDown (if nothing cancels it in the interim
    (view.lastIOSEnter > Date.now() - 225);

The isIOS14OrLater check is webkit_version > 604, as iOS 14 appears to have shipped with webkit 605.

This patch to prosemirror-view should solve this. The problem was that the regular iOS enter hack wasn’t kicking in because the DOM structure created in this case caused ProseMirror to not treat the new block as a parseable node at all, returning from the DOM change code before even checking for the iOS enter hack.


Thanks for your work!
I can’t test it right now but I think everything works fine. I will let you know if there are any problems. Thanks!