@ckeditor/ckeditor5-engine 35.0.1 → 35.1.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.
- package/CHANGELOG.md +4 -4
- package/package.json +30 -24
- package/src/controller/datacontroller.js +467 -561
- package/src/controller/editingcontroller.js +168 -204
- package/src/conversion/conversion.js +541 -565
- package/src/conversion/conversionhelpers.js +24 -28
- package/src/conversion/downcastdispatcher.js +457 -686
- package/src/conversion/downcasthelpers.js +1583 -1965
- package/src/conversion/mapper.js +518 -707
- package/src/conversion/modelconsumable.js +240 -283
- package/src/conversion/upcastdispatcher.js +372 -718
- package/src/conversion/upcasthelpers.js +707 -818
- package/src/conversion/viewconsumable.js +524 -581
- package/src/dataprocessor/basichtmlwriter.js +12 -16
- package/src/dataprocessor/dataprocessor.js +5 -0
- package/src/dataprocessor/htmldataprocessor.js +100 -116
- package/src/dataprocessor/htmlwriter.js +1 -18
- package/src/dataprocessor/xmldataprocessor.js +116 -137
- package/src/dev-utils/model.js +260 -352
- package/src/dev-utils/operationreplayer.js +106 -126
- package/src/dev-utils/utils.js +34 -51
- package/src/dev-utils/view.js +632 -753
- package/src/index.js +0 -11
- package/src/model/batch.js +111 -127
- package/src/model/differ.js +988 -1233
- package/src/model/document.js +340 -449
- package/src/model/documentfragment.js +327 -364
- package/src/model/documentselection.js +996 -1189
- package/src/model/element.js +306 -410
- package/src/model/history.js +224 -262
- package/src/model/item.js +5 -0
- package/src/model/liveposition.js +84 -145
- package/src/model/liverange.js +108 -185
- package/src/model/markercollection.js +379 -480
- package/src/model/model.js +883 -1034
- package/src/model/node.js +419 -463
- package/src/model/nodelist.js +175 -201
- package/src/model/operation/attributeoperation.js +153 -182
- package/src/model/operation/detachoperation.js +64 -83
- package/src/model/operation/insertoperation.js +135 -166
- package/src/model/operation/markeroperation.js +114 -140
- package/src/model/operation/mergeoperation.js +163 -191
- package/src/model/operation/moveoperation.js +157 -187
- package/src/model/operation/nooperation.js +28 -38
- package/src/model/operation/operation.js +106 -125
- package/src/model/operation/operationfactory.js +30 -34
- package/src/model/operation/renameoperation.js +109 -135
- package/src/model/operation/rootattributeoperation.js +155 -188
- package/src/model/operation/splitoperation.js +196 -232
- package/src/model/operation/transform.js +1833 -2204
- package/src/model/operation/utils.js +140 -204
- package/src/model/position.js +899 -1053
- package/src/model/range.js +910 -1028
- package/src/model/rootelement.js +77 -97
- package/src/model/schema.js +1189 -1835
- package/src/model/selection.js +745 -862
- package/src/model/text.js +90 -114
- package/src/model/textproxy.js +204 -240
- package/src/model/treewalker.js +316 -397
- package/src/model/typecheckable.js +16 -0
- package/src/model/utils/autoparagraphing.js +32 -44
- package/src/model/utils/deletecontent.js +334 -418
- package/src/model/utils/findoptimalinsertionrange.js +25 -36
- package/src/model/utils/getselectedcontent.js +96 -118
- package/src/model/utils/insertcontent.js +654 -773
- package/src/model/utils/insertobject.js +96 -119
- package/src/model/utils/modifyselection.js +120 -158
- package/src/model/utils/selection-post-fixer.js +153 -201
- package/src/model/writer.js +1305 -1474
- package/src/view/attributeelement.js +189 -225
- package/src/view/containerelement.js +75 -85
- package/src/view/document.js +172 -215
- package/src/view/documentfragment.js +200 -249
- package/src/view/documentselection.js +338 -367
- package/src/view/domconverter.js +1370 -1617
- package/src/view/downcastwriter.js +1747 -2076
- package/src/view/editableelement.js +81 -97
- package/src/view/element.js +739 -890
- package/src/view/elementdefinition.js +5 -0
- package/src/view/emptyelement.js +82 -92
- package/src/view/filler.js +35 -50
- package/src/view/item.js +5 -0
- package/src/view/matcher.js +260 -559
- package/src/view/node.js +274 -360
- package/src/view/observer/arrowkeysobserver.js +19 -28
- package/src/view/observer/bubblingemittermixin.js +120 -263
- package/src/view/observer/bubblingeventinfo.js +47 -55
- package/src/view/observer/clickobserver.js +7 -13
- package/src/view/observer/compositionobserver.js +14 -24
- package/src/view/observer/domeventdata.js +57 -67
- package/src/view/observer/domeventobserver.js +40 -64
- package/src/view/observer/fakeselectionobserver.js +81 -96
- package/src/view/observer/focusobserver.js +45 -61
- package/src/view/observer/inputobserver.js +7 -13
- package/src/view/observer/keyobserver.js +17 -27
- package/src/view/observer/mouseobserver.js +7 -14
- package/src/view/observer/mutationobserver.js +220 -315
- package/src/view/observer/observer.js +81 -102
- package/src/view/observer/selectionobserver.js +191 -246
- package/src/view/observer/tabobserver.js +23 -36
- package/src/view/placeholder.js +128 -173
- package/src/view/position.js +350 -401
- package/src/view/range.js +453 -513
- package/src/view/rawelement.js +85 -112
- package/src/view/renderer.js +874 -1018
- package/src/view/rooteditableelement.js +80 -90
- package/src/view/selection.js +608 -689
- package/src/view/styles/background.js +43 -44
- package/src/view/styles/border.js +220 -276
- package/src/view/styles/margin.js +8 -17
- package/src/view/styles/padding.js +8 -16
- package/src/view/styles/utils.js +127 -160
- package/src/view/stylesmap.js +728 -905
- package/src/view/text.js +102 -126
- package/src/view/textproxy.js +144 -170
- package/src/view/treewalker.js +383 -479
- package/src/view/typecheckable.js +19 -0
- package/src/view/uielement.js +166 -187
- package/src/view/upcastwriter.js +395 -449
- package/src/view/view.js +569 -664
- package/src/dataprocessor/dataprocessor.jsdoc +0 -64
- package/src/model/item.jsdoc +0 -14
- package/src/view/elementdefinition.jsdoc +0 -59
- package/src/view/item.jsdoc +0 -14
|
@@ -2,14 +2,11 @@
|
|
|
2
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
|
-
|
|
6
5
|
/**
|
|
7
6
|
* @module engine/conversion/modelconsumable
|
|
8
7
|
*/
|
|
9
|
-
|
|
10
8
|
import TextProxy from '../model/textproxy';
|
|
11
9
|
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
|
|
12
|
-
|
|
13
10
|
/**
|
|
14
11
|
* Manages a list of consumable values for the {@link module:engine/model/item~Item model items}.
|
|
15
12
|
*
|
|
@@ -89,291 +86,251 @@ import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
|
|
|
89
86
|
* } );
|
|
90
87
|
*/
|
|
91
88
|
export default class ModelConsumable {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Adds a symbol for the given {@link module:engine/model/textproxy~TextProxy} instance.
|
|
324
|
-
*
|
|
325
|
-
* Used internally to correctly consume `TextProxy` instances.
|
|
326
|
-
*
|
|
327
|
-
* @private
|
|
328
|
-
* @param {module:engine/model/textproxy~TextProxy} textProxy Text proxy instance.
|
|
329
|
-
* @returns {Symbol} Symbol generated for given `TextProxy`.
|
|
330
|
-
*/
|
|
331
|
-
_addSymbolForTextProxy( textProxy ) {
|
|
332
|
-
const start = textProxy.startOffset;
|
|
333
|
-
const end = textProxy.endOffset;
|
|
334
|
-
const parent = textProxy.parent;
|
|
335
|
-
|
|
336
|
-
const symbol = Symbol( '$textProxy:' + textProxy.data );
|
|
337
|
-
let startMap, endMap;
|
|
338
|
-
|
|
339
|
-
startMap = this._textProxyRegistry.get( start );
|
|
340
|
-
|
|
341
|
-
if ( !startMap ) {
|
|
342
|
-
startMap = new Map();
|
|
343
|
-
this._textProxyRegistry.set( start, startMap );
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
endMap = startMap.get( end );
|
|
347
|
-
|
|
348
|
-
if ( !endMap ) {
|
|
349
|
-
endMap = new Map();
|
|
350
|
-
startMap.set( end, endMap );
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
endMap.set( parent, symbol );
|
|
354
|
-
|
|
355
|
-
return symbol;
|
|
356
|
-
}
|
|
89
|
+
/**
|
|
90
|
+
* Creates an empty consumables list.
|
|
91
|
+
*/
|
|
92
|
+
constructor() {
|
|
93
|
+
/**
|
|
94
|
+
* Contains list of consumable values.
|
|
95
|
+
*
|
|
96
|
+
* @private
|
|
97
|
+
* @member {Map} module:engine/conversion/modelconsumable~ModelConsumable#_consumable
|
|
98
|
+
*/
|
|
99
|
+
this._consumable = new Map();
|
|
100
|
+
/**
|
|
101
|
+
* For each {@link module:engine/model/textproxy~TextProxy} added to `ModelConsumable`, this registry holds a parent
|
|
102
|
+
* of that `TextProxy` and the start and end indices of that `TextProxy`. This allows identification of the `TextProxy`
|
|
103
|
+
* instances that point to the same part of the model but are different instances. Each distinct `TextProxy`
|
|
104
|
+
* is given a unique `Symbol` which is then registered as consumable. This process is transparent for the `ModelConsumable`
|
|
105
|
+
* API user because whenever `TextProxy` is added, tested, consumed or reverted, the internal mechanisms of
|
|
106
|
+
* `ModelConsumable` translate `TextProxy` to that unique `Symbol`.
|
|
107
|
+
*
|
|
108
|
+
* @private
|
|
109
|
+
* @member {Map} module:engine/conversion/modelconsumable~ModelConsumable#_textProxyRegistry
|
|
110
|
+
*/
|
|
111
|
+
this._textProxyRegistry = new Map();
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Adds a consumable value to the consumables list and links it with a given model item.
|
|
115
|
+
*
|
|
116
|
+
* modelConsumable.add( modelElement, 'insert' ); // Add `modelElement` insertion change to consumable values.
|
|
117
|
+
* modelConsumable.add( modelElement, 'addAttribute:bold' ); // Add `bold` attribute insertion on `modelElement` change.
|
|
118
|
+
* modelConsumable.add( modelElement, 'removeAttribute:bold' ); // Add `bold` attribute removal on `modelElement` change.
|
|
119
|
+
* modelConsumable.add( modelSelection, 'selection' ); // Add `modelSelection` to consumable values.
|
|
120
|
+
* modelConsumable.add( modelRange, 'range' ); // Add `modelRange` to consumable values.
|
|
121
|
+
*
|
|
122
|
+
* @param {module:engine/model/item~Item|module:engine/model/selection~Selection|module:engine/model/range~Range} item
|
|
123
|
+
* Model item, range or selection that has the consumable.
|
|
124
|
+
* @param {String} type Consumable type. Will be normalized to a proper form, that is either `<word>` or `<part>:<part>`.
|
|
125
|
+
* Second colon and everything after will be cut. Passing event name is a safe and good practice.
|
|
126
|
+
*/
|
|
127
|
+
add(item, type) {
|
|
128
|
+
type = _normalizeConsumableType(type);
|
|
129
|
+
if (item instanceof TextProxy) {
|
|
130
|
+
item = this._getSymbolForTextProxy(item);
|
|
131
|
+
}
|
|
132
|
+
if (!this._consumable.has(item)) {
|
|
133
|
+
this._consumable.set(item, new Map());
|
|
134
|
+
}
|
|
135
|
+
this._consumable.get(item).set(type, true);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Removes a given consumable value from a given model item.
|
|
139
|
+
*
|
|
140
|
+
* modelConsumable.consume( modelElement, 'insert' ); // Remove `modelElement` insertion change from consumable values.
|
|
141
|
+
* modelConsumable.consume( modelElement, 'addAttribute:bold' ); // Remove `bold` attribute insertion on `modelElement` change.
|
|
142
|
+
* modelConsumable.consume( modelElement, 'removeAttribute:bold' ); // Remove `bold` attribute removal on `modelElement` change.
|
|
143
|
+
* modelConsumable.consume( modelSelection, 'selection' ); // Remove `modelSelection` from consumable values.
|
|
144
|
+
* modelConsumable.consume( modelRange, 'range' ); // Remove 'modelRange' from consumable values.
|
|
145
|
+
*
|
|
146
|
+
* @param {module:engine/model/item~Item|module:engine/model/selection~Selection|module:engine/model/range~Range} item
|
|
147
|
+
* Model item, range or selection from which consumable will be consumed.
|
|
148
|
+
* @param {String} type Consumable type. Will be normalized to a proper form, that is either `<word>` or `<part>:<part>`.
|
|
149
|
+
* Second colon and everything after will be cut. Passing event name is a safe and good practice.
|
|
150
|
+
* @returns {Boolean} `true` if consumable value was available and was consumed, `false` otherwise.
|
|
151
|
+
*/
|
|
152
|
+
consume(item, type) {
|
|
153
|
+
type = _normalizeConsumableType(type);
|
|
154
|
+
if (item instanceof TextProxy) {
|
|
155
|
+
item = this._getSymbolForTextProxy(item);
|
|
156
|
+
}
|
|
157
|
+
if (this.test(item, type)) {
|
|
158
|
+
this._consumable.get(item).set(type, false);
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Tests whether there is a consumable value of a given type connected with a given model item.
|
|
167
|
+
*
|
|
168
|
+
* modelConsumable.test( modelElement, 'insert' ); // Check for `modelElement` insertion change.
|
|
169
|
+
* modelConsumable.test( modelElement, 'addAttribute:bold' ); // Check for `bold` attribute insertion on `modelElement` change.
|
|
170
|
+
* modelConsumable.test( modelElement, 'removeAttribute:bold' ); // Check for `bold` attribute removal on `modelElement` change.
|
|
171
|
+
* modelConsumable.test( modelSelection, 'selection' ); // Check if `modelSelection` is consumable.
|
|
172
|
+
* modelConsumable.test( modelRange, 'range' ); // Check if `modelRange` is consumable.
|
|
173
|
+
*
|
|
174
|
+
* @param {module:engine/model/item~Item|module:engine/model/selection~Selection|module:engine/model/range~Range} item
|
|
175
|
+
* Model item, range or selection to be tested.
|
|
176
|
+
* @param {String} type Consumable type. Will be normalized to a proper form, that is either `<word>` or `<part>:<part>`.
|
|
177
|
+
* Second colon and everything after will be cut. Passing event name is a safe and good practice.
|
|
178
|
+
* @returns {null|Boolean} `null` if such consumable was never added, `false` if the consumable values was
|
|
179
|
+
* already consumed or `true` if it was added and not consumed yet.
|
|
180
|
+
*/
|
|
181
|
+
test(item, type) {
|
|
182
|
+
type = _normalizeConsumableType(type);
|
|
183
|
+
if (item instanceof TextProxy) {
|
|
184
|
+
item = this._getSymbolForTextProxy(item);
|
|
185
|
+
}
|
|
186
|
+
const itemConsumables = this._consumable.get(item);
|
|
187
|
+
if (itemConsumables === undefined) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
const value = itemConsumables.get(type);
|
|
191
|
+
if (value === undefined) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
return value;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Reverts consuming of a consumable value.
|
|
198
|
+
*
|
|
199
|
+
* modelConsumable.revert( modelElement, 'insert' ); // Revert consuming `modelElement` insertion change.
|
|
200
|
+
* modelConsumable.revert( modelElement, 'addAttribute:bold' ); // Revert consuming `bold` attribute insert from `modelElement`.
|
|
201
|
+
* modelConsumable.revert( modelElement, 'removeAttribute:bold' ); // Revert consuming `bold` attribute remove from `modelElement`.
|
|
202
|
+
* modelConsumable.revert( modelSelection, 'selection' ); // Revert consuming `modelSelection`.
|
|
203
|
+
* modelConsumable.revert( modelRange, 'range' ); // Revert consuming `modelRange`.
|
|
204
|
+
*
|
|
205
|
+
* @param {module:engine/model/item~Item|module:engine/model/selection~Selection|module:engine/model/range~Range} item
|
|
206
|
+
* Model item, range or selection to be reverted.
|
|
207
|
+
* @param {String} type Consumable type.
|
|
208
|
+
* @returns {null|Boolean} `true` if consumable has been reversed, `false` otherwise. `null` if the consumable has
|
|
209
|
+
* never been added.
|
|
210
|
+
*/
|
|
211
|
+
revert(item, type) {
|
|
212
|
+
type = _normalizeConsumableType(type);
|
|
213
|
+
if (item instanceof TextProxy) {
|
|
214
|
+
item = this._getSymbolForTextProxy(item);
|
|
215
|
+
}
|
|
216
|
+
const test = this.test(item, type);
|
|
217
|
+
if (test === false) {
|
|
218
|
+
this._consumable.get(item).set(type, true);
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
else if (test === true) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Verifies if all events from the specified group were consumed.
|
|
228
|
+
*
|
|
229
|
+
* @param {String} eventGroup The events group to verify.
|
|
230
|
+
*/
|
|
231
|
+
verifyAllConsumed(eventGroup) {
|
|
232
|
+
const items = [];
|
|
233
|
+
for (const [item, consumables] of this._consumable) {
|
|
234
|
+
for (const [event, canConsume] of consumables) {
|
|
235
|
+
const eventPrefix = event.split(':')[0];
|
|
236
|
+
if (canConsume && eventGroup == eventPrefix) {
|
|
237
|
+
items.push({
|
|
238
|
+
event,
|
|
239
|
+
item: item.name || item.description
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (items.length) {
|
|
245
|
+
/**
|
|
246
|
+
* Some of the {@link module:engine/model/item~Item model items} were not consumed while downcasting the model to view.
|
|
247
|
+
*
|
|
248
|
+
* This might be the effect of:
|
|
249
|
+
*
|
|
250
|
+
* * A missing converter for some model elements. Make sure that you registered downcast converters for all model elements.
|
|
251
|
+
* * A custom converter that does not consume converted items. Make sure that you
|
|
252
|
+
* {@link module:engine/conversion/modelconsumable~ModelConsumable#consume consumed} all model elements that you converted
|
|
253
|
+
* from the model to the view.
|
|
254
|
+
* * A custom converter that called `event.stop()`. When providing a custom converter, keep in mind that you should not stop
|
|
255
|
+
* the event. If you stop it then the default converter at the `lowest` priority will not trigger the conversion of this node's
|
|
256
|
+
* attributes and child nodes.
|
|
257
|
+
*
|
|
258
|
+
* @error conversion-model-consumable-not-consumed
|
|
259
|
+
* @param {Array.<module:engine/model/item~Item>} items Items that were not consumed.
|
|
260
|
+
*/
|
|
261
|
+
throw new CKEditorError('conversion-model-consumable-not-consumed', null, { items });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Gets a unique symbol for the passed {@link module:engine/model/textproxy~TextProxy} instance. All `TextProxy` instances that
|
|
266
|
+
* have same parent, same start index and same end index will get the same symbol.
|
|
267
|
+
*
|
|
268
|
+
* Used internally to correctly consume `TextProxy` instances.
|
|
269
|
+
*
|
|
270
|
+
* @internal
|
|
271
|
+
* @protected
|
|
272
|
+
* @param {module:engine/model/textproxy~TextProxy} textProxy `TextProxy` instance to get a symbol for.
|
|
273
|
+
* @returns {Symbol} Symbol representing all equal instances of `TextProxy`.
|
|
274
|
+
*/
|
|
275
|
+
_getSymbolForTextProxy(textProxy) {
|
|
276
|
+
let symbol = null;
|
|
277
|
+
const startMap = this._textProxyRegistry.get(textProxy.startOffset);
|
|
278
|
+
if (startMap) {
|
|
279
|
+
const endMap = startMap.get(textProxy.endOffset);
|
|
280
|
+
if (endMap) {
|
|
281
|
+
symbol = endMap.get(textProxy.parent);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if (!symbol) {
|
|
285
|
+
symbol = this._addSymbolForTextProxy(textProxy);
|
|
286
|
+
}
|
|
287
|
+
return symbol;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Adds a symbol for the given {@link module:engine/model/textproxy~TextProxy} instance.
|
|
291
|
+
*
|
|
292
|
+
* Used internally to correctly consume `TextProxy` instances.
|
|
293
|
+
*
|
|
294
|
+
* @private
|
|
295
|
+
* @param {module:engine/model/textproxy~TextProxy} textProxy Text proxy instance.
|
|
296
|
+
* @returns {Symbol} Symbol generated for given `TextProxy`.
|
|
297
|
+
*/
|
|
298
|
+
_addSymbolForTextProxy(textProxy) {
|
|
299
|
+
const start = textProxy.startOffset;
|
|
300
|
+
const end = textProxy.endOffset;
|
|
301
|
+
const parent = textProxy.parent;
|
|
302
|
+
const symbol = Symbol('$textProxy:' + textProxy.data);
|
|
303
|
+
let startMap;
|
|
304
|
+
let endMap;
|
|
305
|
+
startMap = this._textProxyRegistry.get(start);
|
|
306
|
+
if (!startMap) {
|
|
307
|
+
startMap = new Map();
|
|
308
|
+
this._textProxyRegistry.set(start, startMap);
|
|
309
|
+
}
|
|
310
|
+
endMap = startMap.get(end);
|
|
311
|
+
if (!endMap) {
|
|
312
|
+
endMap = new Map();
|
|
313
|
+
startMap.set(end, endMap);
|
|
314
|
+
}
|
|
315
|
+
endMap.set(parent, symbol);
|
|
316
|
+
return symbol;
|
|
317
|
+
}
|
|
357
318
|
}
|
|
358
|
-
|
|
359
319
|
// Returns a normalized consumable type name from the given string. A normalized consumable type name is a string that has
|
|
360
320
|
// at most one colon, for example: `insert` or `addMarker:highlight`. If a string to normalize has more "parts" (more colons),
|
|
361
321
|
// the further parts are dropped, for example: `addattribute:bold:$text` -> `addattributes:bold`.
|
|
362
322
|
//
|
|
363
323
|
// @param {String} type Consumable type.
|
|
364
324
|
// @returns {String} Normalized consumable type.
|
|
365
|
-
function _normalizeConsumableType(
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
return parts.length > 1 ? parts[ 0 ] + ':' + parts[ 1 ] : parts[ 0 ];
|
|
325
|
+
function _normalizeConsumableType(type) {
|
|
326
|
+
const parts = type.split(':');
|
|
327
|
+
// For inserts allow passing event name, it's stored in the context of a specified element so the element name is not needed.
|
|
328
|
+
if (parts[0] == 'insert') {
|
|
329
|
+
return parts[0];
|
|
330
|
+
}
|
|
331
|
+
// Markers are identified by the whole name (otherwise we would consume the whole markers group).
|
|
332
|
+
if (parts[0] == 'addMarker' || parts[0] == 'removeMarker') {
|
|
333
|
+
return type;
|
|
334
|
+
}
|
|
335
|
+
return parts.length > 1 ? parts[0] + ':' + parts[1] : parts[0];
|
|
379
336
|
}
|