@ckeditor/ckeditor5-engine 31.1.0 → 34.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/LICENSE.md +2 -2
  2. package/README.md +2 -1
  3. package/package.json +25 -25
  4. package/src/controller/datacontroller.js +65 -74
  5. package/src/controller/editingcontroller.js +83 -6
  6. package/src/conversion/conversion.js +15 -14
  7. package/src/conversion/conversionhelpers.js +1 -1
  8. package/src/conversion/downcastdispatcher.js +298 -367
  9. package/src/conversion/downcasthelpers.js +860 -81
  10. package/src/conversion/mapper.js +105 -60
  11. package/src/conversion/modelconsumable.js +85 -35
  12. package/src/conversion/upcastdispatcher.js +34 -7
  13. package/src/conversion/upcasthelpers.js +4 -2
  14. package/src/conversion/viewconsumable.js +1 -1
  15. package/src/dataprocessor/basichtmlwriter.js +1 -1
  16. package/src/dataprocessor/dataprocessor.jsdoc +1 -1
  17. package/src/dataprocessor/htmldataprocessor.js +9 -31
  18. package/src/dataprocessor/htmlwriter.js +1 -1
  19. package/src/dataprocessor/xmldataprocessor.js +1 -1
  20. package/src/dev-utils/model.js +16 -14
  21. package/src/dev-utils/operationreplayer.js +1 -1
  22. package/src/dev-utils/utils.js +1 -1
  23. package/src/dev-utils/view.js +1 -1
  24. package/src/index.js +8 -1
  25. package/src/model/batch.js +77 -10
  26. package/src/model/differ.js +115 -69
  27. package/src/model/document.js +13 -4
  28. package/src/model/documentfragment.js +1 -1
  29. package/src/model/documentselection.js +1 -1
  30. package/src/model/element.js +1 -1
  31. package/src/model/history.js +1 -1
  32. package/src/model/item.jsdoc +1 -1
  33. package/src/model/liveposition.js +1 -1
  34. package/src/model/liverange.js +1 -1
  35. package/src/model/markercollection.js +29 -5
  36. package/src/model/model.js +138 -12
  37. package/src/model/node.js +1 -1
  38. package/src/model/nodelist.js +1 -1
  39. package/src/model/operation/attributeoperation.js +1 -1
  40. package/src/model/operation/detachoperation.js +1 -1
  41. package/src/model/operation/insertoperation.js +1 -1
  42. package/src/model/operation/markeroperation.js +1 -1
  43. package/src/model/operation/mergeoperation.js +1 -1
  44. package/src/model/operation/moveoperation.js +1 -1
  45. package/src/model/operation/nooperation.js +1 -1
  46. package/src/model/operation/operation.js +1 -1
  47. package/src/model/operation/operationfactory.js +1 -1
  48. package/src/model/operation/renameoperation.js +1 -1
  49. package/src/model/operation/rootattributeoperation.js +1 -1
  50. package/src/model/operation/splitoperation.js +1 -1
  51. package/src/model/operation/transform.js +1 -1
  52. package/src/model/operation/utils.js +1 -1
  53. package/src/model/position.js +1 -1
  54. package/src/model/range.js +1 -1
  55. package/src/model/rootelement.js +1 -1
  56. package/src/model/schema.js +80 -11
  57. package/src/model/selection.js +1 -1
  58. package/src/model/text.js +1 -1
  59. package/src/model/textproxy.js +1 -1
  60. package/src/model/treewalker.js +3 -4
  61. package/src/model/utils/autoparagraphing.js +1 -1
  62. package/src/model/utils/deletecontent.js +16 -3
  63. package/src/model/utils/findoptimalinsertionrange.js +68 -0
  64. package/src/model/utils/getselectedcontent.js +1 -1
  65. package/src/model/utils/insertcontent.js +1 -1
  66. package/src/model/utils/insertobject.js +173 -0
  67. package/src/model/utils/modifyselection.js +15 -8
  68. package/src/model/utils/selection-post-fixer.js +1 -1
  69. package/src/model/writer.js +17 -27
  70. package/src/view/attributeelement.js +1 -11
  71. package/src/view/containerelement.js +1 -1
  72. package/src/view/document.js +3 -2
  73. package/src/view/documentfragment.js +1 -1
  74. package/src/view/documentselection.js +1 -1
  75. package/src/view/domconverter.js +55 -28
  76. package/src/view/downcastwriter.js +91 -50
  77. package/src/view/editableelement.js +1 -1
  78. package/src/view/element.js +1 -28
  79. package/src/view/elementdefinition.jsdoc +1 -1
  80. package/src/view/emptyelement.js +1 -4
  81. package/src/view/filler.js +1 -1
  82. package/src/view/item.jsdoc +1 -1
  83. package/src/view/matcher.js +3 -3
  84. package/src/view/node.js +1 -1
  85. package/src/view/observer/arrowkeysobserver.js +1 -1
  86. package/src/view/observer/bubblingemittermixin.js +1 -1
  87. package/src/view/observer/bubblingeventinfo.js +1 -1
  88. package/src/view/observer/clickobserver.js +1 -2
  89. package/src/view/observer/compositionobserver.js +1 -1
  90. package/src/view/observer/domeventdata.js +1 -1
  91. package/src/view/observer/domeventobserver.js +1 -1
  92. package/src/view/observer/fakeselectionobserver.js +1 -1
  93. package/src/view/observer/focusobserver.js +1 -1
  94. package/src/view/observer/inputobserver.js +2 -2
  95. package/src/view/observer/keyobserver.js +1 -1
  96. package/src/view/observer/mouseobserver.js +1 -1
  97. package/src/view/observer/mutationobserver.js +1 -1
  98. package/src/view/observer/observer.js +1 -1
  99. package/src/view/observer/selectionobserver.js +1 -1
  100. package/src/view/observer/tabobserver.js +68 -0
  101. package/src/view/placeholder.js +2 -2
  102. package/src/view/position.js +1 -1
  103. package/src/view/range.js +1 -1
  104. package/src/view/rawelement.js +1 -4
  105. package/src/view/renderer.js +3 -2
  106. package/src/view/rooteditableelement.js +1 -1
  107. package/src/view/selection.js +1 -1
  108. package/src/view/styles/background.js +1 -1
  109. package/src/view/styles/border.js +1 -1
  110. package/src/view/styles/margin.js +1 -1
  111. package/src/view/styles/padding.js +1 -1
  112. package/src/view/styles/utils.js +1 -1
  113. package/src/view/stylesmap.js +1 -1
  114. package/src/view/text.js +1 -1
  115. package/src/view/textproxy.js +1 -1
  116. package/src/view/treewalker.js +1 -1
  117. package/src/view/uielement.js +1 -4
  118. package/src/view/upcastwriter.js +1 -1
  119. package/src/view/view.js +5 -1
  120. package/theme/placeholder.css +10 -1
  121. package/theme/renderer.css +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
 
@@ -58,11 +58,12 @@ export default class Differ {
58
58
  * A map that stores all changed markers.
59
59
  *
60
60
  * The keys of the map are marker names.
61
- * The values of the map are objects with the `oldRange` and `newRange` properties. They store the marker range
62
- * state before and after the change.
61
+ * The values of the map are objects with the following properties:
62
+ * - `oldMarkerData`,
63
+ * - `newMarkerData`.
63
64
  *
64
65
  * @private
65
- * @type {Map}
66
+ * @type {Map.<String, Object>}
66
67
  */
67
68
  this._changedMarkers = new Map();
68
69
 
@@ -98,6 +99,14 @@ export default class Differ {
98
99
  * @type {Array.<Object>|null}
99
100
  */
100
101
  this._cachedChangesWithGraveyard = null;
102
+
103
+ /**
104
+ * Set of model items that were marked to get refreshed in {@link #_refreshItem}.
105
+ *
106
+ * @private
107
+ * @type {Set.<module:engine/model/item~Item>}
108
+ */
109
+ this._refreshedItems = new Set();
101
110
  }
102
111
 
103
112
  /**
@@ -110,32 +119,6 @@ export default class Differ {
110
119
  return this._changesInElement.size == 0 && this._changedMarkers.size == 0;
111
120
  }
112
121
 
113
- /**
114
- * Marks given `item` in differ to be "refreshed". It means that the item will be marked as removed and inserted in the differ changes
115
- * set, so it will be effectively re-converted when differ changes will be handled by a dispatcher.
116
- *
117
- * @param {module:engine/model/item~Item} item Item to refresh.
118
- */
119
- refreshItem( item ) {
120
- if ( this._isInInsertedElement( item.parent ) ) {
121
- return;
122
- }
123
-
124
- this._markRemove( item.parent, item.startOffset, item.offsetSize );
125
- this._markInsert( item.parent, item.startOffset, item.offsetSize );
126
-
127
- const range = Range._createOn( item );
128
-
129
- for ( const marker of this._markerCollection.getMarkersIntersectingRange( range ) ) {
130
- const markerRange = marker.getRange();
131
-
132
- this.bufferMarkerChange( marker.name, markerRange, markerRange, marker.affectsData );
133
- }
134
-
135
- // Clear cache after each buffered operation as it is no longer valid.
136
- this._cachedChanges = null;
137
- }
138
-
139
122
  /**
140
123
  * Buffers the given operation. An operation has to be buffered before it is executed.
141
124
  *
@@ -208,9 +191,9 @@ export default class Differ {
208
191
  const range = Range._createFromPositionAndShift( operation.position, 1 );
209
192
 
210
193
  for ( const marker of this._markerCollection.getMarkersIntersectingRange( range ) ) {
211
- const markerRange = marker.getRange();
194
+ const markerData = marker.getData();
212
195
 
213
- this.bufferMarkerChange( marker.name, markerRange, markerRange, marker.affectsData );
196
+ this.bufferMarkerChange( marker.name, markerData, markerData );
214
197
  }
215
198
 
216
199
  break;
@@ -267,27 +250,23 @@ export default class Differ {
267
250
  * Buffers a marker change.
268
251
  *
269
252
  * @param {String} markerName The name of the marker that changed.
270
- * @param {module:engine/model/range~Range|null} oldRange Marker range before the change or `null` if the marker has just
271
- * been created.
272
- * @param {module:engine/model/range~Range|null} newRange Marker range after the change or `null` if the marker was removed.
273
- * @param {Boolean} affectsData Flag indicating whether marker affects the editor data.
253
+ * @param {module:engine/model/markercollection~MarkerData} oldMarkerData Marker data before the change.
254
+ * @param {module:engine/model/markercollection~MarkerData} newMarkerData Marker data after the change.
274
255
  */
275
- bufferMarkerChange( markerName, oldRange, newRange, affectsData ) {
256
+ bufferMarkerChange( markerName, oldMarkerData, newMarkerData ) {
276
257
  const buffered = this._changedMarkers.get( markerName );
277
258
 
278
259
  if ( !buffered ) {
279
260
  this._changedMarkers.set( markerName, {
280
- oldRange,
281
- newRange,
282
- affectsData
261
+ newMarkerData,
262
+ oldMarkerData
283
263
  } );
284
264
  } else {
285
- buffered.newRange = newRange;
286
- buffered.affectsData = affectsData;
265
+ buffered.newMarkerData = newMarkerData;
287
266
 
288
- if ( buffered.oldRange == null && buffered.newRange == null ) {
289
- // The marker is going to be removed (`newRange == null`) but it did not exist before the first buffered change
290
- // (`buffered.oldRange == null`). In this case, do not keep the marker in buffer at all.
267
+ if ( buffered.oldMarkerData.range == null && newMarkerData.range == null ) {
268
+ // The marker is going to be removed (`newMarkerData.range == null`) but it did not exist before the first buffered change
269
+ // (`buffered.oldMarkerData.range == null`). In this case, do not keep the marker in buffer at all.
291
270
  this._changedMarkers.delete( markerName );
292
271
  }
293
272
  }
@@ -302,8 +281,8 @@ export default class Differ {
302
281
  const result = [];
303
282
 
304
283
  for ( const [ name, change ] of this._changedMarkers ) {
305
- if ( change.oldRange != null ) {
306
- result.push( { name, range: change.oldRange } );
284
+ if ( change.oldMarkerData.range != null ) {
285
+ result.push( { name, range: change.oldMarkerData.range } );
307
286
  }
308
287
  }
309
288
 
@@ -319,8 +298,8 @@ export default class Differ {
319
298
  const result = [];
320
299
 
321
300
  for ( const [ name, change ] of this._changedMarkers ) {
322
- if ( change.newRange != null ) {
323
- result.push( { name, range: change.newRange } );
301
+ if ( change.newMarkerData.range != null ) {
302
+ result.push( { name, range: change.newMarkerData.range } );
324
303
  }
325
304
  }
326
305
 
@@ -333,12 +312,12 @@ export default class Differ {
333
312
  * @returns {Array.<Object>}
334
313
  */
335
314
  getChangedMarkers() {
336
- return Array.from( this._changedMarkers ).map( item => (
315
+ return Array.from( this._changedMarkers ).map( ( [ name, change ] ) => (
337
316
  {
338
- name: item[ 0 ],
317
+ name,
339
318
  data: {
340
- oldRange: item[ 1 ].oldRange,
341
- newRange: item[ 1 ].newRange
319
+ oldRange: change.oldMarkerData.range,
320
+ newRange: change.newMarkerData.range
342
321
  }
343
322
  }
344
323
  ) );
@@ -351,19 +330,33 @@ export default class Differ {
351
330
  *
352
331
  * * model structure changes,
353
332
  * * attribute changes,
354
- * * changes of markers which were defined as `affectingData`.
333
+ * * changes of markers which were defined as `affectsData`,
334
+ * * changes of markers' `affectsData` property.
355
335
  *
356
336
  * @returns {Boolean}
357
337
  */
358
338
  hasDataChanges() {
359
- for ( const [ , change ] of this._changedMarkers ) {
360
- if ( change.affectsData ) {
339
+ if ( this._changesInElement.size > 0 ) {
340
+ return true;
341
+ }
342
+
343
+ for ( const { newMarkerData, oldMarkerData } of this._changedMarkers.values() ) {
344
+ if ( newMarkerData.affectsData !== oldMarkerData.affectsData ) {
361
345
  return true;
362
346
  }
347
+
348
+ if ( newMarkerData.affectsData ) {
349
+ const markerAdded = newMarkerData.range && !oldMarkerData.range;
350
+ const markerRemoved = !newMarkerData.range && oldMarkerData.range;
351
+ const markerChanged = newMarkerData.range && oldMarkerData.range && !newMarkerData.range.isEqual( oldMarkerData.range );
352
+
353
+ if ( markerAdded || markerRemoved || markerChanged ) {
354
+ return true;
355
+ }
356
+ }
363
357
  }
364
358
 
365
- // If markers do not affect the data, check whether there are some changes in elements.
366
- return this._changesInElement.size > 0;
359
+ return false;
367
360
  }
368
361
 
369
362
  /**
@@ -430,12 +423,12 @@ export default class Differ {
430
423
  for ( const action of actions ) {
431
424
  if ( action === 'i' ) {
432
425
  // Generate diff item for this element and insert it into the diff set.
433
- diffSet.push( this._getInsertDiff( element, i, elementChildren[ i ].name ) );
426
+ diffSet.push( this._getInsertDiff( element, i, elementChildren[ i ] ) );
434
427
 
435
428
  i++;
436
429
  } else if ( action === 'r' ) {
437
430
  // Generate diff item for this element and insert it into the diff set.
438
- diffSet.push( this._getRemoveDiff( element, i, snapshotChildren[ j ].name ) );
431
+ diffSet.push( this._getRemoveDiff( element, i, snapshotChildren[ j ] ) );
439
432
 
440
433
  j++;
441
434
  } else if ( action === 'a' ) {
@@ -540,16 +533,25 @@ export default class Differ {
540
533
  this._changeCount = 0;
541
534
 
542
535
  // Cache changes.
543
- this._cachedChangesWithGraveyard = diffSet.slice();
536
+ this._cachedChangesWithGraveyard = diffSet;
544
537
  this._cachedChanges = diffSet.filter( _changesInGraveyardFilter );
545
538
 
546
539
  if ( options.includeChangesInGraveyard ) {
547
- return this._cachedChangesWithGraveyard;
540
+ return this._cachedChangesWithGraveyard.slice();
548
541
  } else {
549
- return this._cachedChanges;
542
+ return this._cachedChanges.slice();
550
543
  }
551
544
  }
552
545
 
546
+ /**
547
+ * Returns a set of model items that were marked to get refreshed.
548
+ *
549
+ * @return {Set.<module:engine/model/item~Item>}
550
+ */
551
+ getRefreshedItems() {
552
+ return new Set( this._refreshedItems );
553
+ }
554
+
553
555
  /**
554
556
  * Resets `Differ`. Removes all buffered changes.
555
557
  */
@@ -557,6 +559,36 @@ export default class Differ {
557
559
  this._changesInElement.clear();
558
560
  this._elementSnapshots.clear();
559
561
  this._changedMarkers.clear();
562
+ this._refreshedItems = new Set();
563
+ this._cachedChanges = null;
564
+ }
565
+
566
+ /**
567
+ * Marks the given `item` in differ to be "refreshed". It means that the item will be marked as removed and inserted
568
+ * in the differ changes set, so it will be effectively re-converted when the differ changes are handled by a dispatcher.
569
+ *
570
+ * @protected
571
+ * @param {module:engine/model/item~Item} item Item to refresh.
572
+ */
573
+ _refreshItem( item ) {
574
+ if ( this._isInInsertedElement( item.parent ) ) {
575
+ return;
576
+ }
577
+
578
+ this._markRemove( item.parent, item.startOffset, item.offsetSize );
579
+ this._markInsert( item.parent, item.startOffset, item.offsetSize );
580
+
581
+ this._refreshedItems.add( item );
582
+
583
+ const range = Range._createOn( item );
584
+
585
+ for ( const marker of this._markerCollection.getMarkersIntersectingRange( range ) ) {
586
+ const markerData = marker.getData();
587
+
588
+ this.bufferMarkerChange( marker.name, markerData, markerData );
589
+ }
590
+
591
+ // Clear cache after each buffered operation as it is no longer valid.
560
592
  this._cachedChanges = null;
561
593
  }
562
594
 
@@ -897,14 +929,15 @@ export default class Differ {
897
929
  * @private
898
930
  * @param {module:engine/model/element~Element} parent The element in which the change happened.
899
931
  * @param {Number} offset The offset at which change happened.
900
- * @param {String} name The name of the removed element or `'$text'` for a character.
932
+ * @param {Object} elementSnapshot The snapshot of the removed element a character.
901
933
  * @returns {Object} The diff item.
902
934
  */
903
- _getInsertDiff( parent, offset, name ) {
935
+ _getInsertDiff( parent, offset, elementSnapshot ) {
904
936
  return {
905
937
  type: 'insert',
906
938
  position: Position._createAt( parent, offset ),
907
- name,
939
+ name: elementSnapshot.name,
940
+ attributes: new Map( elementSnapshot.attributes ),
908
941
  length: 1,
909
942
  changeCount: this._changeCount++
910
943
  };
@@ -916,14 +949,15 @@ export default class Differ {
916
949
  * @private
917
950
  * @param {module:engine/model/element~Element} parent The element in which change happened.
918
951
  * @param {Number} offset The offset at which change happened.
919
- * @param {String} name The name of the removed element or `'$text'` for a character.
952
+ * @param {Object} elementSnapshot The snapshot of the removed element a character.
920
953
  * @returns {Object} The diff item.
921
954
  */
922
- _getRemoveDiff( parent, offset, name ) {
955
+ _getRemoveDiff( parent, offset, elementSnapshot ) {
923
956
  return {
924
957
  type: 'remove',
925
958
  position: Position._createAt( parent, offset ),
926
- name,
959
+ name: elementSnapshot.name,
960
+ attributes: new Map( elementSnapshot.attributes ),
927
961
  length: 1,
928
962
  changeCount: this._changeCount++
929
963
  };
@@ -1201,6 +1235,12 @@ function _changesInGraveyardFilter( entry ) {
1201
1235
  * @member {String} module:engine/model/differ~DiffItemInsert#name
1202
1236
  */
1203
1237
 
1238
+ /**
1239
+ * Map of attributes that were set on the item while it was inserted.
1240
+ *
1241
+ * @member {Map.<String,*>} module:engine/model/differ~DiffItemInsert#attributes
1242
+ */
1243
+
1204
1244
  /**
1205
1245
  * The position where the node was inserted.
1206
1246
  *
@@ -1232,6 +1272,12 @@ function _changesInGraveyardFilter( entry ) {
1232
1272
  * @member {String} module:engine/model/differ~DiffItemRemove#name
1233
1273
  */
1234
1274
 
1275
+ /**
1276
+ * Map of attributes that were set on the item while it was removed.
1277
+ *
1278
+ * @member {Map.<String,*>} module:engine/model/differ~DiffItemRemove#attributes
1279
+ */
1280
+
1235
1281
  /**
1236
1282
  * The position where the node was removed.
1237
1283
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
 
@@ -157,14 +157,23 @@ export default class Document {
157
157
  // Buffer marker changes.
158
158
  // This is not covered in buffering operations because markers may change outside of them (when they
159
159
  // are modified using `model.markers` collection, not through `MarkerOperation`).
160
- this.listenTo( model.markers, 'update', ( evt, marker, oldRange, newRange ) => {
160
+ this.listenTo( model.markers, 'update', ( evt, marker, oldRange, newRange, oldMarkerData ) => {
161
+ // Copy the `newRange` to the new marker data as during the marker removal the range is not updated.
162
+ const newMarkerData = { ...marker.getData(), range: newRange };
163
+
161
164
  // Whenever marker is updated, buffer that change.
162
- this.differ.bufferMarkerChange( marker.name, oldRange, newRange, marker.affectsData );
165
+ this.differ.bufferMarkerChange( marker.name, oldMarkerData, newMarkerData );
163
166
 
164
167
  if ( oldRange === null ) {
165
168
  // If this is a new marker, add a listener that will buffer change whenever marker changes.
166
169
  marker.on( 'change', ( evt, oldRange ) => {
167
- this.differ.bufferMarkerChange( marker.name, oldRange, marker.getRange(), marker.affectsData );
170
+ const markerData = marker.getData();
171
+
172
+ this.differ.bufferMarkerChange(
173
+ marker.name,
174
+ { ...markerData, range: oldRange },
175
+ markerData
176
+ );
168
177
  } );
169
178
  }
170
179
  } );
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
5
 
@@ -106,6 +106,8 @@ export default class MarkerCollection {
106
106
  const oldMarker = this._markers.get( markerName );
107
107
 
108
108
  if ( oldMarker ) {
109
+ const oldMarkerData = oldMarker.getData();
110
+
109
111
  const oldRange = oldMarker.getRange();
110
112
  let hasChanged = false;
111
113
 
@@ -125,7 +127,7 @@ export default class MarkerCollection {
125
127
  }
126
128
 
127
129
  if ( hasChanged ) {
128
- this.fire( 'update:' + markerName, oldMarker, oldRange, range );
130
+ this.fire( 'update:' + markerName, oldMarker, oldRange, range, oldMarkerData );
129
131
  }
130
132
 
131
133
  return oldMarker;
@@ -135,7 +137,7 @@ export default class MarkerCollection {
135
137
  const marker = new Marker( markerName, liveRange, managedUsingOperations, affectsData );
136
138
 
137
139
  this._markers.set( markerName, marker );
138
- this.fire( 'update:' + markerName, marker, null, range );
140
+ this.fire( 'update:' + markerName, marker, null, range, { ...marker.getData(), range: null } );
139
141
 
140
142
  return marker;
141
143
  }
@@ -154,7 +156,7 @@ export default class MarkerCollection {
154
156
 
155
157
  if ( oldMarker ) {
156
158
  this._markers.delete( markerName );
157
- this.fire( 'update:' + markerName, oldMarker, oldMarker.getRange(), null );
159
+ this.fire( 'update:' + markerName, oldMarker, oldMarker.getRange(), null, oldMarker.getData() );
158
160
 
159
161
  this._destroyMarker( oldMarker );
160
162
 
@@ -188,7 +190,7 @@ export default class MarkerCollection {
188
190
 
189
191
  const range = marker.getRange();
190
192
 
191
- this.fire( 'update:' + markerName, marker, range, range, marker.managedUsingOperations, marker.affectsData );
193
+ this.fire( 'update:' + markerName, marker, range, range, marker.getData() );
192
194
  }
193
195
 
194
196
  /**
@@ -273,11 +275,20 @@ export default class MarkerCollection {
273
275
  * means that marker is just added.
274
276
  * @param {module:engine/model/range~Range|null} newRange Marker range after update. When is not defined it
275
277
  * means that marker is just removed.
278
+ * @param {module:engine/model/markercollection~MarkerData} oldMarkerData Data of the marker before the change.
276
279
  */
277
280
  }
278
281
 
279
282
  mix( MarkerCollection, EmitterMixin );
280
283
 
284
+ /**
285
+ * @typedef {Object} module:engine/model/markercollection~MarkerData
286
+ *
287
+ * @property {module:engine/model/range~Range|null} range Marker range. `null` if the marker was removed.
288
+ * @property {Boolean} affectsData A property defining if the marker affects data.
289
+ * @property {Boolean} managedUsingOperations A property defining if the marker is managed using operations.
290
+ */
291
+
281
292
  /**
282
293
  * `Marker` is a continuous parts of model (like a range), is named and represent some kind of information about marked
283
294
  * part of model document. In contrary to {@link module:engine/model/node~Node nodes}, which are building blocks of
@@ -418,6 +429,19 @@ class Marker {
418
429
  return this._affectsData;
419
430
  }
420
431
 
432
+ /**
433
+ * Returns the marker data (properties defining the marker).
434
+ *
435
+ * @returns {module:engine/model/markercollection~MarkerData}
436
+ */
437
+ getData() {
438
+ return {
439
+ range: this.getRange(),
440
+ affectsData: this.affectsData,
441
+ managedUsingOperations: this.managedUsingOperations
442
+ };
443
+ }
444
+
421
445
  /**
422
446
  * Returns current marker start position.
423
447
  *