ProseMirror / prosemirror

The ProseMirror WYSIWYM editor
http://prosemirror.net/
MIT License
7.76k stars 337 forks source link

Japanese IME input issue with stored marks in ProseMirror editor #1494

Open r1cep opened 2 weeks ago

r1cep commented 2 weeks ago

Bug Description

When using IME to input Japanese characters with the ProseMirror editor's marks stored, the cursor is positioned to the left of the input character.

Steps to Reproduce.

  1. open https://prosemirror.net/ in Chrome
  2. Press the bold or emphasis button.
  3. Type Japanese characters in the IME.

https://github.com/user-attachments/assets/b8651960-201b-46ba-bf63-c5594b80a2fc

Browser Used

Chrome

Expected Behavior

The cursor is positioned to the right of the character you type.

Additional Context (Optional)

I've print debugged the issue at hand, and it seems that the result of the relevant Document.getSelection method is different between Chrome and Firefox.

https://github.com/ProseMirror/prosemirror-view/blob/5c33b883d39d7d40097e1fcdf17f543d18ad502a/src/index.ts#L498-L501

Table of results of executing the relevant Document.getSelection including bold in storedMarks

browser anchorNode.parentElement anchorOffset
Chrome p 0
Firefox b 1
Safari b 1

https://github.com/ProseMirror/prosemirror-view/blob/5c33b883d39d7d40097e1fcdf17f543d18ad502a/src/domchange.ts#L15-L25

Modifying the above parseBetween function as follows will solve this issue, but I am not sure if this is the right way to do it.


  function parseBetween(view: EditorView, from_: number, to_: number) {
    let {node: parent, fromOffset, toOffset, from, to} = view.docView.parseRange(from_, to_)

    let domSel = view.domSelectionRange()
    let find: {node: DOMNode, offset: number, pos?: number}[] | undefined
    let anchor = domSel.anchorNode
    if (anchor && view.dom.contains(anchor.nodeType == 1 ? anchor : anchor.parentNode)) {
-     find = [{node: anchor, offset: domSel.anchorOffset}]
+     find = [{ node: anchor, offset: browser.chrome && anchor.nodeType !== 3 ? domSel.anchorOffset + 1 : domSel.anchorOffset }]
      if (!selectionCollapsed(domSel))
        find.push({node: domSel.focusNode!, offset: domSel.focusOffset})
    }
marijnh commented 2 weeks ago

It appears Chrome is reporting a different selection (via getSelection) than it is actually displaying. We've had some issues like that before (see also #41467501, which still hasn't really gotten taken seriously on the Chrome side). What I am seeing is that the cursor is moved to the proper place after you confirm the composition with Enter. As such, does this impact actual editing, or is it just producing a visual discrepancy with the cursor being drawn in the wrong spot?

r1cep commented 2 weeks ago

As such, does this impact actual editing, or is it just producing a visual discrepancy with the cursor being drawn in the wrong spot?

Yes, there are cases that affect the actual editing.

https://github.com/user-attachments/assets/3bdb8b9b-7d4f-442d-8297-ea820530edaa

The video above is an example.