ProseMirror / prosemirror

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

HandleTextInput not called for type over or text replacement. #1307

Open kashuSpext opened 2 years ago

kashuSpext commented 2 years ago

Issue

So i'd set up the handleTextInput plugin in a way that it doesn't allow any sort of direct text input in the editor, but still allows copy and paste. This was the case when i was still on prosemirror-view@1.10.0. After upgrading to prosemirror-view@1.27.2 for typescript support and also upgrading all the other prosemirror packages, the handleTextInput plugin prop does not work the same way anymore.

So currently - handleTextInput does not get called for type-over or text replacement. That is, if i select some text and type anything, the text gets replaced, but handleTextInput is not called. However even this is sort of inconsistent, I'm not sure how but it does get called if i select text that spans multiple paragraphs. (The doc structure i've used consists of text nodes where each word is a text node and a paragraph node contains all the text nodes, and the document is divided into multiple paragraph nodes).

It isn't really possible for me to provide a glitch or codepen with the issue's working, but here's a screen recording you can check to see the issue.

Steps to reproduce:

  1. setup a doc that has a hierarchy of 'paragraph' > 'text' (where each word is a text node)
  2. Select some text on the editor
  3. Click any letter or number key

Expected behaviour:

Browser: Brave (Chrome 103) on MacOS Catalina

If this information does not help and you need some more details, please let me know.

marijnh commented 2 years ago

If I set up an editor with the example schema, which has text inside paragraphs, and add a handleTextInput prop that logs its arguments, selecting a bit of text within a paragraph and press a letter, I do see my handler get called.

kashuSpext commented 2 years ago

Alright i suppose in a default example schema it'll work. I will try to recreate the issue on a codepen and get back to you so we get more clarity in what caused this.

Nantris commented 1 year ago

@marijnh this isn't exact situation as OP but I have a case where handleTextInput never fires in Chrome (but does in Firefox) using TipTap's codeblock with highlighting.

You can reproduce it here by selecting the entire codeblock and trying to type a single character over it. Instead, nothing will appear. I went to try to work around this via handleTextInput and found it doesn't fire. If this seems addressable I'd be happy to create a more complete repro.

I filed this related issue with TipTap, but the problem appears to be with ProseMirror itself: https://github.com/ueberdosis/tiptap/issues/4255

Nantris commented 1 year ago

The problem seemingly occurs because typeOver is not set, so it isn't handled as a typeOver in these lines:

https://github.com/ProseMirror/prosemirror-view/blob/f6d96de9f2714bcf97d6ca9b0906d8750a142d1b/src/domobserver.ts#L174-L184

Specifically in this event the generated mutations list looks like this:

image

As a solution, I suggest that we check the removedNodes in each childList type event when at least one of the MutationRecords is of type characterData. Then we'd check each other MutationRecord's removedNodes to ensure the only nodes removed were br tags. If that's the case, we should set the typeOver to true.

Does this seem reasonable to you @marijnh?

marijnh commented 1 year ago

Can you create a reproduction that doesn't involve Tiptap?