-
-
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
Redesign and introduce new reconversion system #10294
Comments
The It also implements the logic of |
I just noticed another bug in the current reconversion implementation: #10314 |
I have couple thoughts after working on adding support for reconversion in Let me put them all together in this ticket so they are at least noted somewhere. Children prop
|
* @param {Array.<String>} [config.model.attributes] The list of attribute names that should be consumed while creating | |
* the view structure. Note that the view will be reconverted if any of the listed attributes will change. |
Do we have to mention consumables here? Isn't enough to say the second part:
View will be reconverted if any of the listed attributes will change.
Also, to keep it consistent with other parts of this API, shouldn't we accept both array of strings and string for single attribute?
@param {String|Array.<String>} [config.model.attributes]
ckeditor5/packages/ckeditor5-engine/src/conversion/downcasthelpers.js
Lines 219 to 220 in e10b4ea
* Note: The children of a model element that's being converted must be allocated in the same order in the view | |
* in which they are placed in the model. |
I know it has been added as part of "improving docs" commit, but this note is still a bit unclear to me. Yeah it describes the constraint but does not say why nor what happens if you don't follow it. Will it raise an error? Will it crash?
I guess this probably might be a part of improving conversion docs and be just a matter of putting a link near this note.
@Reinmar @niegowski FYI
The normalization accepts it, maybe it's just missing JSDoc? |
Hopefully this will solve issues like #10306 |
Feature (engine): The DowncastWriter#createContainerElement() should accept a list of children so bigger view structures can be created in one call. Closes #10714. Feature (engine): The elementToElement downcast helper will log a console warning if multiple elements have been created. Closes #10610. Feature (engine): The DowncastDispatcher will throw an error if any of the model items were not consumed while converting. Closes #10377. Feature (engine): Introducing convertItem(), convertChildren() and convertAttributes() in the downcast conversion API interface. Feature (engine): Added support for reconversion in DowncastHelpers#elementToElement() downcast helper. Closes #10359. Feature (engine): Added DowncastHelpers#elementToStructure() downcast helper with reconversion support. Closes #10358. Feature (engine): It's now possible to trigger a nested conversion while downcasting an element. Docs (engine): Overhauled the conversion documentation and introduced the documentation for conversion helpers. Closes #10294. Internal (engine): elementToStructure() should throw when invoked for an element that allows $text. Closes #11163. Internal (engine): Replaced conversionApi.slotFor() in elementToStructure with writer.createSlot(). Closes #11179. Internal (engine): Reconversion helpers can coexist with Differ#refreshItem() children. Other (engine): Implemented the EditingController#reconvertMarker() method to be used instead of Writer#updateMarker() for marker reconversion purposes. Implemented the EditingController#reconvertItem() method to replace Differ#refreshItem(). Closes #10659. Other (engine): The attribute and child nodes conversion events are fired by the lowest priority handler for the insert event instead of by DowncastDispatcher itself. Closes #10376. Other (engine): Events are fired by the DowncastDispatcher even if they were previously consumed. It's the conversion handler's responsibility to check if it can be consumed or if it was already consumed by other converters. Other (engine): The DowncastDispatcher#convert() method introduced as a replacement to previously used convertInsert(). The new method handles not only nodes conversion but also markers. Internal (horizontal-line): The horizontalLine element downcast conversion has been changed from elementToElement to elementToStructure. Internal (html-support): HTML elements downcast conversion have been changed from elementToElement to elementToStructure. Internal (image): The imageBlock and imageInline elements downcast conversion have been changed from elementToElement to elementToStructure. Internal (link): Link inlineWidget element downcast conversion has been changed from elementToElement to elementToStructure. Internal (media-embed): The media element downcast conversion has been changed from elementToElement to elementToStructure. Internal (page-break): The pageBreak element downcast conversion has been changed from elementToElement to elementToStructure. Internal (widget): The blockWidget and inlineWidget elements downcast conversion have been changed from elementToElement to elementToStructure. Internal (heading): Added missing consuming converter. Internal (heading): Code adjusted to changes in DowncastDispatcher API. Internal (html-embed): Code adjusted to the removal of triggerBy conversion option. Other (list): The ckeditor5-list package was restructured into subdirectories. Closes #10811. Other (list): Downcast conversion should consume downcasted attributes. Other (table): Table downcast conversion migrated to elementToStructure() downcast helper. Closes #10502. Tests (clipboard): Added missing downcast conversion. Tests (image): Tests updated to properly handle non-consumed errors fired by the DowncastDispatcher. Tests (alignment, autoformat, block-quote, engine, html-support, image, indent, table, word-count): Tests updated after list package restructuring. Tests (html-support): Fixed test for checking if an attribute was consumed while converting. Docs (ckeditor5): Links in the migration guide point to the new conversion documentation. MAJOR BREAKING CHANGE (list): The ListEditing, ListUI, ListStyleEditing, ListStyleUI, TodoListEditing, TodoListUI plugins were moved to the dedicated subdirectories (list, liststyle, todolist). MAJOR BREAKING CHANGE (engine): Removed the Differ#refreshItem() method from the public API. Replaced by EditingController#reconvertItem() (see #10659). MAJOR BREAKING CHANGE (engine): The DowncastDispatcher will throw an error if any of the model items were not consumed while converting. Read the conversion-model-consumable-not-consumed error documentation for more information. MAJOR BREAKING CHANGE (engine): The DowncastDispatcher#conversionApi property is no longer available. The instances of DowncastConversionApi being created at the start of conversion. MAJOR BREAKING CHANGE (engine): The support for the triggerBy option for downcast helpers is removed and replaced with the new elementToStructure() options. MINOR BREAKING CHANGE (media-embed): The createMediaFigureElement helper function first argument has been changed from writer object to conversionApi object. MINOR BREAKING CHANGE (table): The downcast converters of the table feature has been rewritten with the use of elementToStructure() and the re-conversion mechanism. See #10502.
Crosslinking the summary of changes for this huge feature: #11268 (comment) |
EDIT (Summary of changes)
You can find a summary of changes in the conversion system in this post: #11268 (comment)
There's also a migration guide that covers related changes: Migration to CKEditor 5 v33.0.0.
Why
What do we have now
There is a downcast helper for
elementToElement
with atriggerBy
option that triggers reconversion of a specific model element by removing its view representation (but keeping mappings), triggering the new view structure conversion callbacks (for that model element only), and reusing the child elements' old view representations.What’s wrong with what we have now
To downcast a single model element to a slightly more complex structure we need to use the low-level API (so we need to take care of consuming what we converted and to bind model elements with view elements). That's because we are converting a subtree of a model structure. The reusing of view elements works sort of in a "magical" way.
There is also an issue about the current implementation conflicting different
triggerBy
converters: #9641.What could we improve in the current solution
It could be more understandable if a single
elementToElement
converter would handle a single model element and do not touch its children elements. The conversion callback could provide a view structure with the special placeholders (slots) that model child elements should be downcasted into.Why do we think it can be done better?
The current
triggerBy
usage is very confusing. It requires to convert (in a single converter) not only an element itself but also its model child elements (and only their content is reused). This would be more declarative if we could provide conversion for a single model element to a bigger view structure with placeholders/slots for model child elements so that it could take care of inserting view elements in the correct positions in the view structure (not only as a direct child of the main element).That slots could also have conditions for example to handle specific table rows (
thead
vstbody
that depends onheadingRows
attribute value).What do we have prototyped so far? Where’s that code?
The early PoC is in the list reconversion branch (that includes a lot of other experiments for
rangeToStructure
conversion). That branch is currently broken (because of changes in progress). The most interesting function isinsertSlotted
that is supposed to get triggered after the old view was removed (but the view mapping was temporarily kept until the end of the conversion process to be reused while converting slots' content).What
A high-level overview of a new mechanism
The solution could be split into layers:
DowncastDispatcher
could fire a newreduceChanges
event before the conversion process starts to allow features (or conversion helpers) to alter the list of changes provided by theDiffer
so it could detect cases where the reconversion should be used. The re-conversion would be split into 2 events - one to remove the old view representation of a model element and one to insert a new representation. The old view elements would get removed from the view and unbound in theMapper
but it could keep temporal mapping to allow reusing view elements that got removed in the same conversion process. Those would get flushed at the end of the whole conversion.DowncastHelpers
elementToElement
andelementToStructure
would listen for thereduceChanges
event to register callbacks fortriggerBy
changes to trigger re-conversion is a specified situation.elementToStructure
downcast helper could provide a factory for placeholders/slots so the simple view generator could put those into the structure and the helper itself would take care of converting those slot's content or reusing the view that was previously there.Example API proposal
The high-level API:
Success criteria
rangeToStructure
future helper that will be used for the document list conversion.Risks, other things to change.
When
Why now
The PoC was prepared while working on #9784 and #9783. This could be extracted from that PoC as it's a separate feature that would be later used by
rangeToStructure
downcast helper.What’s next
The next step would be to implement
rangeToStructure
downcast helper and use it for document list conversion.If you'd like to see this feature implemented, add a 👍 reaction to this post.
The text was updated successfully, but these errors were encountered: