ianstormtaylor / slate

A completely customizable framework for building rich text editors. (Currently in beta.)
http://slatejs.org
MIT License
29.59k stars 3.23k forks source link

decorate not work well with ime input method #3162

Open Jokcy opened 4 years ago

Jokcy commented 4 years ago

Do you want to request a feature or report a bug?

bug

What's the current behavior?

Nov-27-2019 16-47-50

The problem which I found in 4x version still exist in 50 version. This time I drived into source code to find the reason.

The main reason is when I input the cursor locate at some decoration for example *123*, after I finish IME input, first of all the text will be placed in the span where *123* in. Then slate update the text tree, rerender, but based on text tree in slate, this decoration won't need to be update, because it's range never change. In slate the text is "123这", after decorate, *123* is still there. So it never rerender, but in the real dom, "这" has been added.

Jokcy commented 4 years ago

There are two ways to solve this problem:

  1. Prevent browser from insert text to the decorated node, which I guess is very difficult to do.
  2. Let the decorated node rerender.
Jokcy commented 4 years ago

Example here https://codesandbox.io/s/trusting-gagarin-ij22y

ianstormtaylor commented 4 years ago

What browser and operating system is this?

Jokcy commented 4 years ago

@ianstormtaylor macos and chrome, all latest.

Jokcy commented 4 years ago

Any idea about this problem? I tyied to solve this problem, it seems no other way except render the block every time since we can't prevent from editing and there is no better way to detect the decoration dom node changed.

Jokcy commented 4 years ago

@ianstormtaylor How about add this code to TextString component?

useEffect(() => {
    // console.log(ref.current)
    if (ref.current && ref.current.innerText !== text) {
      ref.current.innerText = text
    }
  })

This seems fix this problem, except it moves the cursor forward to the start of the TextString

Jokcy commented 4 years ago

@ianstormtaylor I want to mark a PR about this, but when I run test, I got a lot of error:

TypeError: children.filter(...).flat is not a function
      at jsx (../src/hyperscript.ts:99:5)
      at Object.<anonymous> (packages/slate/test/transforms/wrapNodes/split-inline/inline.js:10:7)
      at Module._compile (internal/modules/cjs/loader.js:688:30)
      at Module._compile (node_modules/pirates/lib/index.js:99:24)
      at Module._extensions..js (internal/modules/cjs/loader.js:699:10)
      at Object.newLoader [as .js] (node_modules/pirates/lib/index.js:104:7)
      at Module.load (internal/modules/cjs/loader.js:598:32)
      at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
      at Function.Module._load (internal/modules/cjs/loader.js:529:3)
      at Module.require (internal/modules/cjs/loader.js:636:17)
      at require (internal/modules/cjs/helpers.js:20:18)
      at Context.<anonymous> (support/fixtures.js:39:26)

How to fix this?

hdsuperman commented 3 years ago

same problem (code highlighting example):

v2-bce4bdf71868aea7c49d6f378d0cdf9a_hd

@ianstormtaylor @Jokcy

neko-neko commented 3 years ago

Same problem in current version, report here.

Environment

Slate Version: 0.65.3
Operating System: Mac, Windows
Browser: Chrome, Edge, Firefox

Safari seems to be working fine.