Update to CKEditor 5 v33.x
When updating your CKEditor 5 installation, ensure all the packages are the same version to avoid errors.
For custom builds, you may try removing the package-lock.json
or yarn.lock
files (if applicable) and reinstalling all packages before rebuilding the editor. For best results, make sure you use the most recent package versions.
# Update to CKEditor 5 v33.0.0
Released on March 9, 2022.
For the entire list of changes introduced in version 33.0.0, see the release notes for CKEditor 5 v33.0.0.
Below are the most important changes that require your attention when upgrading to CKEditor 5 v33.0.0.
# New import paths in the ckeditor5-list
package
Starting with v33.0.0, some import paths have changed in the ckeditor5-list
package. If your application imports individual plugins to integrate or build CKEditor 5, you should update the paths accordingly:
// ❌ Old import paths:
import ListEditing from '@ckeditor/ckeditor5-list/src/listediting';
import ListUI from '@ckeditor/ckeditor5-list/src/listui';
import TodoListEditing from '@ckeditor/ckeditor5-list/src/todolistediting';
import ListPropertiesEditing from '@ckeditor/ckeditor5-list/src/listpropertiesediting';
// ✅ New import paths (with subdirectories):
import ListEditing from '@ckeditor/ckeditor5-list/src/list/listediting';
import ListUI from '@ckeditor/ckeditor5-list/src/list/listui';
import TodoListEditing from '@ckeditor/ckeditor5-list/src/todolist/todolistediting';
import ListPropertiesEditing from '@ckeditor/ckeditor5-list/src/listproperties/listpropertiesediting';
Import paths for top-level plugins such as List
, ListProperties
, TodoList
, etc. remain the same. If you are not sure which import path you should use, you can always browse the GitHub source code that corresponds to the contents of the package on npm.
# Additional dependencies in CKEditor 5 collaboration features
The DLL builds support was introduced for collaboration features. As a result, some imports, plugin requirements and cross-package dependencies have changed to allow for the new building process.
From now on, extra plugins will be required when you add the following CKEditor 5 collaboration features to the editor:
-
TrackChanges
will also require addingComments
to the list of the editor plugins:// ❌ Old imports: import TrackChanges from '@ckeditor/ckeditor5-track-changes/src/trackchanges'; // ✅ New imports: import TrackChanges from '@ckeditor/ckeditor5-track-changes/src/trackchanges'; import Comments from '@ckeditor/ckeditor5-comments/src/comments';
-
RealTimeCollaborativeEditing
will also requireCloudServices
:// ❌ Old imports: import RealTimeCollaborativeEditing from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativeediting'; // ✅ New imports: import RealTimeCollaborativeEditing from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativeediting'; import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices';
-
RealTimeCollaborativeComments
will also requireCloudServices
andComments
:// ❌ Old imports: import RealTimeCollaborativeComments from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativecomments'; // ✅ New imports: import RealTimeCollaborativeComments from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativecomments'; import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices'; import Comments from '@ckeditor/ckeditor5-comments/src/comments';
-
RealTimeCollaborativeTrackChanges
will also requireCloudServices
,Comments
, andTrackChanges
:// ❌ Old imports: import RealTimeCollaborativeTrackChanges from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativetrackchanges'; // ✅ New imports: import RealTimeCollaborativeTrackChanges from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativetrackchanges'; import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices'; import Comments from '@ckeditor/ckeditor5-comments/src/comments'; import TrackChanges from '@ckeditor/ckeditor5-track-changes/src/trackchanges';
-
RealTimeCollaborativeRevisionHistory
will also requireCloudServices
:// ❌ Old imports: import RealTimeCollaborativeRevisionHistory from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativerevisionhistory'; // ✅ New imports: import RealTimeCollaborativeRevisionHistory from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativerevisionhistory'; import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices';
-
CloudServicesCommentsAdapter
will also requireCloudServices
andCommentsRepository
:// ❌ Old imports: import CloudServicesCommentsAdapter from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativecomments/cloudservicescommentsadapter'; // ✅ New imports: import CloudServicesCommentsAdapter from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativecomments/cloudservicescommentsadapter'; import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices'; import CommentsRepository from '@ckeditor/ckeditor5-comments/src/comments/commentsrepository';
-
CloudServicesTrackChangesAdapter
will also requireCloudServices
,CommentsRepository
, andTrackChangesEditing
:// ❌ Old imports: import CloudServicesTrackChangesAdapter from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativetrackchanges/cloudservicestrackchangesadapter'; // ✅ New imports: import CloudServicesTrackChangesAdapter from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativetrackchanges/cloudservicestrackchangesadapter'; import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices'; import CommentsRepository from '@ckeditor/ckeditor5-comments/src/comments/commentsrepository'; import TrackChangesEditing from '@ckeditor/ckeditor5-track-changes/src/trackchangesediting';
-
CloudServicesRevisionHistoryAdapter
will also requireCloudServices
:// ❌ Old imports: import CloudServicesRevisionHistoryAdapter from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativerevisionhistory/cloudservicesrevisionhistoryadapter'; // ✅ New imports: import CloudServicesRevisionHistoryAdapter from '@ckeditor/ckeditor5-real-time-collaboration/src/realtimecollaborativerevisionhistory/cloudservicesrevisionhistoryadapter'; import CloudServices from '@ckeditor/ckeditor5-cloud-services/src/cloudservices';
# Mandatory consumption of all model items in the downcast conversion pipeline
Starting with v33.0.0, all items in the model must be consumed in the downcast conversion pipeline to prevent errors and unpredictable behavior of the editor features. If a model item is not consumed, the conversion-model-consumable-not-consumed
error will be thrown. To learn more about the causes of this error and possible solutions, refer to the API documentation.
# The triggerBy
option in the downcast pipeline is now obsolete
The v33.0.0 release introduces a massive upgrade to the conversion system. You can find a detailed summary of all these changes in the developer notes on GitHub.
If some of your downcast pipeline converters used the experimental triggerBy
property to trigger (re)conversion upon changes of attributes or children, you need to update them. For instance:
// ❌ The old conversion using obsolete "triggerBy":
editor.conversion.for( 'downcast' ).elementToElement( {
model: 'myElement',
view: ( modelElement, { writer } ) => {
return writer.createContainerElement( 'div', {
'data-owner-id': modelElement.getAttribute( 'ownerId' ),
class: `my-element my-element-${ modelElement.getAttribute( 'type' ) }`
} );
},
triggerBy: {
attributes: [ 'ownerId', 'type' ],
children: 'childModelElement'
}
} );
// ✅ The new conversion syntax:
editor.conversion.for( 'downcast' ).elementToElement( {
model: {
name: 'myElement',
attributes: [ 'ownerId', 'type' ],
children: true
},
view: ( modelElement, { writer } ) => {
// The same converter code.
}
} );
The new syntax is available both in elementToElement
and elementToStructure
helpers.
# New downcast converters for the table feature
The conversion brought by the TableEditing
plugin was refined in this version and now relies heavily on the elementToStructure
downcast conversion helper.
If your integration extends or overwrites that conversion (the table
, tableRow
, tableCell
model elements and/or their attributes), you might need to undertake some actions to align your custom features with the latest editor API. The extent of necessary changes may vary depending on how advanced your customizations are.
# Responsibility shift in the low–level downcast converters
Downcast dispatcher will now fire events for model items no matter if they were consumed or not. This means that the low–level (event-driven) downcast converters listening to these events must first test whether the item has already been consumed to prevent double conversion and errors:
editor.conversion.for( 'downcast' ).add( dispatcher => {
dispatcher.on( '...', ( evt, data, conversionApi ) => {
// Before converting, check whether the change has not been consumed yet.
if ( !conversionApi.consumable.test( data.item, evt.name ) ) {
return;
}
// Converter code...
} );
} );
Also, starting with CKEditor 5 v33.0.0, your custom converters must consume all model items to prevent further errors.
# The Differ#refreshItem()
method is now obsolete
Differ#refreshItem()
is obsolete and was replaced by reconvertItem
:
// ❌ Old API:
editor.model.document.differ.refreshItem( ... );
// ✅ New API:
editor.editing.reconvertItem( ... );
# Comments editor configuration is now required
Since we removed the cross-package dependencies inside the project, the configuration for the comments editor became required. The editor used in the comments section is also a CKEditor 5 instance. It is configured the same way as the regular editor.
After the update, you should configure the comments editor using the config.comments.editorConfig
option:
import Autoformat from '@ckeditor/ckeditor5-autoformat/src/autoformat';
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
import List from '@ckeditor/ckeditor5-list/src/list';
ClassicEditor
.create( document.querySelector( '#editor' ), {
// ...
comments: {
editorConfig: {
extraPlugins: [ Autoformat, Bold, Italic, List ]
}
}
} )
.then( /* ... */ )
.catch( /* ... */ );
Before the change, the comments editor included the Bold
, Italic
, Autoformat
, and List
plugins.
If you want to keep the same user experience after updating the editor, you need to configure the comments editor as shown in the example above.
If this configuration is not provided, a warning will be logged in the console and the comments editor will be initialized with the most basic features: typing, paragraph, and undo.
To hide the warning (and use the basic configuration), provide an empty configuration for the comments editor:
ClassicEditor
.create( document.querySelector( '#editor' ), {
// ...
comments: {
editorConfig: {}
}
} );
# New API
# New elementToStructure()
downcast helper
The new elementToStructure
helper was introduced to streamline downcast conversion to complex view structures. Unlike elementToElement
, it allows placing children of an element in configurable slots in the view structure without the need to develop complex converters using the low–level event–driven API.
To learn more about this new helper, refer to the API documentation or check out the official conversion guide with plenty of examples and details.
# New API to trigger downcast (re)conversion
The triggerBy
property is obsolete and a new API was created to trigger the downcast conversion of a model element upon changes to its attributes or children (also known as reconversion):
editor.conversion.for( 'downcast' ).elementToElement( {
model: {
name: 'myElement',
// Changes to these attributes will (re)convert myElement.
attributes: [ 'ownerId', 'type' ],
// If some children are added or removed, myElement will be (re)converted.
children: true
},
view: ( modelElement, { writer } ) => {
// ...
}
} );
The new syntax of the model
property is available in the elementToElement
and elementToStructure
helpers. Refer to the respective API documentation for more details.
# Improved API of DowncastWriter#createContainerElement()
Starting from v33.0.0, you can specify the children of a container element directly in the createContainerElement
method:
// ❌ Old API:
const element = writer.createContainerElement( 'p', { id: '1234' } );
writer.insert( writer.createPositionAt( element, 0 ), childElementA );
writer.insert( writer.createPositionAt( element, 1 ), childElementB );
// ...
// ✅ New API:
writer.createContainerElement( 'p', { id: '1234' }, [
childElementA,
childElementB,
// ...
] );
Every day, we work hard to keep our documentation complete. Have you spotted outdated information? Is something missing? Please report it via our issue tracker.
With the release of version 42.0.0, we have rewritten much of our documentation to reflect the new import paths and features. We appreciate your feedback to help us ensure its accuracy and completeness.