@ckeditor/ckeditor5-engine 36.0.0 → 37.0.0-alpha.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 (201) hide show
  1. package/README.md +1 -1
  2. package/package.json +24 -23
  3. package/src/controller/datacontroller.d.ts +331 -0
  4. package/src/controller/datacontroller.js +62 -109
  5. package/src/controller/editingcontroller.d.ts +98 -0
  6. package/src/controller/editingcontroller.js +22 -46
  7. package/src/conversion/conversion.d.ts +476 -0
  8. package/src/conversion/conversion.js +328 -347
  9. package/src/conversion/conversionhelpers.d.ts +26 -0
  10. package/src/conversion/conversionhelpers.js +1 -5
  11. package/src/conversion/downcastdispatcher.d.ts +547 -0
  12. package/src/conversion/downcastdispatcher.js +74 -152
  13. package/src/conversion/downcasthelpers.d.ts +1226 -0
  14. package/src/conversion/downcasthelpers.js +843 -762
  15. package/src/conversion/mapper.d.ts +499 -0
  16. package/src/conversion/mapper.js +84 -99
  17. package/src/conversion/modelconsumable.d.ts +201 -0
  18. package/src/conversion/modelconsumable.js +96 -99
  19. package/src/conversion/upcastdispatcher.d.ts +492 -0
  20. package/src/conversion/upcastdispatcher.js +73 -100
  21. package/src/conversion/upcasthelpers.d.ts +499 -0
  22. package/src/conversion/upcasthelpers.js +406 -373
  23. package/src/conversion/viewconsumable.d.ts +177 -0
  24. package/src/conversion/viewconsumable.js +157 -162
  25. package/src/dataprocessor/basichtmlwriter.d.ts +18 -0
  26. package/src/dataprocessor/basichtmlwriter.js +0 -9
  27. package/src/dataprocessor/dataprocessor.d.ts +61 -0
  28. package/src/dataprocessor/htmldataprocessor.d.ts +76 -0
  29. package/src/dataprocessor/htmldataprocessor.js +6 -28
  30. package/src/dataprocessor/htmlwriter.d.ts +16 -0
  31. package/src/dataprocessor/xmldataprocessor.d.ts +90 -0
  32. package/src/dataprocessor/xmldataprocessor.js +8 -40
  33. package/src/dev-utils/model.d.ts +124 -0
  34. package/src/dev-utils/model.js +41 -38
  35. package/src/dev-utils/operationreplayer.d.ts +51 -0
  36. package/src/dev-utils/operationreplayer.js +6 -14
  37. package/src/dev-utils/utils.d.ts +37 -0
  38. package/src/dev-utils/utils.js +5 -18
  39. package/src/dev-utils/view.d.ts +319 -0
  40. package/src/dev-utils/view.js +205 -226
  41. package/src/index.d.ts +105 -0
  42. package/src/index.js +1 -0
  43. package/src/model/batch.d.ts +106 -0
  44. package/src/model/differ.d.ts +329 -0
  45. package/src/model/document.d.ts +245 -0
  46. package/src/model/document.js +1 -1
  47. package/src/model/documentfragment.d.ts +196 -0
  48. package/src/model/documentfragment.js +2 -2
  49. package/src/model/documentselection.d.ts +420 -0
  50. package/src/model/element.d.ts +165 -0
  51. package/src/model/history.d.ts +114 -0
  52. package/src/model/item.d.ts +14 -0
  53. package/src/model/liveposition.d.ts +77 -0
  54. package/src/model/liverange.d.ts +102 -0
  55. package/src/model/markercollection.d.ts +335 -0
  56. package/src/model/model.d.ts +812 -0
  57. package/src/model/model.js +59 -30
  58. package/src/model/node.d.ts +256 -0
  59. package/src/model/nodelist.d.ts +91 -0
  60. package/src/model/operation/attributeoperation.d.ts +98 -0
  61. package/src/model/operation/detachoperation.d.ts +55 -0
  62. package/src/model/operation/insertoperation.d.ts +85 -0
  63. package/src/model/operation/markeroperation.d.ts +86 -0
  64. package/src/model/operation/mergeoperation.d.ts +95 -0
  65. package/src/model/operation/moveoperation.d.ts +91 -0
  66. package/src/model/operation/nooperation.d.ts +33 -0
  67. package/src/model/operation/operation.d.ts +89 -0
  68. package/src/model/operation/operationfactory.d.ts +18 -0
  69. package/src/model/operation/renameoperation.d.ts +78 -0
  70. package/src/model/operation/rootattributeoperation.d.ts +97 -0
  71. package/src/model/operation/rootattributeoperation.js +1 -1
  72. package/src/model/operation/splitoperation.d.ts +104 -0
  73. package/src/model/operation/transform.d.ts +100 -0
  74. package/src/model/operation/utils.d.ts +71 -0
  75. package/src/model/position.d.ts +539 -0
  76. package/src/model/position.js +1 -1
  77. package/src/model/range.d.ts +458 -0
  78. package/src/model/range.js +1 -1
  79. package/src/model/rootelement.d.ts +40 -0
  80. package/src/model/schema.d.ts +1176 -0
  81. package/src/model/schema.js +15 -15
  82. package/src/model/selection.d.ts +472 -0
  83. package/src/model/text.d.ts +66 -0
  84. package/src/model/text.js +0 -2
  85. package/src/model/textproxy.d.ts +144 -0
  86. package/src/model/treewalker.d.ts +186 -0
  87. package/src/model/treewalker.js +19 -10
  88. package/src/model/typecheckable.d.ts +255 -0
  89. package/src/model/utils/autoparagraphing.d.ts +37 -0
  90. package/src/model/utils/deletecontent.d.ts +58 -0
  91. package/src/model/utils/findoptimalinsertionrange.d.ts +32 -0
  92. package/src/model/utils/getselectedcontent.d.ts +30 -0
  93. package/src/model/utils/insertcontent.d.ts +46 -0
  94. package/src/model/utils/insertcontent.js +2 -12
  95. package/src/model/utils/insertobject.d.ts +44 -0
  96. package/src/model/utils/insertobject.js +3 -14
  97. package/src/model/utils/modifyselection.d.ts +48 -0
  98. package/src/model/utils/selection-post-fixer.d.ts +65 -0
  99. package/src/model/writer.d.ts +726 -0
  100. package/src/model/writer.js +6 -4
  101. package/src/view/attributeelement.d.ts +108 -0
  102. package/src/view/attributeelement.js +25 -69
  103. package/src/view/containerelement.d.ts +49 -0
  104. package/src/view/containerelement.js +10 -43
  105. package/src/view/datatransfer.d.ts +75 -0
  106. package/src/view/datatransfer.js +24 -27
  107. package/src/view/document.d.ts +184 -0
  108. package/src/view/document.js +15 -84
  109. package/src/view/documentfragment.d.ts +150 -0
  110. package/src/view/documentfragment.js +40 -81
  111. package/src/view/documentselection.d.ts +219 -0
  112. package/src/view/documentselection.js +75 -121
  113. package/src/view/domconverter.d.ts +620 -0
  114. package/src/view/domconverter.js +159 -276
  115. package/src/view/downcastwriter.d.ts +804 -0
  116. package/src/view/downcastwriter.js +336 -380
  117. package/src/view/editableelement.d.ts +52 -0
  118. package/src/view/editableelement.js +9 -49
  119. package/src/view/element.d.ts +466 -0
  120. package/src/view/element.js +150 -222
  121. package/src/view/elementdefinition.d.ts +87 -0
  122. package/src/view/emptyelement.d.ts +41 -0
  123. package/src/view/emptyelement.js +11 -44
  124. package/src/view/filler.d.ts +111 -0
  125. package/src/view/filler.js +24 -21
  126. package/src/view/item.d.ts +14 -0
  127. package/src/view/matcher.d.ts +486 -0
  128. package/src/view/matcher.js +247 -218
  129. package/src/view/node.d.ts +160 -0
  130. package/src/view/node.js +26 -100
  131. package/src/view/observer/arrowkeysobserver.d.ts +41 -0
  132. package/src/view/observer/arrowkeysobserver.js +0 -13
  133. package/src/view/observer/bubblingemittermixin.d.ts +166 -0
  134. package/src/view/observer/bubblingemittermixin.js +36 -25
  135. package/src/view/observer/bubblingeventinfo.d.ts +47 -0
  136. package/src/view/observer/bubblingeventinfo.js +3 -29
  137. package/src/view/observer/clickobserver.d.ts +43 -0
  138. package/src/view/observer/clickobserver.js +9 -19
  139. package/src/view/observer/compositionobserver.d.ts +82 -0
  140. package/src/view/observer/compositionobserver.js +13 -42
  141. package/src/view/observer/domeventdata.d.ts +50 -0
  142. package/src/view/observer/domeventdata.js +5 -30
  143. package/src/view/observer/domeventobserver.d.ts +69 -0
  144. package/src/view/observer/domeventobserver.js +19 -21
  145. package/src/view/observer/fakeselectionobserver.d.ts +46 -0
  146. package/src/view/observer/fakeselectionobserver.js +2 -15
  147. package/src/view/observer/focusobserver.d.ts +82 -0
  148. package/src/view/observer/focusobserver.js +14 -40
  149. package/src/view/observer/inputobserver.d.ts +86 -0
  150. package/src/view/observer/inputobserver.js +18 -64
  151. package/src/view/observer/keyobserver.d.ts +67 -0
  152. package/src/view/observer/keyobserver.js +8 -42
  153. package/src/view/observer/mouseobserver.d.ts +89 -0
  154. package/src/view/observer/mouseobserver.js +8 -28
  155. package/src/view/observer/mutationobserver.d.ts +82 -0
  156. package/src/view/observer/mutationobserver.js +7 -37
  157. package/src/view/observer/observer.d.ts +84 -0
  158. package/src/view/observer/observer.js +12 -25
  159. package/src/view/observer/selectionobserver.d.ts +143 -0
  160. package/src/view/observer/selectionobserver.js +9 -99
  161. package/src/view/observer/tabobserver.d.ts +42 -0
  162. package/src/view/observer/tabobserver.js +0 -14
  163. package/src/view/placeholder.d.ts +85 -0
  164. package/src/view/placeholder.js +26 -43
  165. package/src/view/position.d.ts +189 -0
  166. package/src/view/position.js +36 -83
  167. package/src/view/range.d.ts +279 -0
  168. package/src/view/range.js +79 -122
  169. package/src/view/rawelement.d.ts +73 -0
  170. package/src/view/rawelement.js +34 -48
  171. package/src/view/renderer.d.ts +265 -0
  172. package/src/view/renderer.js +105 -193
  173. package/src/view/rooteditableelement.d.ts +41 -0
  174. package/src/view/rooteditableelement.js +12 -40
  175. package/src/view/selection.d.ts +375 -0
  176. package/src/view/selection.js +79 -153
  177. package/src/view/styles/background.d.ts +33 -0
  178. package/src/view/styles/background.js +14 -12
  179. package/src/view/styles/border.d.ts +43 -0
  180. package/src/view/styles/border.js +58 -48
  181. package/src/view/styles/margin.d.ts +29 -0
  182. package/src/view/styles/margin.js +13 -11
  183. package/src/view/styles/padding.d.ts +29 -0
  184. package/src/view/styles/padding.js +13 -11
  185. package/src/view/styles/utils.d.ts +93 -0
  186. package/src/view/styles/utils.js +22 -48
  187. package/src/view/stylesmap.d.ts +675 -0
  188. package/src/view/stylesmap.js +249 -244
  189. package/src/view/text.d.ts +74 -0
  190. package/src/view/text.js +16 -46
  191. package/src/view/textproxy.d.ts +97 -0
  192. package/src/view/textproxy.js +10 -59
  193. package/src/view/treewalker.d.ts +195 -0
  194. package/src/view/treewalker.js +43 -106
  195. package/src/view/typecheckable.d.ts +401 -0
  196. package/src/view/uielement.d.ts +96 -0
  197. package/src/view/uielement.js +28 -62
  198. package/src/view/upcastwriter.d.ts +328 -0
  199. package/src/view/upcastwriter.js +124 -134
  200. package/src/view/view.d.ts +327 -0
  201. package/src/view/view.js +79 -150
@@ -29,7 +29,6 @@ import { CKEditorError, EmitterMixin } from '@ckeditor/ckeditor5-utils';
29
29
  * and {@link module:engine/conversion/mapper~Mapper#toModelPosition toModelPosition} methods. `Mapper` adds its own default callbacks
30
30
  * with `'lowest'` priority. To override default `Mapper` mapping, add custom callback with higher priority and
31
31
  * stop the event.
32
- * @mixes module:utils/emittermixin~EmitterMixin
33
32
  */
34
33
  export default class Mapper extends EmitterMixin() {
35
34
  /**
@@ -39,24 +38,15 @@ export default class Mapper extends EmitterMixin() {
39
38
  super();
40
39
  /**
41
40
  * Model element to view element mapping.
42
- *
43
- * @private
44
- * @member {WeakMap}
45
41
  */
46
42
  this._modelToViewMapping = new WeakMap();
47
43
  /**
48
44
  * View element to model element mapping.
49
- *
50
- * @private
51
- * @member {WeakMap}
52
45
  */
53
46
  this._viewToModelMapping = new WeakMap();
54
47
  /**
55
48
  * A map containing callbacks between view element names and functions evaluating length of view elements
56
49
  * in model.
57
- *
58
- * @private
59
- * @member {Map}
60
50
  */
61
51
  this._viewToModelLengthCallbacks = new Map();
62
52
  /**
@@ -64,33 +54,21 @@ export default class Mapper extends EmitterMixin() {
64
54
  *
65
55
  * Keys are `String`s while values are `Set`s with {@link module:engine/view/element~Element view elements}.
66
56
  * One marker (name) can be mapped to multiple elements.
67
- *
68
- * @private
69
- * @member {Map}
70
57
  */
71
58
  this._markerNameToElements = new Map();
72
59
  /**
73
60
  * View element to model marker names mapping.
74
61
  *
75
62
  * This is reverse to {@link ~Mapper#_markerNameToElements} map.
76
- *
77
- * @private
78
- * @member {Map}
79
63
  */
80
64
  this._elementToMarkerNames = new Map();
81
65
  /**
82
66
  * The map of removed view elements with their current root (used for deferred unbinding).
83
- *
84
- * @private
85
- * @member {Map.<module:engine/view/element~Element,module:engine/view/documentfragment~DocumentFragment>}
86
67
  */
87
68
  this._deferredBindingRemovals = new Map();
88
69
  /**
89
70
  * Stores marker names of markers which have changed due to unbinding a view element (so it is assumed that the view element
90
71
  * has been removed, moved or renamed).
91
- *
92
- * @private
93
- * @member {Set.<module:engine/model/markercollection~Marker>}
94
72
  */
95
73
  this._unboundMarkerNames = new Set();
96
74
  // Default mapper algorithm for mapping model position to view position.
@@ -129,8 +107,8 @@ export default class Mapper extends EmitterMixin() {
129
107
  * {@link module:engine/conversion/mapper~Mapper#toViewElement toViewElement} methods.
130
108
  * The information that elements are bound is also used to translate positions.
131
109
  *
132
- * @param {module:engine/model/element~Element} modelElement Model element.
133
- * @param {module:engine/view/element~Element} viewElement View element.
110
+ * @param modelElement Model element.
111
+ * @param viewElement View element.
134
112
  */
135
113
  bindElements(modelElement, viewElement) {
136
114
  this._modelToViewMapping.set(modelElement, viewElement);
@@ -145,9 +123,9 @@ export default class Mapper extends EmitterMixin() {
145
123
  * This behavior allows for re-binding model element to another view element without fear of losing the new binding
146
124
  * when the previously bound view element is unbound.
147
125
  *
148
- * @param {module:engine/view/element~Element} viewElement View element to unbind.
149
- * @param {Object} [options={}] The options object.
150
- * @param {Boolean} [options.defer=false] Controls whether the binding should be removed immediately or deferred until a
126
+ * @param viewElement View element to unbind.
127
+ * @param options The options object.
128
+ * @param options.defer Controls whether the binding should be removed immediately or deferred until a
151
129
  * {@link #flushDeferredBindings `flushDeferredBindings()`} call.
152
130
  */
153
131
  unbindViewElement(viewElement, options = {}) {
@@ -176,7 +154,7 @@ export default class Mapper extends EmitterMixin() {
176
154
  * This behavior lets for re-binding view element to another model element without fear of losing the new binding
177
155
  * when the previously bound model element is unbound.
178
156
  *
179
- * @param {module:engine/model/element~Element} modelElement Model element to unbind.
157
+ * @param modelElement Model element to unbind.
180
158
  */
181
159
  unbindModelElement(modelElement) {
182
160
  const viewElement = this.toViewElement(modelElement);
@@ -189,8 +167,8 @@ export default class Mapper extends EmitterMixin() {
189
167
  * Binds the given marker name with the given {@link module:engine/view/element~Element view element}. The element
190
168
  * will be added to the current set of elements bound with the given marker name.
191
169
  *
192
- * @param {module:engine/view/element~Element} element Element to bind.
193
- * @param {String} name Marker name.
170
+ * @param element Element to bind.
171
+ * @param name Marker name.
194
172
  */
195
173
  bindElementToMarker(element, name) {
196
174
  const elements = this._markerNameToElements.get(name) || new Set();
@@ -203,8 +181,8 @@ export default class Mapper extends EmitterMixin() {
203
181
  /**
204
182
  * Unbinds an element from given marker name.
205
183
  *
206
- * @param {module:engine/view/element~Element} element Element to unbind.
207
- * @param {String} name Marker name.
184
+ * @param element Element to unbind.
185
+ * @param name Marker name.
208
186
  */
209
187
  unbindElementFromMarkerName(element, name) {
210
188
  const nameToElements = this._markerNameToElements.get(name);
@@ -225,8 +203,6 @@ export default class Mapper extends EmitterMixin() {
225
203
  /**
226
204
  * Returns all marker names of markers which have changed due to unbinding a view element (so it is assumed that the view element
227
205
  * has been removed, moved or renamed) since the last flush. After returning, the marker names list is cleared.
228
- *
229
- * @returns {Array.<String>}
230
206
  */
231
207
  flushUnboundMarkerNames() {
232
208
  const markerNames = Array.from(this._unboundMarkerNames);
@@ -267,8 +243,8 @@ export default class Mapper extends EmitterMixin() {
267
243
  /**
268
244
  * Gets the corresponding model range.
269
245
  *
270
- * @param {module:engine/view/range~Range} viewRange View range.
271
- * @returns {module:engine/model/range~Range} Corresponding model range.
246
+ * @param viewRange View range.
247
+ * @returns Corresponding model range.
272
248
  */
273
249
  toModelRange(viewRange) {
274
250
  return new ModelRange(this.toModelPosition(viewRange.start), this.toModelPosition(viewRange.end));
@@ -276,8 +252,8 @@ export default class Mapper extends EmitterMixin() {
276
252
  /**
277
253
  * Gets the corresponding view range.
278
254
  *
279
- * @param {module:engine/model/range~Range} modelRange Model range.
280
- * @returns {module:engine/view/range~Range} Corresponding view range.
255
+ * @param modelRange Model range.
256
+ * @returns Corresponding view range.
281
257
  */
282
258
  toViewRange(modelRange) {
283
259
  return new ViewRange(this.toViewPosition(modelRange.start), this.toViewPosition(modelRange.end));
@@ -286,8 +262,8 @@ export default class Mapper extends EmitterMixin() {
286
262
  * Gets the corresponding model position.
287
263
  *
288
264
  * @fires viewToModelPosition
289
- * @param {module:engine/view/position~Position} viewPosition View position.
290
- * @returns {module:engine/model/position~Position} Corresponding model position.
265
+ * @param viewPosition View position.
266
+ * @returns Corresponding model position.
291
267
  */
292
268
  toModelPosition(viewPosition) {
293
269
  const data = {
@@ -301,11 +277,11 @@ export default class Mapper extends EmitterMixin() {
301
277
  * Gets the corresponding view position.
302
278
  *
303
279
  * @fires modelToViewPosition
304
- * @param {module:engine/model/position~Position} modelPosition Model position.
305
- * @param {Object} [options] Additional options for position mapping process.
306
- * @param {Boolean} [options.isPhantom=false] Should be set to `true` if the model position to map is pointing to a place
280
+ * @param modelPosition Model position.
281
+ * @param options Additional options for position mapping process.
282
+ * @param options.isPhantom Should be set to `true` if the model position to map is pointing to a place
307
283
  * in model tree which no longer exists. For example, it could be an end of a removed model range.
308
- * @returns {module:engine/view/position~Position} Corresponding view position.
284
+ * @returns Corresponding view position.
309
285
  */
310
286
  toViewPosition(modelPosition, options = {}) {
311
287
  const data = {
@@ -319,8 +295,8 @@ export default class Mapper extends EmitterMixin() {
319
295
  /**
320
296
  * Gets all view elements bound to the given marker name.
321
297
  *
322
- * @param {String} name Marker name.
323
- * @returns {Set.<module:engine/view/element~Element>|null} View elements bound with the given marker name or `null`
298
+ * @param name Marker name.
299
+ * @returns View elements bound with the given marker name or `null`
324
300
  * if no elements are bound to the given marker name.
325
301
  */
326
302
  markerNameToElements(name) {
@@ -347,28 +323,30 @@ export default class Mapper extends EmitterMixin() {
347
323
  * The callback is fired with one argument, which is a view element instance. The callback is expected to return
348
324
  * a number representing the length of the view element in the model.
349
325
  *
350
- * // List item in view may contain nested list, which have other list items. In model though,
351
- * // the lists are represented by flat structure. Because of those differences, length of list view element
352
- * // may be greater than one. In the callback it's checked how many nested list items are in evaluated list item.
326
+ * ```ts
327
+ * // List item in view may contain nested list, which have other list items. In model though,
328
+ * // the lists are represented by flat structure. Because of those differences, length of list view element
329
+ * // may be greater than one. In the callback it's checked how many nested list items are in evaluated list item.
353
330
  *
354
- * function getViewListItemLength( element ) {
355
- * let length = 1;
331
+ * function getViewListItemLength( element ) {
332
+ * let length = 1;
356
333
  *
357
- * for ( let child of element.getChildren() ) {
358
- * if ( child.name == 'ul' || child.name == 'ol' ) {
359
- * for ( let item of child.getChildren() ) {
360
- * length += getViewListItemLength( item );
361
- * }
362
- * }
363
- * }
334
+ * for ( let child of element.getChildren() ) {
335
+ * if ( child.name == 'ul' || child.name == 'ol' ) {
336
+ * for ( let item of child.getChildren() ) {
337
+ * length += getViewListItemLength( item );
338
+ * }
339
+ * }
340
+ * }
364
341
  *
365
- * return length;
366
- * }
342
+ * return length;
343
+ * }
367
344
  *
368
- * mapper.registerViewToModelLength( 'li', getViewListItemLength );
345
+ * mapper.registerViewToModelLength( 'li', getViewListItemLength );
346
+ * ```
369
347
  *
370
- * @param {String} viewElementName Name of view element for which callback is registered.
371
- * @param {Function} lengthCallback Function return a length of view element instance in model.
348
+ * @param viewElementName Name of view element for which callback is registered.
349
+ * @param lengthCallback Function return a length of view element instance in model.
372
350
  */
373
351
  registerViewToModelLength(viewElementName, lengthCallback) {
374
352
  this._viewToModelLengthCallbacks.set(viewElementName, lengthCallback);
@@ -377,8 +355,7 @@ export default class Mapper extends EmitterMixin() {
377
355
  * For the given `viewPosition`, finds and returns the closest ancestor of this position that has a mapping to
378
356
  * the model.
379
357
  *
380
- * @param {module:engine/view/position~Position} viewPosition Position for which a mapped ancestor should be found.
381
- * @returns {module:engine/view/element~Element}
358
+ * @param viewPosition Position for which a mapped ancestor should be found.
382
359
  */
383
360
  findMappedViewAncestor(viewPosition) {
384
361
  let parent = viewPosition.parent;
@@ -392,18 +369,21 @@ export default class Mapper extends EmitterMixin() {
392
369
  *
393
370
  * Example:
394
371
  *
395
- * <p>foo<b>ba|r</b></p> // _toModelOffset( b, 2, p ) -> 5
372
+ * ```html
373
+ * <p>foo<b>ba|r</b></p> // _toModelOffset( b, 2, p ) -> 5
374
+ * ```
396
375
  *
397
376
  * Is a sum of:
398
377
  *
399
- * <p>foo|<b>bar</b></p> // _toModelOffset( p, 3, p ) -> 3
400
- * <p>foo<b>ba|r</b></p> // _toModelOffset( b, 2, b ) -> 2
378
+ * ```html
379
+ * <p>foo|<b>bar</b></p> // _toModelOffset( p, 3, p ) -> 3
380
+ * <p>foo<b>ba|r</b></p> // _toModelOffset( b, 2, b ) -> 2
381
+ * ```
401
382
  *
402
- * @private
403
- * @param {module:engine/view/element~Element} viewParent Position parent.
404
- * @param {Number} viewOffset Position offset.
405
- * @param {module:engine/view/element~Element} viewBlock Block used as a base to calculate offset.
406
- * @returns {Number} Offset in the model.
383
+ * @param viewParent Position parent.
384
+ * @param viewOffset Position offset.
385
+ * @param viewBlock Block used as a base to calculate offset.
386
+ * @returns Offset in the model.
407
387
  */
408
388
  _toModelOffset(viewParent, viewOffset, viewBlock) {
409
389
  if (viewBlock != viewParent) {
@@ -438,13 +418,15 @@ export default class Mapper extends EmitterMixin() {
438
418
  *
439
419
  * Examples:
440
420
  *
441
- * foo -> 3 // Text length is equal to its data length.
442
- * <p>foo</p> -> 1 // Length of an element which is mapped is by default equal to 1.
443
- * <b>foo</b> -> 3 // Length of an element which is not mapped is a length of its children.
444
- * <div><p>x</p><p>y</p></div> -> 2 // Assuming that <div> is not mapped and <p> are mapped.
421
+ * ```
422
+ * foo -> 3 // Text length is equal to its data length.
423
+ * <p>foo</p> -> 1 // Length of an element which is mapped is by default equal to 1.
424
+ * <b>foo</b> -> 3 // Length of an element which is not mapped is a length of its children.
425
+ * <div><p>x</p><p>y</p></div> -> 2 // Assuming that <div> is not mapped and <p> are mapped.
426
+ * ```
445
427
  *
446
- * @param {module:engine/view/element~Element} viewNode View node.
447
- * @returns {Number} Length of the node in the tree model.
428
+ * @param viewNode View node.
429
+ * @returns Length of the node in the tree model.
448
430
  */
449
431
  getModelLength(viewNode) {
450
432
  if (this._viewToModelLengthCallbacks.get(viewNode.name)) {
@@ -473,24 +455,26 @@ export default class Mapper extends EmitterMixin() {
473
455
  *
474
456
  * Example:
475
457
  *
476
- * <p>fo<b>bar</b>bom</p> -> expected offset: 4
458
+ * ```
459
+ * <p>fo<b>bar</b>bom</p> -> expected offset: 4
477
460
  *
478
- * findPositionIn( p, 4 ):
479
- * <p>|fo<b>bar</b>bom</p> -> expected offset: 4, actual offset: 0
480
- * <p>fo|<b>bar</b>bom</p> -> expected offset: 4, actual offset: 2
481
- * <p>fo<b>bar</b>|bom</p> -> expected offset: 4, actual offset: 5 -> we are too far
461
+ * findPositionIn( p, 4 ):
462
+ * <p>|fo<b>bar</b>bom</p> -> expected offset: 4, actual offset: 0
463
+ * <p>fo|<b>bar</b>bom</p> -> expected offset: 4, actual offset: 2
464
+ * <p>fo<b>bar</b>|bom</p> -> expected offset: 4, actual offset: 5 -> we are too far
482
465
  *
483
- * findPositionIn( b, 4 - ( 5 - 3 ) ):
484
- * <p>fo<b>|bar</b>bom</p> -> expected offset: 2, actual offset: 0
485
- * <p>fo<b>bar|</b>bom</p> -> expected offset: 2, actual offset: 3 -> we are too far
466
+ * findPositionIn( b, 4 - ( 5 - 3 ) ):
467
+ * <p>fo<b>|bar</b>bom</p> -> expected offset: 2, actual offset: 0
468
+ * <p>fo<b>bar|</b>bom</p> -> expected offset: 2, actual offset: 3 -> we are too far
486
469
  *
487
- * findPositionIn( bar, 2 - ( 3 - 3 ) ):
488
- * We are in the text node so we can simple find the offset.
489
- * <p>fo<b>ba|r</b>bom</p> -> expected offset: 2, actual offset: 2 -> position found
470
+ * findPositionIn( bar, 2 - ( 3 - 3 ) ):
471
+ * We are in the text node so we can simple find the offset.
472
+ * <p>fo<b>ba|r</b>bom</p> -> expected offset: 2, actual offset: 2 -> position found
473
+ * ```
490
474
  *
491
- * @param {module:engine/view/element~Element} viewParent Tree view element in which we are looking for the position.
492
- * @param {Number} expectedOffset Expected offset.
493
- * @returns {module:engine/view/position~Position} Found position.
475
+ * @param viewParent Tree view element in which we are looking for the position.
476
+ * @param expectedOffset Expected offset.
477
+ * @returns Found position.
494
478
  */
495
479
  findPositionIn(viewParent, expectedOffset) {
496
480
  // Last scanned view node.
@@ -526,13 +510,14 @@ export default class Mapper extends EmitterMixin() {
526
510
  * Because we prefer positions in the text nodes over positions next to text nodes, if the view position was next to a text node,
527
511
  * it moves it into the text node instead.
528
512
  *
529
- * <p>[]<b>foo</b></p> -> <p>[]<b>foo</b></p> // do not touch if position is not directly next to text
530
- * <p>foo[]<b>foo</b></p> -> <p>foo{}<b>foo</b></p> // move to text node
531
- * <p><b>[]foo</b></p> -> <p><b>{}foo</b></p> // move to text node
513
+ * ```
514
+ * <p>[]<b>foo</b></p> -> <p>[]<b>foo</b></p> // do not touch if position is not directly next to text
515
+ * <p>foo[]<b>foo</b></p> -> <p>foo{}<b>foo</b></p> // move to text node
516
+ * <p><b>[]foo</b></p> -> <p><b>{}foo</b></p> // move to text node
517
+ * ```
532
518
  *
533
- * @private
534
- * @param {module:engine/view/position~Position} viewPosition Position potentially next to the text node.
535
- * @returns {module:engine/view/position~Position} Position in the text node if possible.
519
+ * @param viewPosition Position potentially next to the text node.
520
+ * @returns Position in the text node if possible.
536
521
  */
537
522
  _moveViewPositionToTextNode(viewPosition) {
538
523
  // If the position is just after a text node, put it at the end of that text node.
@@ -0,0 +1,201 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module engine/conversion/modelconsumable
7
+ */
8
+ import TextProxy from '../model/textproxy';
9
+ import type Item from '../model/item';
10
+ import type Selection from '../model/selection';
11
+ import type DocumentSelection from '../model/documentselection';
12
+ import type Range from '../model/range';
13
+ /**
14
+ * Manages a list of consumable values for the {@link module:engine/model/item~Item model items}.
15
+ *
16
+ * Consumables are various aspects of the model. A model item can be broken down into separate, single properties that might be
17
+ * taken into consideration when converting that item.
18
+ *
19
+ * `ModelConsumable` is used by {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher} while analyzing the changed
20
+ * parts of {@link module:engine/model/document~Document the document}. The added / changed / removed model items are broken down
21
+ * into singular properties (the item itself and its attributes). All those parts are saved in `ModelConsumable`. Then,
22
+ * during conversion, when the given part of a model item is converted (i.e. the view element has been inserted into the view,
23
+ * but without attributes), the consumable value is removed from `ModelConsumable`.
24
+ *
25
+ * For model items, `ModelConsumable` stores consumable values of one of following types: `insert`, `addattribute:<attributeKey>`,
26
+ * `changeattributes:<attributeKey>`, `removeattributes:<attributeKey>`.
27
+ *
28
+ * In most cases, it is enough to let th {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}
29
+ * gather consumable values, so there is no need to use
30
+ * the {@link module:engine/conversion/modelconsumable~ModelConsumable#add add method} directly.
31
+ * However, it is important to understand how consumable values can be
32
+ * {@link module:engine/conversion/modelconsumable~ModelConsumable#consume consumed}.
33
+ * See {@link module:engine/conversion/downcasthelpers default downcast converters} for more information.
34
+ *
35
+ * Keep in mind that one conversion event may have multiple callbacks (converters) attached to it. Each of those is
36
+ * able to convert one or more parts of the model. However, when one of those callbacks actually converts
37
+ * something, the others should not, because they would duplicate the results. Using `ModelConsumable` helps to avoid
38
+ * this situation, because callbacks should only convert these values that were not yet consumed from `ModelConsumable`.
39
+ *
40
+ * Consuming multiple values in a single callback:
41
+ *
42
+ * ```ts
43
+ * // Converter for custom `imageBlock` element that might have a `caption` element inside which changes
44
+ * // how the image is displayed in the view:
45
+ * //
46
+ * // Model:
47
+ * //
48
+ * // [imageBlock]
49
+ * // └─ [caption]
50
+ * // └─ foo
51
+ * //
52
+ * // View:
53
+ * //
54
+ * // <figure>
55
+ * // ├─ <img />
56
+ * // └─ <caption>
57
+ * // └─ foo
58
+ * modelConversionDispatcher.on( 'insert:imageBlock', ( evt, data, conversionApi ) => {
59
+ * // First, consume the `imageBlock` element.
60
+ * conversionApi.consumable.consume( data.item, 'insert' );
61
+ *
62
+ * // Just create normal image element for the view.
63
+ * // Maybe it will be "decorated" later.
64
+ * const viewImage = new ViewElement( 'img' );
65
+ * const insertPosition = conversionApi.mapper.toViewPosition( data.range.start );
66
+ * const viewWriter = conversionApi.writer;
67
+ *
68
+ * // Check if the `imageBlock` element has children.
69
+ * if ( data.item.childCount > 0 ) {
70
+ * const modelCaption = data.item.getChild( 0 );
71
+ *
72
+ * // `modelCaption` insertion change is consumed from consumable values.
73
+ * // It will not be converted by other converters, but it's children (probably some text) will be.
74
+ * // Through mapping, converters for text will know where to insert contents of `modelCaption`.
75
+ * if ( conversionApi.consumable.consume( modelCaption, 'insert' ) ) {
76
+ * const viewCaption = new ViewElement( 'figcaption' );
77
+ *
78
+ * const viewImageHolder = new ViewElement( 'figure', null, [ viewImage, viewCaption ] );
79
+ *
80
+ * conversionApi.mapper.bindElements( modelCaption, viewCaption );
81
+ * conversionApi.mapper.bindElements( data.item, viewImageHolder );
82
+ * viewWriter.insert( insertPosition, viewImageHolder );
83
+ * }
84
+ * } else {
85
+ * conversionApi.mapper.bindElements( data.item, viewImage );
86
+ * viewWriter.insert( insertPosition, viewImage );
87
+ * }
88
+ *
89
+ * evt.stop();
90
+ * } );
91
+ * ```
92
+ */
93
+ export default class ModelConsumable {
94
+ /**
95
+ * Contains list of consumable values.
96
+ */
97
+ private _consumable;
98
+ /**
99
+ * For each {@link module:engine/model/textproxy~TextProxy} added to `ModelConsumable`, this registry holds a parent
100
+ * of that `TextProxy` and the start and end indices of that `TextProxy`. This allows identification of the `TextProxy`
101
+ * instances that point to the same part of the model but are different instances. Each distinct `TextProxy`
102
+ * is given a unique `Symbol` which is then registered as consumable. This process is transparent for the `ModelConsumable`
103
+ * API user because whenever `TextProxy` is added, tested, consumed or reverted, the internal mechanisms of
104
+ * `ModelConsumable` translate `TextProxy` to that unique `Symbol`.
105
+ */
106
+ private _textProxyRegistry;
107
+ /**
108
+ * Adds a consumable value to the consumables list and links it with a given model item.
109
+ *
110
+ * ```ts
111
+ * modelConsumable.add( modelElement, 'insert' ); // Add `modelElement` insertion change to consumable values.
112
+ * modelConsumable.add( modelElement, 'addAttribute:bold' ); // Add `bold` attribute insertion on `modelElement` change.
113
+ * modelConsumable.add( modelElement, 'removeAttribute:bold' ); // Add `bold` attribute removal on `modelElement` change.
114
+ * modelConsumable.add( modelSelection, 'selection' ); // Add `modelSelection` to consumable values.
115
+ * modelConsumable.add( modelRange, 'range' ); // Add `modelRange` to consumable values.
116
+ * ```
117
+ *
118
+ * @param item Model item, range or selection that has the consumable.
119
+ * @param type Consumable type. Will be normalized to a proper form, that is either `<word>` or `<part>:<part>`.
120
+ * Second colon and everything after will be cut. Passing event name is a safe and good practice.
121
+ */
122
+ add(item: Item | Selection | DocumentSelection | Range, type: string): void;
123
+ /**
124
+ * Removes a given consumable value from a given model item.
125
+ *
126
+ * ```ts
127
+ * modelConsumable.consume( modelElement, 'insert' ); // Remove `modelElement` insertion change from consumable values.
128
+ * modelConsumable.consume( modelElement, 'addAttribute:bold' ); // Remove `bold` attribute insertion on `modelElement` change.
129
+ * modelConsumable.consume( modelElement, 'removeAttribute:bold' ); // Remove `bold` attribute removal on `modelElement` change.
130
+ * modelConsumable.consume( modelSelection, 'selection' ); // Remove `modelSelection` from consumable values.
131
+ * modelConsumable.consume( modelRange, 'range' ); // Remove 'modelRange' from consumable values.
132
+ * ```
133
+ *
134
+ * @param item Model item, range or selection from which consumable will be consumed.
135
+ * @param type Consumable type. Will be normalized to a proper form, that is either `<word>` or `<part>:<part>`.
136
+ * Second colon and everything after will be cut. Passing event name is a safe and good practice.
137
+ * @returns `true` if consumable value was available and was consumed, `false` otherwise.
138
+ */
139
+ consume(item: Item | Selection | DocumentSelection | Range, type: string): boolean;
140
+ /**
141
+ * Tests whether there is a consumable value of a given type connected with a given model item.
142
+ *
143
+ * ```ts
144
+ * modelConsumable.test( modelElement, 'insert' ); // Check for `modelElement` insertion change.
145
+ * modelConsumable.test( modelElement, 'addAttribute:bold' ); // Check for `bold` attribute insertion on `modelElement` change.
146
+ * modelConsumable.test( modelElement, 'removeAttribute:bold' ); // Check for `bold` attribute removal on `modelElement` change.
147
+ * modelConsumable.test( modelSelection, 'selection' ); // Check if `modelSelection` is consumable.
148
+ * modelConsumable.test( modelRange, 'range' ); // Check if `modelRange` is consumable.
149
+ * ```
150
+ *
151
+ * @param item Model item, range or selection to be tested.
152
+ * @param type Consumable type. Will be normalized to a proper form, that is either `<word>` or `<part>:<part>`.
153
+ * Second colon and everything after will be cut. Passing event name is a safe and good practice.
154
+ * @returns `null` if such consumable was never added, `false` if the consumable values was
155
+ * already consumed or `true` if it was added and not consumed yet.
156
+ */
157
+ test(item: Item | Selection | DocumentSelection | Range, type: string): boolean | null;
158
+ /**
159
+ * Reverts consuming of a consumable value.
160
+ *
161
+ * ```ts
162
+ * modelConsumable.revert( modelElement, 'insert' ); // Revert consuming `modelElement` insertion change.
163
+ * modelConsumable.revert( modelElement, 'addAttribute:bold' ); // Revert consuming `bold` attribute insert from `modelElement`.
164
+ * modelConsumable.revert( modelElement, 'removeAttribute:bold' ); // Revert consuming `bold` attribute remove from `modelElement`.
165
+ * modelConsumable.revert( modelSelection, 'selection' ); // Revert consuming `modelSelection`.
166
+ * modelConsumable.revert( modelRange, 'range' ); // Revert consuming `modelRange`.
167
+ * ```
168
+ *
169
+ * @param item Model item, range or selection to be reverted.
170
+ * @param type Consumable type.
171
+ * @returns `true` if consumable has been reversed, `false` otherwise. `null` if the consumable has
172
+ * never been added.
173
+ */
174
+ revert(item: Item | Selection | DocumentSelection | Range, type: string): boolean | null;
175
+ /**
176
+ * Verifies if all events from the specified group were consumed.
177
+ *
178
+ * @param eventGroup The events group to verify.
179
+ */
180
+ verifyAllConsumed(eventGroup: string): void;
181
+ /**
182
+ * Gets a unique symbol for the passed {@link module:engine/model/textproxy~TextProxy} instance. All `TextProxy` instances that
183
+ * have same parent, same start index and same end index will get the same symbol.
184
+ *
185
+ * Used internally to correctly consume `TextProxy` instances.
186
+ *
187
+ * @internal
188
+ * @param textProxy `TextProxy` instance to get a symbol for.
189
+ * @returns Symbol representing all equal instances of `TextProxy`.
190
+ */
191
+ _getSymbolForTextProxy(textProxy: TextProxy): symbol;
192
+ /**
193
+ * Adds a symbol for the given {@link module:engine/model/textproxy~TextProxy} instance.
194
+ *
195
+ * Used internally to correctly consume `TextProxy` instances.
196
+ *
197
+ * @param textProxy Text proxy instance.
198
+ * @returns Symbol generated for given `TextProxy`.
199
+ */
200
+ private _addSymbolForTextProxy;
201
+ }