-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Renderer – take 2 #4372
Comments
One design problem of the current Renderer came out when we were working on ckeditor/ckeditor5-engine#1455. I pushed some tests to // <ul><li1>Foo</li1><li2><b>Bar</b></li2></ul>
// ->
// <ul><li1>Foo<ul><li2><b>Bar</b><i>Baz</i></li2></ul></li1></ul>
it( 'renders changes made in detached elements', () => {
const ul = parse(
'<container:ul>' +
'<container:li>Foo</container:li>' +
'<container:li><attribute:b>Bar</attribute:b>Baz</container:li>' +
'</container:ul>' );
// Render the initial content.
view.change( writer => {
writer.insert( Position.createAt( viewRoot ), ul );
} );
// Make some changes in a detached elements (li1, li2).
view.change( writer => {
const li1 = ul.getChild( 0 );
const li2 = ul.getChild( 1 );
writer.remove( Range.createIn( ul ) );
const innerUl = writer.createContainerElement( 'ul' );
writer.insert( Position.createAt( innerUl ), li2 );
writer.insert( Position.createAt( li1, 'end' ), innerUl );
const i = writer.createAttributeElement( 'i' );
writer.wrap( Range.createFromParentsAndOffsets( li2, 1, li2, 2 ), i );
writer.insert( Position.createAt( ul ), li1 );
} );
expect( domRoot.innerHTML ).to.equal( '<ul><li>Foo<ul><li><b>Bar</b><i>Baz</i></li></ul></li></ul>' );
} ); What you'll get currently is That's because all the operations in This shows that we:
Right now, the "nodes watching" logic is implemented in the This is in line with other observations that we had. Right now, all Regardless of what kind of tests are better for We discussed briefly with @pjasiun and @f1ames how the architecture could look and we came up with this:
The It's still to discuss how |
One more thing that I'd love to do before we'll work on this is a research on:
|
As @Reinmar already mentioned Renderer on the other hand, for the editing pipeline, need to handle much more. The fact that big part of its logic is now in the
Agree, but keep in mind that there is a significant difference between popular virtual DOM libraries and an editor. In the editor, based on the |
Recently we have encountered an issue described by @Reinmar in https://github.com/ckeditor/ckeditor5-engine/issues/1456#issuecomment-402424524 (manipulating detached nodes) - https://github.com/ckeditor/ckeditor5-engine/issues/1560. |
Oh my god, I've just stumbled upon #4353 when debugging some IME/typing related scenarios with @oleq and it's a nightmare. The role of the renderer should be to take any new view, even completely rebuilt, and apply reasonable ( Why do I write "reasonable" instead of "minimal"? Because of complexity. There are cases where we have to go for minimal changes. But in many, especially if the view changed heavily, we can completely rebuild the DOM. When can we take shortcuts? For example, we could have an assumption that if an instance of a view element changes (e.g. one However, there are cases when we shouldn't cut corners. One case where that has hard to predict consequences is when you type. The smaller the changes in the DOM, the better and it shouldn't be rocket science. In case of text nodes, while diffing we should treat text nodes as "similar" and after updating the structure, make minimal changes to update outdated text nodes. In other words, #4353 (comment). The approach to that must be SAFE. The current renderer is too reliant on what happens outside. Currently, the renderer assumes (incorrectly) that if a text node changed in the view from "foo" to "foob" it will be in Let's therefore only mark elements to be checked and if we know that a text node changes in the view (may perhaps happen if two text nodes are merged), let's mark the parent element to be updated. |
Related comment from the community - #9376 (comment) |
There has been no activity on this issue for the past year. We've marked it as stale and will close it in 30 days. We understand it may be relevant, so if you're interested in the solution, leave a comment or reaction under this issue. |
There has been no activity on this issue for the past year. We've marked it as stale and will close it in 30 days. We understand it may still be relevant, so if you're interested in the solution, leave a comment or reaction under this issue. |
We've closed your issue due to inactivity over the last year. We understand that the issue may still be relevant. If so, feel free to open a new one (and link this issue to it). |
We apparently came to the tipping point of what we can do with the current
Renderer
's implementation.For the last 3 years, we've been extending its initial implementation. We added a lot of bug fixes and improvements. But the architecture and the outline of its implementation remained the same.
What we see now are issues like:
domConverter
should not modify DOM structure #4371They show that it became really hard to work on it further. It's too much accidental development now, which, together with a high essential complexity results in reduced stability and potential for further improvements.
What we need to do is to design a new
Renderer
– both its API and the algorithm for updating the DOM. We should also rethink the idea ofDomConverter
because it proved to create confusion.The text was updated successfully, but these errors were encountered: