facebookarchive / draft-js

A React framework for building text editors.
https://draftjs.org/
MIT License
22.56k stars 2.64k forks source link

Decorators with fixed-length ranges makes editing unstable #414

Open Soreine opened 8 years ago

Soreine commented 8 years ago

Hello, I have been struggling with decorators recently. When decorators decorate arbitrary spans of characters (that do not match words), editing those same spans results in weird behaviors from the editor.

Here is a Gist of a single HTML page with simple code to reproduce the issue. The Gist shows an editor with the first 10 characters of each block highlighted in red. Positioning the caret (represented by []) at the start of the text:

[]Accusantium libero ...

And typing ABC, results in this weird state:

ABACc[]cusanttiiium libero ...

Do decorators need to adapt to the editing in some ways ? Are there some rules I ignore about what can be decorated and what should not ?

Thank you for your time.

sophiebits commented 8 years ago

This just seems like a bug to me. Thanks for reporting.

johanneslumpe commented 8 years ago

The culprit is our editOnInput handler which is used for spellcheck changes mostly. It compares the length of the model's text with the one from the DOM. Since a decorator wraps its children within a DOM element, the length of that node's content won't match with what we see in the model (due to the decorator having a constant length). And this leads to corrupt state for normal text input as well as spellcheck changes within a constant length decorator because we use the delta between new and old text to figure out how to adjust the selection.

This issue affects all browsers except Firefox because there we rely on Firefox's internal selection state and do force update it.

This issue gets worse if we try to apply a spellcheck correction to a word whose first character is at the lower bound or whose last character is at the upper bound of the decorator. In Chrome that word will then be put into its own DOM node, thus really messing up our comparison.

hellendag commented 8 years ago

I think editOnInput is doing its job as expected here, and that the problem is the nature of this type of decorator. This seems very similar to the use case in #104 and #92. Specifically, I think https://github.com/facebook/draft-js/issues/92#issuecomment-189457952 is the problem.

aviraldg commented 8 years ago

I'm facing a related problem (I think.) With the cursor before the @ below, adding a character inserts it after the @:

screenshot from 2016-06-15 00-32-45

As you'd guess, the actual content here is just "@aviraldg:matrix.org testing"