-
Notifications
You must be signed in to change notification settings - Fork 40
T/ckeditor5 typing/101 Multiple spaces fix #1083
Conversation
Why did you expose getTouchingTextNode as a util? Is it necessary?
…Sent from my iPhone
On 18 Aug 2017, at 13:03, Szymon Cofalik ***@***.***> wrote:
Suggested merge commit message (convention)
Fix: Multiple spaces in an empty paragraph are now allowed. Closes ckeditor/ckeditor5-typing#101.
You can view, comment on, or merge this pull request online at:
#1083
Commit Summary
Changed: Introduced `view.utils` and `view.utils.getTouchingTextNode`.
Fixed: Fixed handling spaces in view text nodes in view-to-dom conversion.
Changed: Renderer should re-render also next text node if a text node has changed.
File Changes
M src/view/domconverter.js (114)
M src/view/renderer.js (17)
A src/view/utils.js (41)
M tests/view/domconverter/view-to-dom.js (79)
M tests/view/renderer.js (21)
A tests/view/utils.js (58)
Patch Links:
https://github.com/ckeditor/ckeditor5-engine/pull/1083.patch
https://github.com/ckeditor/ckeditor5-engine/pull/1083.diff
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
It is used in If I were to put it in some existing place I'd probably do it as an exported function |
src/view/renderer.js
Outdated
@@ -420,6 +425,12 @@ export default class Renderer { | |||
|
|||
if ( actualText != expectedText ) { | |||
domText.data = expectedText; | |||
|
|||
const nextTouchingTextNode = getTouchingTextNode( viewText, true ); |
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.
Missing comment why we need to do that.
src/view/utils.js
Outdated
/** | ||
* Contains utility functions for working on view. | ||
* | ||
* @module engine/view/utils |
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.
Let's rename this to walker-utils
since the utils that come to our mind are Walker related. We also considered putting this to the walker's module but we don't want to make it too big (hence, a new module).
src/view/utils.js
Outdated
* in the same container element. If there is no such sibling, `null` is returned. | ||
* | ||
* @param {module:engine/view/text~Text} node Reference node. | ||
* @param {Boolean} getNext If `true` next touching sibling will be returned. If `false` previous touching sibling will be returned. |
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.
It'd be good to find it a better name... but I can't :D. lookRight
?
Also, this is an optional param. Should be marked with []
. Maybe this will clarify its meaning (typically, boolean flags are optional).
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.
As for this flag being optional – it's always passed in the tests: https://github.com/ckeditor/ckeditor5-engine/pull/1083/files#diff-41de3c28cf4c9630dfaec4e35850f0faR38. This should be changed also there.
src/view/renderer.js
Outdated
@@ -407,6 +406,12 @@ export default class Renderer { | |||
*/ | |||
_updateText( viewText, options ) { | |||
const domText = this.domConverter.findCorrespondingDomText( viewText ); | |||
|
|||
// If this is a new text node and it is not in DOM, it will be created and handled in `_updateChildren`. | |||
if ( !domText ) { |
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 looks very suspicious. How did this function work without this condition so far? Why is it needed here now?
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.
It worked because there was a condition in view.Renderer#render
method.
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.
So why doesn't that condition save us from adding one 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.
I don't understand. Before there was a condition in render
method in the loop where _updateText
is called. I removed this condition because I wanted _updateText
to be fired more often. But this caused a situation where _upadateText
was fired on text nodes that weren't yet converted to DOM. That's why I needed to add the statement in _updateText
.
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.
Aaand it turned out we can't make this change ;> We'll also need to make a step back and remove the fix for subsequent text nodes updating. It seems that we may not be able to finalise it now because of how the text nodes are mapped.
We can neither update all text nodes before children are updated because changes in children might've changed the indexes of text nodes (so updating text nodes would fail). Changing the order to 1) update children, 2) update text nodes doesn't help too because in the following case, the whole paragraph is updated first and then text nodes are not:
<p>x<strong> b</strong></p>
- Type space after "x".
- Paragraph's children get updated (because for some reason the browser mutated text nodes too much when typing the space).
- The
"x "
text node is up to date when it comes to updating text nodes, so we don't mark" b"
to be updated.
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.
@scofalik will you report a ticket for this case and the one you mentioned in #1083 (comment)? And of course, please revert changes which we can't do now.
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.
src/view/utils.js
Outdated
for ( const value of treeWalker ) { | ||
if ( value.item.is( 'containerElement' ) ) { | ||
// ViewContainerElement is found on a way to next ViewText node, so given `node` was first/last | ||
// text node in it's container element. |
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.
its
test( [ 'x ', ' y' ], 'x_ _ _ _y' ); | ||
test( [ 'x ', ' y' ], 'x _ _ _ y' ); | ||
|
||
// "Non-empty" + "empty" text nodes. |
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.
What about mirrored cases with "empty" + "non-empty"?
All works fine, but a couple of things need to be improved in the code. |
Unfortunately there is one more bug because text nodes are not refreshed when a node is removed or inserted. This is handled in For example, EDIT: |
Let's not enlarge this PR with this case. Refreshing sibling text nodes was already something that we added here. |
…w->dom conversion.
…Moved `getTouchingTextNode` back to `view.DomConverter`.
Ready for review. Added #1093 |
Suggested merge commit message (convention)
Fix: Multiple spaces in an empty paragraph are now allowed. Closes https://github.com/ckeditor/ckeditor5-typing/issues/101.
Additional info
The whole algorithm got simplified and fixed and a few other edge cases has been also fixed.