-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
fix: Broken text replacement feature (macOS-only) #5261
fix: Broken text replacement feature (macOS-only) #5261
Conversation
✅ Deploy Preview for tiptap-embed ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
@bdbch A lot of tests are breaking because the new implementation doesn't seem to play well with |
Hm. This change does really feel like an edge case and I'm not super confident in the change. Could we not account for the positions to make sure that they are out of range? |
For what it's worth, we've been using this change on Todoist for almost 2 months now, and so far we haven't had any bug reports related to the change. That said, I'd be happy if someone else could have a look and find a different solution, but personally, I have no idea how that looks like (I've already spent a lot of time on it, and this was my best shot). |
5e352d2
to
b6ed732
Compare
|
b6ed732
to
eb836a7
Compare
119e4a4
to
07980c4
Compare
@nperez0111 Any thoughts on how to better fix this issue? |
Hey @rfgamaral been looking at this now, So, I think that we should be fixing the root cause instead of trying to make a workaround like this. The root cause is that what got inputted & what exists in the editor are different. & I'm unsure that the macos text replacement feature let's you really do anything about this. I'm not sure what a proper resolution is for this other than what you've come up with Separately, I took a look at what remirror does (they seem to just not apply the text in this situation), I noticed that they are trying to preserve the initial stored marks https://github.com/remirror/remirror/blob/b3c8b02f7562afb7de08b4308a3302a500386d33/packages/remirror__core-utils/src/prosemirror-rules.ts#L213 and I think that we should be doing that too actually. |
But going that route, the macOS text replacement feature will cease to work, right? |
I think the storedMarks is completely separate & orthogonal to this, I just saw it in trying to understand how they implemented it. In their editor, the text will replace, but not match the mark, which I honestly think is acceptable. I think that the main goal here should be to not crash the editor and a secondary goal can be to get it to be marked up properly. The main issue that I have with your solution is:
|
I can understand that, although, to be fair, the editor doesn't crash per se 😅, it continues to work despite the error on the console.
For what it's worth, I can tell you that we've been using this workaround for a couple of months now, and we have a huge user base where some users use IMEs, and we also support lots of different languages. So far, we haven't had anyone complaining about issues in the editor related to this particular change.
Firefox seems to fire it as expected (ref), and I'm sure Chromium-based browsers will as well.
I don't think it's that obscure... I mean, we've reached the conclusion that the main issue is "what got inputted & what exists in the editor are different", and that's an issue caused by handling input rules with If we go to the ProseMirror source (ref), we can see that |
Alright, I'm convinced by your argument. I do need for these tests to pass though. @bdbch you know cypress better than I do, can we get this to work? Also would appreciate your input on what was discussed here |
I wasn't trying to convince you per se 😅, just sharing my point of view. Ultimately, this is your call, of course 👍 |
9fcd057
to
b3d9ba0
Compare
@nperez0111 The test pipeline is still running, but I should've fixed all Cypress tests. It required the usage of |
b3d9ba0
to
900461d
Compare
Thanks for this, didn't realize that you had a library in mind that worked for this. |
900461d
to
c237e23
Compare
It's what we also use internally to solve issues like this (i.e. when |
c237e23
to
5d57bd6
Compare
1502aeb
to
5f76c75
Compare
5f76c75
to
f042222
Compare
f042222
to
e918404
Compare
@nperez0111 @bdbch @svenadlung Finally got all tests to pass, feel free to review. |
@@ -95,3 +97,11 @@ Cypress.Commands.add( | |||
return subject | |||
}, | |||
) | |||
|
|||
Cypress.Commands.add('resetEditor', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
smart!
cy.get('.tiptap .react-component .content div') | ||
.realType('Hello World! This is **bold**.') | ||
cy.get('.tiptap .react-component .content div') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just so I understand better, does realType not support chaining or is this a timing thing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm no Cypress expert but:
- I initially tried with chaining, but it didn't work
- All our internal tests don't chain the
.real*
calls - Examples on the official repo do use chaining
- But like I said, I couldn't make it work...
@@ -4,44 +4,47 @@ context('/src/Examples/InteractivityComponentContent/React/', () => { | |||
}) | |||
|
|||
it('should have a working tiptap instance', () => { | |||
cy.get('.ProseMirror').then(([{ editor }]) => { | |||
cy.get('.tiptap').then(([{ editor }]) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Appreciate you adding consistency here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a fantastic contribution @rfgamaral I really appreciate the work you put into this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm! ty @rfgamaral
@rfgamaral I'm sorry to report this change breaks our existing input rules, and further breaks |
This was not released with 2.7 due to the potential breaking change |
Just FYI I noticed this is listed in the 2.7.0 change list despite not being included. Sorry again to have been the bearer of bad news. It's a worthwhile goal to get |
Changes Overview
Fixes #3602.
Implementation Approach
This input rules feature currently works by handling the
handleTextInput
event, which is fired whenever the user directly inputs text. However, it's important to note that this handler is called before the input is applied, which is basically the source of the issue. Because of that, when a macOS text replacement happens, the positions used by the logic that handles input rules, don't match the editor state, and the editor breaks. This is an oversimplified version, but if you are interested to know more, I've written about it here.The solution implemented in this PR's patch replaces
handleTextInput
withhandleDOMEvents
for input rules, which allows us to handle thekeyup
event. Such event is better suitable here because it will fire after the user directly inputs text, which means the editor state will be as updated as it can be, and all position calculations will match that state.Testing Done
I've patched our app using Tiptap with the exact changes in this PR, and our millions of users have been using it for 3 weeks now, and we haven't received any tickets regarding editor issues since then. I'd say this change was a success.
Verification Steps
See the reproduction steps in the referenced issue that this PR fixes.
Additional Notes
Checklist
feat: Implement new feature
orchore(deps): Update dependencies
)