Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

T/ckeditor5 typing/101 Multiple spaces fix #1083

Merged
merged 9 commits into from
Aug 22, 2017
Merged

Conversation

scofalik
Copy link
Contributor

@scofalik scofalik commented Aug 18, 2017

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.

@scofalik scofalik changed the title T/ckeditor5 typing/101 T/ckeditor5 typing/101 Multiple spaces fix Aug 18, 2017
@Reinmar
Copy link
Member

Reinmar commented Aug 18, 2017 via email

@scofalik
Copy link
Contributor Author

It is used in domconverter.js and renderer.js and I couldn't find any good place where to fit it. I think that with time more functions might join there. For example I've used two times already a function that takes a view position and moves it forward after all ui elements.

If I were to put it in some existing place I'd probably do it as an exported function treewalker.js or maybe in writer.js, although the function does not change the view in any way...

@@ -420,6 +425,12 @@ export default class Renderer {

if ( actualText != expectedText ) {
domText.data = expectedText;

const nextTouchingTextNode = getTouchingTextNode( viewText, true );
Copy link
Member

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.

/**
* Contains utility functions for working on view.
*
* @module engine/view/utils
Copy link
Member

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).

* 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.
Copy link
Member

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).

Copy link
Member

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.

@@ -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 ) {
Copy link
Member

@Reinmar Reinmar Aug 21, 2017

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?

Copy link
Contributor Author

@scofalik scofalik Aug 21, 2017

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.

Copy link
Member

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?

Copy link
Contributor Author

@scofalik scofalik Aug 22, 2017

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.

Copy link
Member

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:

  1. <p>x<strong> b</strong></p>
  2. Type space after "x".
  3. Paragraph's children get updated (because for some reason the browser mutated text nodes too much when typing the space).
  4. The "x " text node is up to date when it comes to updating text nodes, so we don't mark " b" to be updated.

Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Copy link
Member

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.
Copy link
Member

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"?

@Reinmar
Copy link
Member

Reinmar commented Aug 21, 2017

All works fine, but a couple of things need to be improved in the code.

@scofalik
Copy link
Contributor Author

scofalik commented Aug 21, 2017

Unfortunately there is one more bug because text nodes are not refreshed when a node is removed or inserted. This is handled in _updateChildren not in _updateText.

For example, <p><em>&nbsp;x</em> becomes <p>x<em>&nbsp;x</em></p>.

EDIT:
Looking at _updateChildren and how it works, it seems a bit tricky how to trigger refreshing text nodes in a nice way. The algorithm bases on what domConverter.viewChildrenToDom and diffs it with current DOM, then operates only on DOM. The truth is that viewChildrenToDom returns wrong value at the moment, because it will not refresh text node if it was in already mapped AttributeElement. It saves us some processing time, but produces wrong results. I think that the only sane way is to fix viewChildrenToDom so it will refresh all text nodes inside given view element deeply, but this may have some impact on rendering time.

@Reinmar
Copy link
Member

Reinmar commented Aug 21, 2017

Let's not enlarge this PR with this case. Refreshing sibling text nodes was already something that we added here.

…Moved `getTouchingTextNode` back to `view.DomConverter`.
@scofalik
Copy link
Contributor Author

scofalik commented Aug 22, 2017

Ready for review. Added #1093

@Reinmar Reinmar merged commit 9ca61d5 into master Aug 22, 2017
@Reinmar Reinmar deleted the t/ckeditor5-typing/101 branch August 22, 2017 11:32
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Pressing "Spacebar" twice at empty paragraph inserts only one space
2 participants