-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
Handle text replacements explicitly #3807
Conversation
faa93f4
to
44c9e01
Compare
(Sorry if this is out of scope of this PR, I can create a separate issue if that's the case) In #2096 which is closed by this PR, a comment #2096 (comment) mentioned the handling of It seems that there's another case where Reproduction:
<!DOCTYPE html>
<html>
<body>
<div class="ql-editor" contenteditable="true" spellcheck="true">
<p style="font-size: 18px">
<strong style="color: rgb(0, 128, 0); font-size: 18px"
>Styled paragraph (empty line below)</strong
>
</p>
<p style="font-size: 18px">
<strong style="color: rgb(0, 128, 0); font-size: 18px"><br /></strong>
</p>
<h1>List item</h1>
<ol>
<li>
<span class="ql-ui" contenteditable="false"></span>
<span style="color: rgb(102, 204, 132); font-size: 36px"
>List with inline style (empty line below)
</span>
</li>
<li>
<span class="ql-ui" contenteditable="false"></span>
<span style="color: rgb(102, 204, 132); font-size: 36px">
<br />
</span>
</li>
</ol>
</div>
</body>
</html>
|
I don't feel it's possible to have |
@luin Yes, though it's not the default behavior of quill (but it's a hack to restore the native contenteditable behavior) Demo: https://stackblitz.com/edit/vitejs-vite-bcjsis?file=main.js&terminal=dev Long story short, one tiny but critical missing behavior of quill (or any other editors like tiptap/prosemirror etc.) that makes it inferior to the experience of Google Docs, is inheriting inline styles from previous lines when hitting enter at the end. Quill's cursor implementaion can only retain formats for the current line. The hack in the demo tries to mimic Google Docs' behavior Hack in the demo This hack is an approximation because it doesn't really persist the formats on empty lines. They get filtered out by quill.getContents(), but they survive reloads because inheriting styles from previous blocks is deterministic. It all works intuitively - until IME comes into play that breaks it apart. I do consider the behavior of using If we can fix the {
insert: '\n',
attributes: {
color: '#569cd6',
size: '18px',
bold: true,
underline: true,
italic: true
}
} This would represent the empty line that holds the default inline formats. |
Okay I think that makes sense. Can you create a new ticket for that? I think a way to fix that is to listen to compositionstart when caret is at the beginning of a formatted empty line, and reset the br styles. Also listen to compositionend and restore the styles. Haven't thought about it thoroughly though. |
We discovered that |
@fnlctrl Have you tried utilizing CleanShot.2023-11-27.at.15.23.56.mp4Code: https://github.com/quilljs/quill/compare/zh-emptyline-formats?expand=1 There are still some TODOs left though:
|
Fixes: #3692, #3375, #2407, #2096, #3692 , #3375 , #2407 , #2096 , #3267 , #2187 , #2285 , #2144 , #3522 , #2498 , #3450 , #3711
In the case of text replacements (see definition below), we currently rely on the browser's default behavior and then utilize MutationObserver to synchronize DOM changes with the model. Sometimes, this approach doesn't work well, as browsers may generate unexpected mutations that Quill is unable to process.
At Slab, we handle text replacements explicitly with Input Event (mostly Level 1 but some Level 2 features supported by all modern browsers) and it's been working reliably for months. This PR mostly moves the code to Quill but also handles IME as well.
Definition of Text Replacements
The most common scenario occurs when a range of text is selected, and the user presses any keystrokes.
Additionally, built-in spell checks and some platform-specific operations (e.g., emoji picker, text replacement settings on macOS) can also be considered as text replacements.
It's important to note that the selection does not necessarily need to encompass the text that is about to be replaced. For instance, on some platforms, there may be a hover toolbar that appears when the user moves the cursor over the misspelled word, allowing them to select a word to replace the current word.
Test Plan
Open http://localhost:9000/standalone/full.
Simple text replacement
Enter "abc" and make "b" red. Select "bc" and press "d". Make sure the editor ends with "ad".
Simple text replacement with IME
Enter "abc" and make "b" red. Select "bc". Switch to a Chinese/Japanese IME, press "d" and confirm the word. Make sure "bc" is replaced by the confirmed word.
Spell check
Enter "a makeing" and make "makeing" red. Right-click on "makeing" and select "making" in the spell check list:
Make sure "makeing" is converted to "making", and "making" is in red.
Others
Make sure the mentioned issues are fixed.
I verified all the mentioned issues except #2407 which I can't reproduce on my side and this PR fixes all of them.
I also tested on the following browsers and all seem to work correctly:
TODO items
handleBackspace
function to the Input module by handling thedeleteContentBackward
input type. This improvement would increase compatibility with system features, such as iOS's dictation.