Changelog
25.0.0 (2021-01-27)
MAJOR BREAKING CHANGES ℹ️
- comments: The
Annotations
class started operating onAnnotation
instances. Most of its API was changed to support multiple sources of annotations and active annotations. The API for UI management (register()
,switchTo()
, etc.) was moved to the newAnnotationsUIs
class. - comments: All three existing annotation UIs (
InlineAnnotations
,NarrowSidebar
, andWideSidebar
) are using the new annotations API and started operating on the local collections of annotations instead of the global one. Their API has significantly changed. - comments: The
AnnotationsUI
(an interface for annotations UI) has changed. Now it requires theattach( annotations )
,detach()
andsetActiveAnnotation( annotation )
methods and theactiveAnnotation
observable property to be implemented.
See Changes in the Annotations API for more information.
MINOR BREAKING CHANGES ℹ️
- comments: The
Sidebar
API has changed and now it operates on theAnnotation
items from one of annotation UIs. It started adding its newly created items to the collection in theaddAnnotation()
method. - comments: The
EditorAnnotations
class has changed. It started emitting events on actions that might cause changes in the annotations UIs instead of modifying the global collection.
See Changes in the Annotations API for more information.
Features
- comments: Added support for displaying multiple annotation UIs.
Other changes
- comments: Editors will have the
processor
property initialized withHtmlDataProcessor
by default now.
Localization updates
Translations to the Dutch language were updated.
Released packages
Check out the Versioning policy guide for more information.
Released packages (summary)
Major releases (contain major breaking changes):
- @ckeditor/ckeditor5-comments: v24.0.0 => v25.0.0
Other releases:
- @ckeditor/ckeditor5-track-changes: v24.0.0 => v25.0.0
- @ckeditor/letters: v24.0.0 => v25.0.0
- @ckeditor/ckeditor5-collaboration-core: v24.0.0 => v25.0.0
- @ckeditor/ckeditor5-operations-compressor: v24.0.0 => v25.0.0
- @ckeditor/ckeditor5-real-time-collaboration: v24.0.0 => v25.0.0
Changes in the Annotations API
The entire annotations API was redesigned in order to support multiple annotation UIs at the same time. A good example of this is an idea of displaying comments in the sidebar while showing suggestions from track changes in inline balloons when their corresponding suggestions are active. Due to that, some architectural changes were made and quite a lot of breaking changes were introduced with this release. See the migration guide below to check how to adapt to the changes.
Annotations migration guide
Conceptual and architectural changes
- The new annotations API allows for activating (attaching) multiple annotation UIs at the same time. To allow multiple UIs at the same time, the annotation filtering function must be registered during the annotation UI activation. Though, still, one annotation can be handled only by one annotation UI at the same time.
- New annotations API allows for setting multiple active annotations at the same time (max one per each annotation UI), so at some point more than one annotation can be active for various annotation UIs.
- An annotation UI is now activated with its own collection of filtered annotations and became responsible for reacting to more events. This allows for more customization possibilities, however, unfortunately, it comes with more code needed to be written for the custom annotation UI class. After the changes, an annotation UI is responsible for:
- Displaying the annotation.
- Marking the annotation as active when it should be activated and propagating this change via an observable property.
- Reacting to editor events (though this is planned to be changed and simplified in the future).
- Reacting to focus changes in the annotation collection.
- Handling newly added and removed annotations.
- Handling the annotation activation and deactivation from external places via the
setActiveAnnotation()
method.
- The
Annotations
class was split to the newAnnotations
class, which is a global collection of annotations, and the newAnnotationsUIs
class, which is mainly responsible for registering and activating annotation UIs. - In place where the
AnnotationView
had been used, the newAnnotation
class instance is used and it exposes mainly the following properties:target
- The target element to which the annotation should be bound. It can be aRect
instance or an HTML Element.view
- TheAnnotationView
instance.type
- The type of the annotation.isActive
- A property that determines if the annotation view and annotation inner views are active or not. It should be changed by the annotation UI when it changes the active annotation.
The Sidebar
class stopped operating on the global collection of annotations. From now, the Annotation UI that is responsible for displaying the sidebar should provide the sidebar with its collection of annotations and inform about possible actions with the new rearrange()
and refresh()
methods.
The EditorAnnotations
started firing events instead of manipulating the global collection of annotations. From now on, every annotation UI needs to create its own integration with this class. This may change in the future as it complicates the implementation of the custom UI.
Code migration examples
Registering and activating annotation UIs
Before:
const annotations = editor.plugins.get( 'Annotations' );
annotations.register( 'myCustomUI', myCustomUI );
annotations.switchTo( 'myCustomUI' );
// Activate and deactivate the UI.
annotations.attach( 'myCustomUI' );
annotations.detach( 'myCustomUI' );
After:
const annotationsUIs = editor.plugins.get( 'AnnotationsUIs' );
annotationsUIs.register( 'myCustomUI', myCustomUI );
annotationsUIs.switchTo( 'myCustomUI' );
// Activate and deactivate the UI.
annotationsUIs.activate( 'myCustomUI' );
annotationsUIs.deactivate( 'myCustomUI' );
// Activate two different UIs for comments and suggestions.
annotationsUIs.activate( 'wideSidebar', annotation => annotation.type === 'comment' );
annotationsUIs.activate( 'inline', annotation => annotation.type !== 'comment' );
annotationsUIs.deactivateAll();
Using global collection of annotations and active annotations
Before:
const annotations = editor.plugins.get( 'Annotations' );
// An annotation view or `null`.
const activeAnnotationView = annotations.activeView;
// A collection of annotation views.
const annotationViewCollection = annotations.items;
// Adding an annotation to the collection.
const target = new Rect( { left: 0, top: 0 } );
annotations.add( innerView, target );
// Removing an annotation based on the inner view.
annotations.remove( innerView );
After:
const annotations = editor.plugins.get( 'Annotations' );
// A set of active annotations.
const activeAnnotations = annotations.activeAnnotations;
// An array of active annotation views.
Array.from( activeAnnotations, annotation => annotation.view );
// A collection of annotations (`Annotation` class items).
const annotationCollection = annotations.collection;
// Adding an annotation to the collection.
annotations.add( new Annotation( {
view: new AnnotationView( innerView ),
target: new Rect( { left: 0, top: 0 } ),
type: 'comment' // The type is used only for the AnnotationsUIs filtering mechanism.
} ) );
// Removing an annotation based on the inner view.
const annotation = annotations.getByInnerView( innerView );
annotations.remove( annotation );
Creating a custom Annotations UI
Before:
class CustomAnnotationUI {
attach() {
const annotations = this.editor.plugins.get( 'Annotations' );
// The code responsible for displaying annotations
// based on the global collection of annotations.
}
detach() {
// The code responsible for hiding the UI and detaching
// listeners from the global annotation collection.
}
}
After:
class CustomAnnotationUI extends ContextPlugin {
constructor() {
this.set( 'activeAnnotation', null );
}
setActiveAnnotation( annotation ) {
// The code responsible for reacting to annotation changes.
if ( annotation === this.activeAnnotation ) {
return;
}
if ( this.activeAnnotation ) {
this.activeAnnotation.isActive = false;
}
if ( annotation ) {
annotation.isActive = true;
}
this.activeAnnotation = annotation;
}
attach( annotations ) {
// The code responsible for displaying annotations
// based on the annotation collection passed to this UI.
// The code responsible for setting an active and non-active annotation based on the annotation focus changes.
this.listenTo( annotations, 'focus', ( evt, annotation ) => {
this.setActiveAnnotation( annotation );
} );
this.listenTo( annotations, 'blur', () => {
this.setActiveAnnotation( null );
} );
// The code responsible for the integration with editor annotation markers,
// editor events and the editor selection changes.
// The requirement of this integration might change in the future.
// // If the plugin was initialized as an editor plugin, the integration should look like the following:
const editorAnnotations = editor.plugins.get( 'EditorAnnotations' );
this.listenTo( editorAnnotations, 'refresh', () => refreshActiveAnnotation.bind( this ) );
this.listenTo( editorAnnotations, 'blur' ( evt, { isAnnotationTracked } ) => {
if ( this.activeAnnotation && isAnnotationTracked( this.activeAnnotation ) ) {
this.setActiveAnnotation( null );
}
} );
this.listenTo( editorAnnotations, 'uiUpdate' () => annotations._refreshPositioning();
function refreshActiveAnnotation() {
const selectedAnnotations = editorAnnotations.getOrderedSelectedAnnotations( {
annotations: this._annotations,
activeAnnotation: this.activeAnnotation
} );
this.setActiveAnnotation( selectedAnnotations[ 0 ] || null );
}
}
detach() {
// The code responsible for hiding the UI and detaching
// listeners from the annotation collection, editor annotations and others.
}
}
24.0.0 (2020-12-09)
Features
- track-changes: Added support for table cell styles while pasting table cells in the track changes mode.
- track-changes Introduced the
showSuggestionHighlights
option ineditor.getData()
that changes the suggestion marker conversion and allows styling the suggestions in the output. This allows for highlighting a suggestion after exporting to PDF. - track-changes Introduced the
editorConfig.trackChanges.disableComments
option that disallows commenting on suggestions and hides comments UI in the suggestion annotation view. - track-changes, comments Introduced the
.attributes
property for comments and suggestions, which can store arbitrary custom data together with other comment/suggestion data.
Bug fixes
- track-changes Redoing table cell paste after undo will restore markers to the original ranges.
- track-changes: Fixed incorrectly created format suggestions when created on a selection containing empty table cells.
- track-changes: Fixed scenarios when a multi-cell suggestion was not highlighted when the selection was placed inside a cell from that suggestion.
- track-changes: Block quote suggestions were set on incorrect cells when adding a block quote to multiple cells.
Other changes
- track-changes: Improved performance of multi-cell selections in track changes mode.
Localization updates
New translations are available for the following languages:
Hungarian, German, Australian English, French, Estonian, Ukrainian, Galician, Italian, Slovak, Serbian, Serbian (Latin), Chinese
Released packages
Check out the Versioning policy guide for more information.
Released packages (summary)
- @ckeditor/ckeditor5-collaboration-core: v23.1.0 => v24.0.0
- @ckeditor/ckeditor5-comments: v23.1.0 => v24.0.0
- @ckeditor/ckeditor5-real-time-collaboration: v23.1.0 => v24.0.0
- @ckeditor/ckeditor5-track-changes: v23.1.0 => v24.0.0
- @ckeditor/ckeditor5-operations-compressor: v23.1.0 => v24.0.0
- @ckeditor/letters: v23.1.0 => v24.0.0
23.1.0 (2020-10-26)
Features
- Added support for pasting a table into a table in track changes mode.
Bug fixes
- Editor should not crash while removing row with horizontally spanned cells in track changes mode.
- Editor should not crash on splitting a cell selected from the outside in track changes mode.
Other changes
<suggestion-td>
element was introduced to mark table cells paste suggestion. It is returned in the editor data, inside table cell elements, to separate new (pasted) and old cell content.
Localization updates
New translations are available for the following languages:
Chinese, French, Italian, Persian
23.0.0 (2020-09-25)
Features
- Introduced support for importing documents and receiving initial data from the Cloud Services server in real-time collaborative editing.
Bug fixes
- Fixed crash that happened when an editor with multiple annotations was destroyed.
Other changes
- Added support for custom headings in track changes mode.
22.0.0 (2020-08-25)
Features
- Introduced the
TrackChangesData
plugin which returns the editor data with all suggestions accepted or rejected. - Introduced the
sidebar.preventScrollOutOfView
configuration option that prevents sidebar items from being moved out of sight (above the sidebar top edge).
Other
- Changed the annotations positioning algorithms.
Localization updates
New translations are available for the following languages:
Dutch, Korean, Russian, Ukrainian
21.0.0 (2020-07-24)
BREAKING CHANGES
- The comments and track changes features now use the recently introduced marker-to-data conversion. This means that the comment and suggestion markers included in the document data returned from the editor will be different than before. The change is backward compatible with regards to old documents you have already saved in your database. These documents will be correctly processed by the editor, however, upon saving, the document data will be returned in the new format.
Features
- Integrated multi-cell table selection with track changes.
- Enabled multi-cell table selection in real-time collaboration.
Bug fixes
- Passing
Rect
or a callback returningRect
as an annotation target should work now correctly. - An active suggestion should always be highlighted and visible in the editor content. This concerns cases with multiple suggestions on the same part of the content.
- Fixed incorrect suggestion description for space character deletion.
- Enabling part of the content for restricted editing in track changes mode was crashing the editor.
- Fixed a crash happening when the remove row and remove column suggestions were accepted at the same time.
Other changes
- Switched from marker-to-element conversion to marker-to-data conversion.
Localization updates
New translations are available for the following languages:
Brazilian Portuguese, Chinese, Polish, Turkmen, Uighur
20.0.1 (2020-06-26)
Bug fixes
Fixed an error that occurred under certain conditions when opening a document with comments and real-time collaboration enabled. It could lead to losing all comments added to the document.
This was a regression that occurred only in version 20.0.0. It is strongly recommended to upgrade this package to version 20.0.1.
20.0.0 (2020-06-23)
BREAKING CHANGES
- Comment marker names format has been changed. It was
comment:<commentId>
, now it iscomment:<commentId>:<uniqueId>
. This change is related to enabling multi-range comments.
Features
- Introduced support for multi-range comments (multi-cell comments in tables).
Bug fixes
- Fixed a crash happening when an element was inserted after a paragraph insertion suggestion.
- Incorrect comment was activated after creating a second comment on the same element or range.
Notes
At the moment, multi-cell selection and multi-cell comments are supported only without real-time collaboration and when track changes is turned off.
Localization updates
New translations are available for the following languages:
Chinese (China), Slovak.
19.1.0 (2020-05-25)
Features
- Integration for typing around widgets (inserting paragraphs before/after a widget).
- Incorrect comment was activated after creating a second comment on the same element or range.
Localization updates
New translations are available for the following languages:
Australian English, Brazilian Portuguese, Croatian, French, Galician, German, Hungarian, Italian, Japanese, Norwegian, Russian, Serbian, Serbian (Latin), Turkish.
We would like to thank everyone who contributed to these translations!
19.0.1 (2020-04-30)
BREAKING CHANGES
-
AnnotationView#active
was renamed to#isActive
. -
AnnotationView#hasChanges
was renamed to#isDirty
. - Due to changes in how comments are loaded for suggestions, comments now need to be loaded before suggestions in the "load and save" integration type (non-adapter integration).
-
Users#me
is now set tonull
ifUsers#defineMe()
orUsers#useAnonymousUser()
was not called.
Features
- Introduced customizable annotation views.
- Introduced translations for Collaboration Features.
- Introduced
Users#useAnonymousUser()
andconfig.users.anonymousUserId
.
Bug fixes
- User selection marker will now be properly removed when the user switches to a different editor instance or a form field.
- Fixed incorrect accepting and discarding of table row or column suggestions that were in the initial data.
Other changes
-
Users#me
will no longer set the local user to anonymous by default (ifUsers#defineMe()
was not called).
18.0.0 (2020-03-19)
Features
- Introduced the
skipEmpty
parameter inCommentsRepository#getCommentThreads()
.
Bug fixes
- Fixed incorrect suggestion description when styling (e.g. bold) was applied to the whole table.
- Fixed incorrectly created inline formatting suggestion set on a table that had insertion suggestions inside.
- Fixed incorrectly highlighted suggestions for table row or column insertion and deletion.
- Fixed contextual balloon glitches happening when switching from inline annotations to sidebar UI while displaying a comment.
- Fixed the editor crashing during the initial data load in some scenarios involving the track changes adapter.
- Fixed a bug causing new comments to be added with an "Invalid date".
- Comment threads for suggestions will now be correctly returned by
CommentsRepository#getCommentThreads()
. - Connection errors will no longer permanently crash the editor on Firefox and Safari.
- Introduced a synchronization mechanism to fix comments feature errors happening after reconnecting to the document.
- Fixed the editor crash in the track changes feature happening in scenarios involving reconnection.
- Fixed issues with the editor data, comments and presence list not being properly updated after the editor reconnected to the real-time collaboration server.
Other
- Methods marked as deprecated in release 17.0.0 will be removed in the next release instead of in this release.
17.0.0 (2020-02-20)
BREAKING CHANGES
- New configuration parameter
config.collaboration.channelId
was introduced in place ofconfig.cloudServices.documentId
which got deprecated and will be removed in the next release. - If you use
Context
in your application, context plugins should be added to the context configuration instead of the editor configuration. The following plugins were changed to context plugins:-
Annotations
, -
CommentsRepository
, -
WideSidebar
, -
NarrowSidebar
, -
Sessions
, -
PresenceList
, -
CloudServicesCommentsAdapter
. Note thatCloudServicesCommentsAdapter
needs to be added to the context configuration even if you are passing real-time collaboration plugins in the editor configuration.
-
Comments
- The following commands were removed:
-
addComment
, -
removeComment
, -
removeCommentThread
, -
updateComment
.
-
- The only editor command used by the comments feature is
addCommentThread
. It is now the responsibility ofCommentsRepository
to operate on comments. If your integration extended the removed commands, you should now integrate with theCommentsRepository
API. - The previous API available for the
Comments
plugin was deprecated and will be removed in the next release. TheCommentsRepository
API should be used instead. - The comments adapter methods changed accepted parameters and returned values. See the documentation and align your integration with the changes.
- The comments adapter now requires a new
removeCommentThread()
method, which should remove the entire comment thread. If you use a custom comments adapter and would like to support comments outside the editor, you will need to provide this method.
Track changes
- Stylesheets for suggestions were cleaned up. If you are using custom styles, please refer to the documentation to see what CSS variables can now be used.
Real-time collaboration
-
Sessions#connectedUsers
was replaced withSessions#allConnectedUsers
. -
Sessions#sessions
was replaced withSessions#channelSessions
. -
Sessions#getUserSessions()
now requires a second parameter,channelId
. -
Sessions#channelConnectedUsers
is now available to get users connected only to a given channel.
Refer to the Sessions
API documentation to learn about the new API.
Known issues
-
Comments#getCommentThreads()
andCommentsRepository#getCommentThreads( { skipNotAttached: true } )
are not returning comment threads added to suggestions. Instead, useCommentsRepository#getCommentThreads( { skipNotAttached: false } )
and filter comment threads by their IDs, comparing them to IDs returned byTrackChanges#getSuggestions()
. -
NarrowSidebar
andWideSidebar
need to be added to a context in integrations using multiple editors.
Features
Comments
- Opened the comments feature API. Enabled creating comments on form fields and other DOM elements outside the editor. Please refer to the documentation to learn about all introduced changes.
- Introduced
CommentsRepository
which is a context plugin that handles comments. It introduces the API to operate on comments and can be used outside or without an editor instance. -
Annotations
became a context plugin and can be used outside or without an editor instance.
Track changes
- Added support for the image resize feature.
- Added support for the soft break (Shift+Enter) feature.
- Added support for the horizontal line feature.
- Added support for the page break feature.
- Added support for the restricted editing feature.
Real-time collaboration
- Introduced the
config.cloudServices.bundleVersion
configuration parameter.
Bug fixes
Track changes
- Fixed the suggestion description for the title element.
Other changes
Track changes
- Cleaned up track changes suggestion marker styles.
- Improved suggestion descriptions for suggestions on/in tables. Now, the description will show the text contained in the suggestion.
- Improved the behavior of the track changes split button. The dropdown will not be disabled if there is at least one enabled item inside it.
Real-time collaboration
- The sessions plugin was changed to a context plugin and now handles connection to multiple channel IDs.
- Presence list became a context plugin and will show all users connected to all editor instances operating in the same context.