Update to CKEditor 5 v29.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 v29.1.0
Released on August 4, 2021.
For the entire list of changes introduced in version 29.1.0, see the release notes for CKEditor 5 v29.1.0.
Below are the most important changes that require your attention when upgrading to CKEditor 5 v29.1.0.
# Matcher pattern API change
Starting from v29.1.0, the Matcher
feature deprecated matching style
and class
HTML attributes using attributes
key-value pairs pattern.
The Matcher
feature allows to match styles and classes by using dedicated styles
and classes
patterns. Since v29.0.0 it is also possible to match every possible value for these attributes by using the Boolean type with the true
value. To avoid confusion about which pattern to use to match classes and styles, we decided to deprecate matching classes and styles using the attributes
pattern.
Here is an example of changes you may need for proper integration with the Matcher
feature new API:
// Old code.
new Matcher( {
name: 'a',
attributes: {
'data-custom-attribute-1': /.*/,
'data-custom-attribute-2': /.*/,
style: true,
class: true
}
} );
// New code.
new Matcher( {
name: 'a',
attributes: {
'data-custom-attribute-1': /.*/,
'data-custom-attribute-2': /.*/
},
styles: true,
classes: true
} );
# Link decorators API change
Matcher pattern API change also improves how to define the link decorators (both manual decorator and automatic decorator). Similar to the Matcher
feature API, you should define the style
and class
HTML attributes using the classes
and styles
properties.
Here is an example of changes you may need for proper integration with the link decorators API change:
// Old code.
ClassicEditor
.create( ..., {
// ...
link: {
decorators: {
addGreenLink: {
mode: 'automatic',
attributes: {
class: 'my-green-link',
style: 'color:green;'
}
}
}
}
} )
// New code.
ClassicEditor
.create( ..., {
// ...
link: {
decorators: {
addGreenLink: {
mode: 'automatic',
classes: 'my-green-link',
styles: {
color: 'green'
}
}
}
}
} )
# Update to CKEditor 5 v29.0.0
Released on July 7, 2021.
This migration guide enumerates the most important changes that require your attention when upgrading to CKEditor 5 v29.0.0 due to changes introduced in the Image
plugin and some other image-related features.
For the entire list of changes introduced in version 29.0.0, see the release notes for CKEditor 5 v29.0.0.
To get to know the new editor UI for the image features, visit the image feature guide, especially:
# Inline images
Starting from v29.0.0, the existing Image
plugin loads two independent plugins: ImageInline
and ImageBlock
, therefore both of them are included in all of the predefined editor builds by default.
- The
ImageInline
is a newly introduced plugin supporting the inline<img>
tag nested in text (for example inside a paragraph). - The
ImageBlock
maintains the functionality of the previousImage
plugin before v29.0.0. In the model, it uses theimageBlock
element (known asimage
before v29.0.0).
Note: It is possible to load only one of these plugins, but only when building the editor from source.
# Image caption
An image caption is no longer automatically shown when selecting the image widget. You can now toggle its visibility with a ToggleImageCaptionCommand
executed by the 'toggleImageCaption'
toolbar button, both registered by the ImageCaption
plugin. The button is added to the default image toolbar in all the predefined editor builds.
To provide a valid data output, you can only add captions to block images. Adding a caption to an inline image will automatically convert it to a block image (which can be undone by the user).
# Image styles
Since the appearance of the image in the document depends on the image type (block/inline), the ImageStyle
plugin is now in charge of switching between these types. Thus, we introduced the following changes:
-
A new set of buttons is available to manage the image type and appearance.
-
You can group the buttons provided by the
ImageStyle
plugin into dropdowns.- A few default dropdowns are provided.
- In the editor configuration, you can declare a custom dropdown.
-
The name of the default block image style has changed from
full
toblock
(as the default style for the inline images is calledinline
), the default content styles for these images remain the same. The button label has also changed and now readsCentered image
so that it reflects the actual appearance of the image. If you customized the default appearance of the block images, you can change the button label by modifying the existing image style. -
The format of the
config.image.styles
has changed. You must wrap the list of the styles with theoptions
array. Read more about theimage.styles
configuration.// Before v29.0.0. Editor.create( document.querySelector( '#editor' ), { ... image: { styles: [ 'inline', 'full', 'side' ] } } ); // Since v29.0.0. Editor.create( document.querySelector( '#editor' ), { ... image: { styles: { options: [ 'inline', 'block', 'side' ] } } } );
-
The format of the
imageStyle
has changed. It must now provide information about the image types supporting a particular style. Read more about theImageStyleOptionDefinition
.// Before v29.0.0. Editor.create( document.querySelector( '#editor' ), { ... image: { styles: [ { name: 'alignLeft', title: 'Left aligned image', icon: objectLeft, className: 'image-style-align-left' } ] } } ); // Since v29.0.0. Editor.create( document.querySelector( '#editor' ), { ... image: { styles: { options: [ { name: 'alignLeft', title: 'Left aligned image', icon: objectLeft, // Image types (names of the model elements) supporting this style. modelElements: [ 'imageBlock', 'imageInline' ], className: 'image-style-align-left' } ] } } } );
-
Several changes have been also made to the
ImageStyle
plugin API:- In the image style utilities module:
- The
defaultIcons
were renamed toDEFAULT_ICONS
. - The
defaultStyles
were renamed toDEFAULT_OPTIONS
. - The
normalizeImageStyles()
function was removed from the public API.
- The
- The
ImageStyleCommand#defaultStyle
andImageStyleCommand#styles
were removed from the public API.
- In the image style utilities module:
# Image toolbar
Until v29.0.0, custom editor builds without ImageStyle
and ImageToolbar
plugins were possible. Only block images were supported and captions were added by the user upon selecting the image.
Since v29.0.0, image styles and toolbar allow users to choose the type of image (inline or block) and give them a way to add or remove captions from block images via configurable buttons.
The user experience will degrade if either of these features is missing and this makes the image toolbar configuration essential.
Pre-configured editor builds come with ImageStyle
and ImageToolbar
plugins (and configuration) out-of-the-box. This information is mainly for developers who use custom editor builds in their integrations.
We recommend one of the following configurations as the minimum setup for the image toolbar:
-
For structured content editing (implemented by default in the classic, balloon, balloon block, and inline editor builds):
Editor.create( document.querySelector( '#editor' ), { ... image: { toolbar: [ 'imageStyle:inline', 'imageStyle:block', 'imageStyle:side', '|', 'toggleImageCaption', 'imageTextAlternative' ] } } );
-
For document-like editing (implemented by default in the decoupled document build).
Editor.create( document.querySelector( '#editor' ), { ... image: { toolbar: [ 'toggleImageCaption', 'imageStyle:inline', // A dropdown containing `alignLeft` and `alignRight` options. 'imageStyle:wrapText', // A dropdown containing `alignBlockLeft`, `block` (default) and `alignBlockRight` options. 'imageStyle:breakText' ] } } );
See the image feature guide to learn more about the configuration of the image toolbar.
# Inserting images
Since v29.0.0 inserting (also: pasting, dropping) an image in the middle of text will no longer split it if the ImageInline
plugin is loaded (default). If you prefer the old behavior in your integration, you can specify this in the ImageInsert
plugin configuration.
# Image utilities
-
The image utilities are now wrapped by the
ImageUtils
plugin.// Before v29.0.0. import { isImage } from './utils'; const selectedElement = editor.model.document.selection.getSelectedElement(); if ( isImage( selectedElement ) ) { // ... } // Since v29.0.0. // ... const imageUtils = this.editor.plugins.get( 'ImageUtils' ); const selectedElement = editor.model.document.selection.getSelectedElement(); if ( imageUtils.isImage( selectedElement ) ) { // ... }
-
The
insertImage()
function:- No longer requires the
model
model instance to run. - Allows
Selectable
as a second argument (before onlyPosition
was accepted). - Supports the optional
imageType
argument to force the type of the image to be inserted.
// Before v29.0.0. import { insertImage } from './utils'; const src = 'path/to/image.jpg'; const model = ths.editor.model; const selection = model.document.selection; const position = model.createPositionAt( selection.getSelectedElement() ); insertImage( model, { src }, position ); // Since v29.0.0. const src = 'path/to/image.jpg'; const selection = this.editor.model.document.selection; const imageUtils = this.editor.plugins.get( 'ImageUtils' ); const imageType = 'imageBlock'; imageUtils.insertImage( { src }, selection, imageType );
- No longer requires the
-
The
isImage()
function recognizes both inline and block images (before only block images). -
There are two new helpers:
isBlockImageView()
andisInlineImageView()
.
We removed the following helpers from the public API:
getSelectedImageWidget()
,getViewImgFromWidget()
,isImageAllowed()
,isImageWidget()
,toImageWidget()
# EasyImage
plugin
The EasyImage
plugin is no longer automatically importing the Image
plugin as a dependency. This allows using it alone with either ImageBlock
or ImageInline
without loading the other one.
This decoupling does not have an impact on integrations based on predefined builds or using the CKEditor 5 Builder.
However, for integrations that build the editor from source, this means that to get Easy Image working properly, the Image
plugin (or either the ImageBlock
or ImageInline
plugin) must be imported separately:
import EasyImage from '@ckeditor/ckeditor5-easy-image/src/easyimage';
import Image from '@ckeditor/ckeditor5-image/src/image';
ClassicEditor
.create( document.querySelector( '#editor' ), {
plugins: [ EasyImage, Image, ... ],
toolbar: [ 'uploadImage', ... ],
// ...
} )
.then( ... )
.catch( ... );
Check out the comprehensive installation guide to images in CKEditor 5 to learn more.
# CKFinder
plugin
The CKFinder
plugin is no longer automatically importing the Image
plugin as a dependency. This allows using it alone with either ImageBlock
or ImageInline
without loading the other one.
This decoupling does not have an impact on integrations based on predefined builds or using the CKEditor 5 Builder.
However, for integrations that build the editor from source, this means that to get CKFinder working properly, you must import the Image
plugin (or either the ImageBlock
or ImageInline
plugin) separately:
import CKFinder from '@ckeditor/ckeditor5-ckfinder/src/ckfider';
import Image from '@ckeditor/ckeditor5-image/src/image';
ClassicEditor
.create( document.querySelector( '#editor' ), {
plugins: [ CKFinder, Image, ... ],
toolbar: [ 'uploadImage', ... ],
ckfinder: {
// Feature configuration.
}
} )
.then( ... )
.catch( ... );
Check out the comprehensive installation guide to images in CKEditor 5 to learn more.
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.