-
Notifications
You must be signed in to change notification settings - Fork 88
Fix a selection issue where the CodeMirror is the first element in ProseMirror #78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
(You can test this in CodeSandbox by swapping the |
|
(The issue seems to be Chromium-only, btw.) |
|
(And it seems to be new: in BrowserStack, I can only repro it starting Chrome 135+. Could be a browser bug, after all!) |
|
Filed upstream: https://issues.chromium.org/issues/474377386. Thank you for being my rubber duck :D Let’s see what Chromium responds. |
|
I find this patch somewhat scary. It is entirely possible for an editor to receive focus while the selection is elsewhere in the document, and this would cause the library to ignore such focus events entirely, allowing focus-tracking code to get confused. It seems possible to work around this problem by adding any kind of inline element in front of the inner editor. Would adding a kludge like |
|
Oh, that’s clever! That seems to solve Cmd+A (CodeSandbox), but it actually does cause more issues haha. With this workaround, Safari stops showing the Cmd+A highlight at all, and in both Chrome and Firefox, pressing ↑ gets the cursor stuck in the zero-width space div: CleanShot.2026-01-09.at.15.44.04.mp4You can work around that by also adding a Another thing I noticed: having CodeMirror first in ProseMirror also seems to break Cmd+C? (LMK if you’d like me to raise a separate issue for this.) For example, in the original demo, if you Cmd+A in Safari (which works) and then Cmd+C, the only thing the browser copies is The zero-width div workaround that you suggested solves it, but at the cost of the above issues. |
Filed a fix for that: #79 |
Ughhh, you're right. Nesting editable elements is a space where browsers do some really bizarre things. I'm still worried that the fix is worse than the problem here. Even if we ignore that focus event, it seems the browser does put the actual focus on the inner editor, which is clearly not what you want. So maybe a kludge in ProseMirror that detects this situation right after selecting all, and forces the focus back to itself, is a more promising direction. |
When CodeMirror is the first element in ProseMirror, and you press Cmd+A in ProseMirror, the selection doesn’t get applied (or, rather, applies for a single frame). Instead, the CodeMirror element steals the focus.
Repro: CodeSandbox, demo:
CleanShot.2026-01-08.at.20.23.32.mp4
Cause: This seems to boil down to an interaction between ProseMirror’s selection logic and CodeMirror being contenteditable itself. When ProseMirror handles a Cmd+A event, it calls
domSel.collapse()before callingdomSel.expand():https://github.com/ProseMirror/prosemirror-view/blob/76c7c47f03730b18397b94bd269ece8a9cb7f486/src/viewdesc.ts#L464-L468
domSel.collapse()makes the selection collapse to a single point – at the beginning of the editorCodeMirror– so when that happens, the browser triggers the nativefocusevent on it.Solution: This PR attempts to fix the issue. The fix seems to work, but maybe there’s a better place for it, or some edge cases I don’t know about (I’m not very familiar with contenteditable gotchas).