@ckeditor/ckeditor5-engine 34.2.0 → 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 +823 -0
- package/LICENSE.md +4 -0
- package/package.json +32 -25
- 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 +101 -117
- package/src/dataprocessor/htmlwriter.js +1 -18
- package/src/dataprocessor/xmldataprocessor.js +117 -138
- 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 +1371 -1613
- 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 -1014
- 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,16 +2,14 @@
|
|
|
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
|
-
|
|
5
|
+
/* eslint-disable new-cap */
|
|
6
6
|
/**
|
|
7
7
|
* @module engine/model/markercollection
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
import TypeCheckable from './typecheckable';
|
|
10
10
|
import LiveRange from './liverange';
|
|
11
|
-
import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
|
|
11
|
+
import EmitterMixin, { Emitter } from '@ckeditor/ckeditor5-utils/src/emittermixin';
|
|
12
12
|
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
|
|
13
|
-
import mix from '@ckeditor/ckeditor5-utils/src/mix';
|
|
14
|
-
|
|
15
13
|
/**
|
|
16
14
|
* The collection of all {@link module:engine/model/markercollection~Marker markers} attached to the document.
|
|
17
15
|
* It lets you {@link module:engine/model/markercollection~MarkerCollection#get get} markers or track them using
|
|
@@ -26,269 +24,218 @@ import mix from '@ckeditor/ckeditor5-utils/src/mix';
|
|
|
26
24
|
*
|
|
27
25
|
* @see module:engine/model/markercollection~Marker
|
|
28
26
|
*/
|
|
29
|
-
export default class MarkerCollection {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
* const markerFooA = markersCollection.set( 'foo:a', rangeFooA );
|
|
241
|
-
* const markerFooB = markersCollection.set( 'foo:b', rangeFooB );
|
|
242
|
-
* const markerBarA = markersCollection.set( 'bar:a', rangeBarA );
|
|
243
|
-
* const markerFooBarA = markersCollection.set( 'foobar:a', rangeFooBarA );
|
|
244
|
-
* Array.from( markersCollection.getMarkersGroup( 'foo' ) ); // [ markerFooA, markerFooB ]
|
|
245
|
-
* Array.from( markersCollection.getMarkersGroup( 'a' ) ); // []
|
|
246
|
-
*
|
|
247
|
-
* @param prefix
|
|
248
|
-
* @returns {Iterable.<module:engine/model/markercollection~Marker>}
|
|
249
|
-
*/
|
|
250
|
-
* getMarkersGroup( prefix ) {
|
|
251
|
-
for ( const marker of this._markers.values() ) {
|
|
252
|
-
if ( marker.name.startsWith( prefix + ':' ) ) {
|
|
253
|
-
yield marker;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Destroys the marker.
|
|
260
|
-
*
|
|
261
|
-
* @private
|
|
262
|
-
* @param {module:engine/model/markercollection~Marker} marker Marker to destroy.
|
|
263
|
-
*/
|
|
264
|
-
_destroyMarker( marker ) {
|
|
265
|
-
marker.stopListening();
|
|
266
|
-
marker._detachLiveRange();
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Fired whenever marker is added, updated or removed from `MarkerCollection`.
|
|
271
|
-
*
|
|
272
|
-
* @event update
|
|
273
|
-
* @param {module:engine/model/markercollection~Marker} marker Updated Marker.
|
|
274
|
-
* @param {module:engine/model/range~Range|null} oldRange Marker range before the update. When is not defined it
|
|
275
|
-
* means that marker is just added.
|
|
276
|
-
* @param {module:engine/model/range~Range|null} newRange Marker range after update. When is not defined it
|
|
277
|
-
* means that marker is just removed.
|
|
278
|
-
* @param {module:engine/model/markercollection~MarkerData} oldMarkerData Data of the marker before the change.
|
|
279
|
-
*/
|
|
27
|
+
export default class MarkerCollection extends Emitter {
|
|
28
|
+
/**
|
|
29
|
+
* Creates a markers collection.
|
|
30
|
+
*/
|
|
31
|
+
constructor() {
|
|
32
|
+
super();
|
|
33
|
+
/**
|
|
34
|
+
* Stores {@link ~Marker markers} added to the collection.
|
|
35
|
+
*
|
|
36
|
+
* @private
|
|
37
|
+
* @member {Map} #_markers
|
|
38
|
+
*/
|
|
39
|
+
this._markers = new Map();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Iterable interface.
|
|
43
|
+
*
|
|
44
|
+
* Iterates over all {@link ~Marker markers} added to the collection.
|
|
45
|
+
*
|
|
46
|
+
* @returns {Iterator}
|
|
47
|
+
*/
|
|
48
|
+
[Symbol.iterator]() {
|
|
49
|
+
return this._markers.values();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Checks if given {@link ~Marker marker} or marker name is in the collection.
|
|
53
|
+
*
|
|
54
|
+
* @param {String|module:engine/model/markercollection~Marker} markerOrName Name of marker or marker instance to check.
|
|
55
|
+
* @returns {Boolean} `true` if marker is in the collection, `false` otherwise.
|
|
56
|
+
*/
|
|
57
|
+
has(markerOrName) {
|
|
58
|
+
const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
|
|
59
|
+
return this._markers.has(markerName);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns {@link ~Marker marker} with given `markerName`.
|
|
63
|
+
*
|
|
64
|
+
* @param {String} markerName Name of marker to get.
|
|
65
|
+
* @returns {module:engine/model/markercollection~Marker|null} Marker with given name or `null` if such marker was
|
|
66
|
+
* not added to the collection.
|
|
67
|
+
*/
|
|
68
|
+
get(markerName) {
|
|
69
|
+
return this._markers.get(markerName) || null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Creates and adds a {@link ~Marker marker} to the `MarkerCollection` with given name on given
|
|
73
|
+
* {@link module:engine/model/range~Range range}.
|
|
74
|
+
*
|
|
75
|
+
* If `MarkerCollection` already had a marker with given name (or {@link ~Marker marker} was passed), the marker in
|
|
76
|
+
* collection is updated and {@link module:engine/model/markercollection~MarkerCollection#event:update} event is fired
|
|
77
|
+
* but only if there was a change (marker range or {@link module:engine/model/markercollection~Marker#managedUsingOperations}
|
|
78
|
+
* flag has changed.
|
|
79
|
+
*
|
|
80
|
+
* @internal
|
|
81
|
+
* @protected
|
|
82
|
+
* @fires module:engine/model/markercollection~MarkerCollection#event:update
|
|
83
|
+
* @param {String|module:engine/model/markercollection~Marker} markerOrName Name of marker to set or marker instance to update.
|
|
84
|
+
* @param {module:engine/model/range~Range} range Marker range.
|
|
85
|
+
* @param {Boolean} [managedUsingOperations=false] Specifies whether the marker is managed using operations.
|
|
86
|
+
* @param {Boolean} [affectsData=false] Specifies whether the marker affects the data produced by the data pipeline
|
|
87
|
+
* (is persisted in the editor's data).
|
|
88
|
+
* @returns {module:engine/model/markercollection~Marker} `Marker` instance which was added or updated.
|
|
89
|
+
*/
|
|
90
|
+
_set(markerOrName, range, managedUsingOperations = false, affectsData = false) {
|
|
91
|
+
const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
|
|
92
|
+
if (markerName.includes(',')) {
|
|
93
|
+
/**
|
|
94
|
+
* Marker name cannot contain the "," character.
|
|
95
|
+
*
|
|
96
|
+
* @error markercollection-incorrect-marker-name
|
|
97
|
+
*/
|
|
98
|
+
throw new CKEditorError('markercollection-incorrect-marker-name', this);
|
|
99
|
+
}
|
|
100
|
+
const oldMarker = this._markers.get(markerName);
|
|
101
|
+
if (oldMarker) {
|
|
102
|
+
const oldMarkerData = oldMarker.getData();
|
|
103
|
+
const oldRange = oldMarker.getRange();
|
|
104
|
+
let hasChanged = false;
|
|
105
|
+
if (!oldRange.isEqual(range)) {
|
|
106
|
+
oldMarker._attachLiveRange(LiveRange.fromRange(range));
|
|
107
|
+
hasChanged = true;
|
|
108
|
+
}
|
|
109
|
+
if (managedUsingOperations != oldMarker.managedUsingOperations) {
|
|
110
|
+
oldMarker._managedUsingOperations = managedUsingOperations;
|
|
111
|
+
hasChanged = true;
|
|
112
|
+
}
|
|
113
|
+
if (typeof affectsData === 'boolean' && affectsData != oldMarker.affectsData) {
|
|
114
|
+
oldMarker._affectsData = affectsData;
|
|
115
|
+
hasChanged = true;
|
|
116
|
+
}
|
|
117
|
+
if (hasChanged) {
|
|
118
|
+
this.fire(`update:${markerName}`, oldMarker, oldRange, range, oldMarkerData);
|
|
119
|
+
}
|
|
120
|
+
return oldMarker;
|
|
121
|
+
}
|
|
122
|
+
const liveRange = LiveRange.fromRange(range);
|
|
123
|
+
const marker = new Marker(markerName, liveRange, managedUsingOperations, affectsData);
|
|
124
|
+
this._markers.set(markerName, marker);
|
|
125
|
+
this.fire(`update:${markerName}`, marker, null, range, { ...marker.getData(), range: null });
|
|
126
|
+
return marker;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Removes given {@link ~Marker marker} or a marker with given name from the `MarkerCollection`.
|
|
130
|
+
*
|
|
131
|
+
* @internal
|
|
132
|
+
* @protected
|
|
133
|
+
* @fires module:engine/model/markercollection~MarkerCollection#event:update
|
|
134
|
+
* @param {String|module:engine/model/markercollection~Marker} markerOrName Marker or name of a marker to remove.
|
|
135
|
+
* @returns {Boolean} `true` if marker was found and removed, `false` otherwise.
|
|
136
|
+
*/
|
|
137
|
+
_remove(markerOrName) {
|
|
138
|
+
const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
|
|
139
|
+
const oldMarker = this._markers.get(markerName);
|
|
140
|
+
if (oldMarker) {
|
|
141
|
+
this._markers.delete(markerName);
|
|
142
|
+
this.fire(`update:${markerName}`, oldMarker, oldMarker.getRange(), null, oldMarker.getData());
|
|
143
|
+
this._destroyMarker(oldMarker);
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Fires an {@link module:engine/model/markercollection~MarkerCollection#event:update} event for the given {@link ~Marker marker}
|
|
150
|
+
* but does not change the marker. Useful to force {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher downcast
|
|
151
|
+
* conversion} for the marker.
|
|
152
|
+
*
|
|
153
|
+
* @internal
|
|
154
|
+
* @protected
|
|
155
|
+
* @fires module:engine/model/markercollection~MarkerCollection#event:update
|
|
156
|
+
* @param {String|module:engine/model/markercollection~Marker} markerOrName Marker or name of a marker to refresh.
|
|
157
|
+
*/
|
|
158
|
+
_refresh(markerOrName) {
|
|
159
|
+
const markerName = markerOrName instanceof Marker ? markerOrName.name : markerOrName;
|
|
160
|
+
const marker = this._markers.get(markerName);
|
|
161
|
+
if (!marker) {
|
|
162
|
+
/**
|
|
163
|
+
* Marker with provided name does not exists.
|
|
164
|
+
*
|
|
165
|
+
* @error markercollection-refresh-marker-not-exists
|
|
166
|
+
*/
|
|
167
|
+
throw new CKEditorError('markercollection-refresh-marker-not-exists', this);
|
|
168
|
+
}
|
|
169
|
+
const range = marker.getRange();
|
|
170
|
+
this.fire(`update:${markerName}`, marker, range, range, marker.getData());
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Returns iterator that iterates over all markers, which ranges contain given {@link module:engine/model/position~Position position}.
|
|
174
|
+
*
|
|
175
|
+
* @param {module:engine/model/position~Position} position
|
|
176
|
+
* @returns {Iterable.<module:engine/model/markercollection~Marker>}
|
|
177
|
+
*/
|
|
178
|
+
*getMarkersAtPosition(position) {
|
|
179
|
+
for (const marker of this) {
|
|
180
|
+
if (marker.getRange().containsPosition(position)) {
|
|
181
|
+
yield marker;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Returns iterator that iterates over all markers, which intersects with given {@link module:engine/model/range~Range range}.
|
|
187
|
+
*
|
|
188
|
+
* @param {module:engine/model/range~Range} range
|
|
189
|
+
* @returns {Iterable.<module:engine/model/markercollection~Marker>}
|
|
190
|
+
*/
|
|
191
|
+
*getMarkersIntersectingRange(range) {
|
|
192
|
+
for (const marker of this) {
|
|
193
|
+
if (marker.getRange().getIntersection(range) !== null) {
|
|
194
|
+
yield marker;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Destroys marker collection and all markers inside it.
|
|
200
|
+
*/
|
|
201
|
+
destroy() {
|
|
202
|
+
for (const marker of this._markers.values()) {
|
|
203
|
+
this._destroyMarker(marker);
|
|
204
|
+
}
|
|
205
|
+
this._markers = null;
|
|
206
|
+
this.stopListening();
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Iterates over all markers that starts with given `prefix`.
|
|
210
|
+
*
|
|
211
|
+
* const markerFooA = markersCollection.set( 'foo:a', rangeFooA );
|
|
212
|
+
* const markerFooB = markersCollection.set( 'foo:b', rangeFooB );
|
|
213
|
+
* const markerBarA = markersCollection.set( 'bar:a', rangeBarA );
|
|
214
|
+
* const markerFooBarA = markersCollection.set( 'foobar:a', rangeFooBarA );
|
|
215
|
+
* Array.from( markersCollection.getMarkersGroup( 'foo' ) ); // [ markerFooA, markerFooB ]
|
|
216
|
+
* Array.from( markersCollection.getMarkersGroup( 'a' ) ); // []
|
|
217
|
+
*
|
|
218
|
+
* @param prefix
|
|
219
|
+
* @returns {Iterable.<module:engine/model/markercollection~Marker>}
|
|
220
|
+
*/
|
|
221
|
+
*getMarkersGroup(prefix) {
|
|
222
|
+
for (const marker of this._markers.values()) {
|
|
223
|
+
if (marker.name.startsWith(prefix + ':')) {
|
|
224
|
+
yield marker;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Destroys the marker.
|
|
230
|
+
*
|
|
231
|
+
* @private
|
|
232
|
+
* @param {module:engine/model/markercollection~Marker} marker Marker to destroy.
|
|
233
|
+
*/
|
|
234
|
+
_destroyMarker(marker) {
|
|
235
|
+
marker.stopListening();
|
|
236
|
+
marker._detachLiveRange();
|
|
237
|
+
}
|
|
280
238
|
}
|
|
281
|
-
|
|
282
|
-
mix( MarkerCollection, EmitterMixin );
|
|
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
|
-
|
|
292
239
|
/**
|
|
293
240
|
* `Marker` is a continuous parts of model (like a range), is named and represent some kind of information about marked
|
|
294
241
|
* part of model document. In contrary to {@link module:engine/model/node~Node nodes}, which are building blocks of
|
|
@@ -356,220 +303,172 @@ mix( MarkerCollection, EmitterMixin );
|
|
|
356
303
|
*
|
|
357
304
|
* `Marker` instances are created and destroyed only by {@link ~MarkerCollection MarkerCollection}.
|
|
358
305
|
*/
|
|
359
|
-
class Marker {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* Binds new live range to the marker and detach the old one if is attached.
|
|
511
|
-
*
|
|
512
|
-
* @protected
|
|
513
|
-
* @param {module:engine/model/liverange~LiveRange} liveRange Live range to attach
|
|
514
|
-
* @returns {module:engine/model/liverange~LiveRange} Attached live range.
|
|
515
|
-
*/
|
|
516
|
-
_attachLiveRange( liveRange ) {
|
|
517
|
-
if ( this._liveRange ) {
|
|
518
|
-
this._detachLiveRange();
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
// Delegating does not work with namespaces. Alternatively, we could delegate all events (using `*`).
|
|
522
|
-
liveRange.delegate( 'change:range' ).to( this );
|
|
523
|
-
liveRange.delegate( 'change:content' ).to( this );
|
|
524
|
-
|
|
525
|
-
this._liveRange = liveRange;
|
|
526
|
-
|
|
527
|
-
return liveRange;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
/**
|
|
531
|
-
* Unbinds and destroys currently attached live range.
|
|
532
|
-
*
|
|
533
|
-
* @protected
|
|
534
|
-
*/
|
|
535
|
-
_detachLiveRange() {
|
|
536
|
-
this._liveRange.stopDelegating( 'change:range', this );
|
|
537
|
-
this._liveRange.stopDelegating( 'change:content', this );
|
|
538
|
-
this._liveRange.detach();
|
|
539
|
-
this._liveRange = null;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
/**
|
|
543
|
-
* Fired whenever {@link ~Marker#_liveRange marker range} is changed due to changes on {@link module:engine/model/document~Document}.
|
|
544
|
-
* This is a delegated {@link module:engine/model/liverange~LiveRange#event:change:range LiveRange change:range event}.
|
|
545
|
-
*
|
|
546
|
-
* When marker is removed from {@link module:engine/model/markercollection~MarkerCollection MarkerCollection},
|
|
547
|
-
* all event listeners listening to it should be removed. It is best to do it on
|
|
548
|
-
* {@link module:engine/model/markercollection~MarkerCollection#event:update MarkerCollection update event}.
|
|
549
|
-
*
|
|
550
|
-
* @see module:engine/model/liverange~LiveRange#event:change:range
|
|
551
|
-
* @event change:range
|
|
552
|
-
* @param {module:engine/model/range~Range} oldRange
|
|
553
|
-
* @param {Object} data
|
|
554
|
-
*/
|
|
555
|
-
|
|
556
|
-
/**
|
|
557
|
-
* Fired whenever change on {@link module:engine/model/document~Document} is done inside {@link ~Marker#_liveRange marker range}.
|
|
558
|
-
* This is a delegated {@link module:engine/model/liverange~LiveRange#event:change:content LiveRange change:content event}.
|
|
559
|
-
*
|
|
560
|
-
* When marker is removed from {@link module:engine/model/markercollection~MarkerCollection MarkerCollection},
|
|
561
|
-
* all event listeners listening to it should be removed. It is best to do it on
|
|
562
|
-
* {@link module:engine/model/markercollection~MarkerCollection#event:update MarkerCollection update event}.
|
|
563
|
-
*
|
|
564
|
-
* @see module:engine/model/liverange~LiveRange#event:change:content
|
|
565
|
-
* @event change:content
|
|
566
|
-
* @param {module:engine/model/range~Range} oldRange
|
|
567
|
-
* @param {Object} data
|
|
568
|
-
*/
|
|
306
|
+
class Marker extends EmitterMixin(TypeCheckable) {
|
|
307
|
+
/**
|
|
308
|
+
* Creates a marker instance.
|
|
309
|
+
*
|
|
310
|
+
* @param {String} name Marker name.
|
|
311
|
+
* @param {module:engine/model/liverange~LiveRange} liveRange Range marked by the marker.
|
|
312
|
+
* @param {Boolean} managedUsingOperations Specifies whether the marker is managed using operations.
|
|
313
|
+
* @param {Boolean} affectsData Specifies whether the marker affects the data produced by the data pipeline
|
|
314
|
+
* (is persisted in the editor's data).
|
|
315
|
+
*/
|
|
316
|
+
constructor(name, liveRange, managedUsingOperations, affectsData) {
|
|
317
|
+
super();
|
|
318
|
+
/**
|
|
319
|
+
* Marker's name.
|
|
320
|
+
*
|
|
321
|
+
* @readonly
|
|
322
|
+
* @type {String}
|
|
323
|
+
*/
|
|
324
|
+
this.name = name;
|
|
325
|
+
/**
|
|
326
|
+
* Range marked by the marker.
|
|
327
|
+
*
|
|
328
|
+
* @protected
|
|
329
|
+
* @member {module:engine/model/liverange~LiveRange}
|
|
330
|
+
*/
|
|
331
|
+
this._liveRange = this._attachLiveRange(liveRange);
|
|
332
|
+
/**
|
|
333
|
+
* Flag indicates if the marker is managed using operations or not.
|
|
334
|
+
*
|
|
335
|
+
* @private
|
|
336
|
+
* @member {Boolean}
|
|
337
|
+
*/
|
|
338
|
+
this._managedUsingOperations = managedUsingOperations;
|
|
339
|
+
/**
|
|
340
|
+
* Specifies whether the marker affects the data produced by the data pipeline
|
|
341
|
+
* (is persisted in the editor's data).
|
|
342
|
+
*
|
|
343
|
+
* @private
|
|
344
|
+
* @member {Boolean}
|
|
345
|
+
*/
|
|
346
|
+
this._affectsData = affectsData;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* A value indicating if the marker is managed using operations.
|
|
350
|
+
* See {@link ~Marker marker class description} to learn more about marker types.
|
|
351
|
+
* See {@link module:engine/model/writer~Writer#addMarker}.
|
|
352
|
+
*
|
|
353
|
+
* @returns {Boolean}
|
|
354
|
+
*/
|
|
355
|
+
get managedUsingOperations() {
|
|
356
|
+
if (!this._liveRange) {
|
|
357
|
+
throw new CKEditorError('marker-destroyed', this);
|
|
358
|
+
}
|
|
359
|
+
return this._managedUsingOperations;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* A value indicating if the marker changes the data.
|
|
363
|
+
*
|
|
364
|
+
* @returns {Boolean}
|
|
365
|
+
*/
|
|
366
|
+
get affectsData() {
|
|
367
|
+
if (!this._liveRange) {
|
|
368
|
+
throw new CKEditorError('marker-destroyed', this);
|
|
369
|
+
}
|
|
370
|
+
return this._affectsData;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Returns the marker data (properties defining the marker).
|
|
374
|
+
*
|
|
375
|
+
* @returns {module:engine/model/markercollection~MarkerData}
|
|
376
|
+
*/
|
|
377
|
+
getData() {
|
|
378
|
+
return {
|
|
379
|
+
range: this.getRange(),
|
|
380
|
+
affectsData: this.affectsData,
|
|
381
|
+
managedUsingOperations: this.managedUsingOperations
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Returns current marker start position.
|
|
386
|
+
*
|
|
387
|
+
* @returns {module:engine/model/position~Position}
|
|
388
|
+
*/
|
|
389
|
+
getStart() {
|
|
390
|
+
if (!this._liveRange) {
|
|
391
|
+
throw new CKEditorError('marker-destroyed', this);
|
|
392
|
+
}
|
|
393
|
+
return this._liveRange.start.clone();
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Returns current marker end position.
|
|
397
|
+
*
|
|
398
|
+
* @returns {module:engine/model/position~Position}
|
|
399
|
+
*/
|
|
400
|
+
getEnd() {
|
|
401
|
+
if (!this._liveRange) {
|
|
402
|
+
throw new CKEditorError('marker-destroyed', this);
|
|
403
|
+
}
|
|
404
|
+
return this._liveRange.end.clone();
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Returns a range that represents the current state of the marker.
|
|
408
|
+
*
|
|
409
|
+
* Keep in mind that returned value is a {@link module:engine/model/range~Range Range}, not a
|
|
410
|
+
* {@link module:engine/model/liverange~LiveRange LiveRange}. This means that it is up-to-date and relevant only
|
|
411
|
+
* until next model document change. Do not store values returned by this method. Instead, store {@link ~Marker#name}
|
|
412
|
+
* and get `Marker` instance from {@link module:engine/model/markercollection~MarkerCollection MarkerCollection} every
|
|
413
|
+
* time there is a need to read marker properties. This will guarantee that the marker has not been removed and
|
|
414
|
+
* that it's data is up-to-date.
|
|
415
|
+
*
|
|
416
|
+
* @returns {module:engine/model/range~Range}
|
|
417
|
+
*/
|
|
418
|
+
getRange() {
|
|
419
|
+
if (!this._liveRange) {
|
|
420
|
+
throw new CKEditorError('marker-destroyed', this);
|
|
421
|
+
}
|
|
422
|
+
return this._liveRange.toRange();
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Binds new live range to the marker and detach the old one if is attached.
|
|
426
|
+
*
|
|
427
|
+
* @internal
|
|
428
|
+
* @protected
|
|
429
|
+
* @param {module:engine/model/liverange~LiveRange} liveRange Live range to attach
|
|
430
|
+
* @returns {module:engine/model/liverange~LiveRange} Attached live range.
|
|
431
|
+
*/
|
|
432
|
+
_attachLiveRange(liveRange) {
|
|
433
|
+
if (this._liveRange) {
|
|
434
|
+
this._detachLiveRange();
|
|
435
|
+
}
|
|
436
|
+
// Delegating does not work with namespaces. Alternatively, we could delegate all events (using `*`).
|
|
437
|
+
liveRange.delegate('change:range').to(this);
|
|
438
|
+
liveRange.delegate('change:content').to(this);
|
|
439
|
+
this._liveRange = liveRange;
|
|
440
|
+
return liveRange;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Unbinds and destroys currently attached live range.
|
|
444
|
+
*
|
|
445
|
+
* @internal
|
|
446
|
+
* @protected
|
|
447
|
+
*/
|
|
448
|
+
_detachLiveRange() {
|
|
449
|
+
this._liveRange.stopDelegating('change:range', this);
|
|
450
|
+
this._liveRange.stopDelegating('change:content', this);
|
|
451
|
+
this._liveRange.detach();
|
|
452
|
+
this._liveRange = null;
|
|
453
|
+
}
|
|
569
454
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
455
|
+
/**
|
|
456
|
+
* Checks whether this object is of the given.
|
|
457
|
+
*
|
|
458
|
+
* marker.is( 'marker' ); // -> true
|
|
459
|
+
* marker.is( 'model:marker' ); // -> true
|
|
460
|
+
*
|
|
461
|
+
* marker.is( 'view:element' ); // -> false
|
|
462
|
+
* marker.is( 'documentSelection' ); // -> false
|
|
463
|
+
*
|
|
464
|
+
* {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.
|
|
465
|
+
*
|
|
466
|
+
* @param {String} type
|
|
467
|
+
* @returns {Boolean}
|
|
468
|
+
*/
|
|
469
|
+
Marker.prototype.is = function (type) {
|
|
470
|
+
return type === 'marker' || type === 'model:marker';
|
|
471
|
+
};
|
|
573
472
|
/**
|
|
574
473
|
* Cannot use a {@link module:engine/model/markercollection~MarkerCollection#destroy destroyed marker} instance.
|
|
575
474
|
*
|