@ckeditor/ckeditor5-engine 35.4.0 → 36.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/package.json +22 -22
- package/src/controller/datacontroller.js +5 -1
- package/src/controller/editingcontroller.js +1 -1
- package/src/conversion/conversion.js +1 -1
- package/src/conversion/conversionhelpers.js +1 -1
- package/src/conversion/downcastdispatcher.js +1 -1
- package/src/conversion/downcasthelpers.js +1 -1
- package/src/conversion/mapper.js +1 -1
- package/src/conversion/modelconsumable.js +1 -1
- package/src/conversion/upcastdispatcher.js +1 -1
- package/src/conversion/upcasthelpers.js +8 -1
- package/src/conversion/viewconsumable.js +1 -1
- package/src/dataprocessor/basichtmlwriter.js +1 -1
- package/src/dataprocessor/dataprocessor.js +1 -1
- package/src/dataprocessor/htmldataprocessor.js +1 -2
- package/src/dataprocessor/htmlwriter.js +1 -1
- package/src/dataprocessor/xmldataprocessor.js +1 -1
- package/src/dev-utils/model.js +1 -1
- package/src/dev-utils/operationreplayer.js +1 -1
- package/src/dev-utils/utils.js +1 -1
- package/src/dev-utils/view.js +1 -1
- package/src/index.js +3 -2
- package/src/model/batch.js +9 -46
- package/src/model/differ.js +81 -174
- package/src/model/document.js +36 -92
- package/src/model/documentfragment.js +43 -96
- package/src/model/documentselection.js +151 -245
- package/src/model/element.js +47 -100
- package/src/model/history.js +15 -46
- package/src/model/item.js +1 -1
- package/src/model/liveposition.js +10 -36
- package/src/model/liverange.js +13 -36
- package/src/model/markercollection.js +40 -111
- package/src/model/model.js +212 -289
- package/src/model/node.js +35 -125
- package/src/model/nodelist.js +11 -39
- package/src/model/operation/attributeoperation.js +13 -44
- package/src/model/operation/detachoperation.js +3 -16
- package/src/model/operation/insertoperation.js +6 -34
- package/src/model/operation/markeroperation.js +9 -48
- package/src/model/operation/mergeoperation.js +8 -41
- package/src/model/operation/moveoperation.js +14 -37
- package/src/model/operation/nooperation.js +1 -7
- package/src/model/operation/operation.js +5 -63
- package/src/model/operation/operationfactory.js +3 -6
- package/src/model/operation/renameoperation.js +8 -28
- package/src/model/operation/rootattributeoperation.js +18 -47
- package/src/model/operation/splitoperation.js +9 -47
- package/src/model/operation/transform.js +109 -150
- package/src/model/operation/utils.js +36 -50
- package/src/model/position.js +117 -228
- package/src/model/range.js +145 -200
- package/src/model/rootelement.js +8 -47
- package/src/model/schema.js +236 -272
- package/src/model/selection.js +134 -192
- package/src/model/text.js +10 -37
- package/src/model/textproxy.js +15 -69
- package/src/model/treewalker.js +10 -101
- package/src/model/typecheckable.js +1 -1
- package/src/model/utils/autoparagraphing.js +11 -12
- package/src/model/utils/deletecontent.js +93 -62
- package/src/model/utils/findoptimalinsertionrange.js +24 -24
- package/src/model/utils/getselectedcontent.js +3 -6
- package/src/model/utils/insertcontent.js +36 -129
- package/src/model/utils/insertobject.js +19 -21
- package/src/model/utils/modifyselection.js +23 -33
- package/src/model/utils/selection-post-fixer.js +53 -59
- package/src/model/writer.js +208 -314
- package/src/view/attributeelement.js +1 -1
- package/src/view/containerelement.js +1 -1
- package/src/view/datatransfer.js +1 -1
- package/src/view/document.js +1 -17
- package/src/view/documentfragment.js +49 -1
- package/src/view/documentselection.js +1 -1
- package/src/view/domconverter.js +4 -3
- package/src/view/downcastwriter.js +1 -1
- package/src/view/editableelement.js +1 -1
- package/src/view/element.js +5 -5
- package/src/view/elementdefinition.js +1 -1
- package/src/view/emptyelement.js +1 -1
- package/src/view/filler.js +1 -1
- package/src/view/item.js +1 -1
- package/src/view/matcher.js +1 -1
- package/src/view/node.js +1 -1
- package/src/view/observer/arrowkeysobserver.js +1 -1
- package/src/view/observer/bubblingemittermixin.js +1 -1
- package/src/view/observer/bubblingeventinfo.js +1 -1
- package/src/view/observer/clickobserver.js +1 -1
- package/src/view/observer/compositionobserver.js +1 -1
- package/src/view/observer/domeventdata.js +1 -1
- package/src/view/observer/domeventobserver.js +1 -1
- package/src/view/observer/fakeselectionobserver.js +1 -1
- package/src/view/observer/focusobserver.js +22 -4
- package/src/view/observer/inputobserver.js +1 -1
- package/src/view/observer/keyobserver.js +1 -1
- package/src/view/observer/mouseobserver.js +1 -1
- package/src/view/observer/mutationobserver.js +1 -1
- package/src/view/observer/observer.js +1 -1
- package/src/view/observer/selectionobserver.js +13 -2
- package/src/view/observer/tabobserver.js +1 -1
- package/src/view/placeholder.js +1 -1
- package/src/view/position.js +1 -1
- package/src/view/range.js +1 -1
- package/src/view/rawelement.js +1 -1
- package/src/view/renderer.js +1 -14
- package/src/view/rooteditableelement.js +1 -1
- package/src/view/selection.js +1 -1
- package/src/view/styles/background.js +1 -1
- package/src/view/styles/border.js +1 -1
- package/src/view/styles/margin.js +1 -1
- package/src/view/styles/padding.js +1 -1
- package/src/view/styles/utils.js +1 -1
- package/src/view/stylesmap.js +1 -1
- package/src/view/text.js +1 -1
- package/src/view/textproxy.js +1 -1
- package/src/view/treewalker.js +1 -1
- package/src/view/typecheckable.js +1 -1
- package/src/view/uielement.js +1 -1
- package/src/view/upcastwriter.js +1 -1
- package/src/view/view.js +5 -5
- package/theme/placeholder.css +1 -1
- package/theme/renderer.css +1 -1
package/src/model/position.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2023, 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
|
/**
|
|
@@ -41,10 +41,9 @@ export default class Position extends TypeCheckable {
|
|
|
41
41
|
/**
|
|
42
42
|
* Creates a position.
|
|
43
43
|
*
|
|
44
|
-
* @param
|
|
45
|
-
* @param
|
|
46
|
-
* @param {module:engine/model/position~PositionStickiness}
|
|
47
|
-
* See {@link module:engine/model/position~PositionStickiness}.
|
|
44
|
+
* @param root Root of the position.
|
|
45
|
+
* @param path Position path. See {@link module:engine/model/position~Position#path}.
|
|
46
|
+
* @param stickiness Position stickiness. See {@link module:engine/model/position~PositionStickiness}.
|
|
48
47
|
*/
|
|
49
48
|
constructor(root, path, stickiness = 'toNone') {
|
|
50
49
|
super();
|
|
@@ -75,50 +74,8 @@ export default class Position extends TypeCheckable {
|
|
|
75
74
|
path = [...root.getPath(), ...path];
|
|
76
75
|
root = root.root;
|
|
77
76
|
}
|
|
78
|
-
/**
|
|
79
|
-
* Root of the position path.
|
|
80
|
-
*
|
|
81
|
-
* @readonly
|
|
82
|
-
* @member {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment}
|
|
83
|
-
* module:engine/model/position~Position#root
|
|
84
|
-
*/
|
|
85
77
|
this.root = root;
|
|
86
|
-
/**
|
|
87
|
-
* Position of the node in the tree. **Path contains offsets, not indexes.**
|
|
88
|
-
*
|
|
89
|
-
* Position can be placed before, after or in a {@link module:engine/model/node~Node node} if that node has
|
|
90
|
-
* {@link module:engine/model/node~Node#offsetSize} greater than `1`. Items in position path are
|
|
91
|
-
* {@link module:engine/model/node~Node#startOffset starting offsets} of position ancestors, starting from direct root children,
|
|
92
|
-
* down to the position offset in it's parent.
|
|
93
|
-
*
|
|
94
|
-
* ROOT
|
|
95
|
-
* |- P before: [ 0 ] after: [ 1 ]
|
|
96
|
-
* |- UL before: [ 1 ] after: [ 2 ]
|
|
97
|
-
* |- LI before: [ 1, 0 ] after: [ 1, 1 ]
|
|
98
|
-
* | |- foo before: [ 1, 0, 0 ] after: [ 1, 0, 3 ]
|
|
99
|
-
* |- LI before: [ 1, 1 ] after: [ 1, 2 ]
|
|
100
|
-
* |- bar before: [ 1, 1, 0 ] after: [ 1, 1, 3 ]
|
|
101
|
-
*
|
|
102
|
-
* `foo` and `bar` are representing {@link module:engine/model/text~Text text nodes}. Since text nodes has offset size
|
|
103
|
-
* greater than `1` you can place position offset between their start and end:
|
|
104
|
-
*
|
|
105
|
-
* ROOT
|
|
106
|
-
* |- P
|
|
107
|
-
* |- UL
|
|
108
|
-
* |- LI
|
|
109
|
-
* | |- f^o|o ^ has path: [ 1, 0, 1 ] | has path: [ 1, 0, 2 ]
|
|
110
|
-
* |- LI
|
|
111
|
-
* |- b^a|r ^ has path: [ 1, 1, 1 ] | has path: [ 1, 1, 2 ]
|
|
112
|
-
*
|
|
113
|
-
* @readonly
|
|
114
|
-
* @member {Array.<Number>} module:engine/model/position~Position#path
|
|
115
|
-
*/
|
|
116
78
|
this.path = path;
|
|
117
|
-
/**
|
|
118
|
-
* Position stickiness. See {@link module:engine/model/position~PositionStickiness}.
|
|
119
|
-
*
|
|
120
|
-
* @member {module:engine/model/position~PositionStickiness} module:engine/model/position~Position#stickiness
|
|
121
|
-
*/
|
|
122
79
|
this.stickiness = stickiness;
|
|
123
80
|
}
|
|
124
81
|
/**
|
|
@@ -141,9 +98,6 @@ export default class Position extends TypeCheckable {
|
|
|
141
98
|
* leads to a non-existing element, `parent` property will throw error.
|
|
142
99
|
*
|
|
143
100
|
* Also it is a good idea to cache `parent` property if it is used frequently in an algorithm (i.e. in a long loop).
|
|
144
|
-
*
|
|
145
|
-
* @readonly
|
|
146
|
-
* @type {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment}
|
|
147
101
|
*/
|
|
148
102
|
get parent() {
|
|
149
103
|
let parent = this.root;
|
|
@@ -163,7 +117,7 @@ export default class Position extends TypeCheckable {
|
|
|
163
117
|
* the {@glink framework/guides/architecture/editing-engine#indexes-and-offsets Editing engine architecture guide}.
|
|
164
118
|
*
|
|
165
119
|
* @error model-position-path-incorrect
|
|
166
|
-
* @param
|
|
120
|
+
* @param position The incorrect position.
|
|
167
121
|
*/
|
|
168
122
|
throw new CKEditorError('model-position-path-incorrect', this, { position: this });
|
|
169
123
|
}
|
|
@@ -177,9 +131,6 @@ export default class Position extends TypeCheckable {
|
|
|
177
131
|
* Position {@link module:engine/model/position~Position#offset offset} converted to an index in position's parent node. It is
|
|
178
132
|
* equal to the {@link module:engine/model/node~Node#index index} of a node after this position. If position is placed
|
|
179
133
|
* in text node, position index is equal to the index of that text node.
|
|
180
|
-
*
|
|
181
|
-
* @readonly
|
|
182
|
-
* @type {Number}
|
|
183
134
|
*/
|
|
184
135
|
get index() {
|
|
185
136
|
return this.parent.offsetToIndex(this.offset);
|
|
@@ -187,18 +138,12 @@ export default class Position extends TypeCheckable {
|
|
|
187
138
|
/**
|
|
188
139
|
* Returns {@link module:engine/model/text~Text text node} instance in which this position is placed or `null` if this
|
|
189
140
|
* position is not in a text node.
|
|
190
|
-
*
|
|
191
|
-
* @readonly
|
|
192
|
-
* @type {module:engine/model/text~Text|null}
|
|
193
141
|
*/
|
|
194
142
|
get textNode() {
|
|
195
143
|
return getTextNodeAtPosition(this, this.parent);
|
|
196
144
|
}
|
|
197
145
|
/**
|
|
198
146
|
* Node directly after this position or `null` if this position is in text node.
|
|
199
|
-
*
|
|
200
|
-
* @readonly
|
|
201
|
-
* @type {module:engine/model/node~Node|null}
|
|
202
147
|
*/
|
|
203
148
|
get nodeAfter() {
|
|
204
149
|
// Cache the parent and reuse for performance reasons. See #6579 and #6582.
|
|
@@ -207,9 +152,6 @@ export default class Position extends TypeCheckable {
|
|
|
207
152
|
}
|
|
208
153
|
/**
|
|
209
154
|
* Node directly before this position or `null` if this position is in text node.
|
|
210
|
-
*
|
|
211
|
-
* @readonly
|
|
212
|
-
* @type {module:engine/model/node~Node|null}
|
|
213
155
|
*/
|
|
214
156
|
get nodeBefore() {
|
|
215
157
|
// Cache the parent and reuse for performance reasons. See #6579 and #6582.
|
|
@@ -218,18 +160,12 @@ export default class Position extends TypeCheckable {
|
|
|
218
160
|
}
|
|
219
161
|
/**
|
|
220
162
|
* Is `true` if position is at the beginning of its {@link module:engine/model/position~Position#parent parent}, `false` otherwise.
|
|
221
|
-
*
|
|
222
|
-
* @readonly
|
|
223
|
-
* @type {Boolean}
|
|
224
163
|
*/
|
|
225
164
|
get isAtStart() {
|
|
226
165
|
return this.offset === 0;
|
|
227
166
|
}
|
|
228
167
|
/**
|
|
229
168
|
* Is `true` if position is at the end of its {@link module:engine/model/position~Position#parent parent}, `false` otherwise.
|
|
230
|
-
*
|
|
231
|
-
* @readonly
|
|
232
|
-
* @type {Boolean}
|
|
233
169
|
*/
|
|
234
170
|
get isAtEnd() {
|
|
235
171
|
return this.offset == this.parent.maxOffset;
|
|
@@ -238,9 +174,6 @@ export default class Position extends TypeCheckable {
|
|
|
238
174
|
* Checks whether this position is before or after given position.
|
|
239
175
|
*
|
|
240
176
|
* This method is safe to use it on non-existing positions (for example during operational transformation).
|
|
241
|
-
*
|
|
242
|
-
* @param {module:engine/model/position~Position} otherPosition Position to compare with.
|
|
243
|
-
* @returns {module:engine/model/position~PositionRelation}
|
|
244
177
|
*/
|
|
245
178
|
compareWith(otherPosition) {
|
|
246
179
|
if (this.root != otherPosition.root) {
|
|
@@ -264,20 +197,22 @@ export default class Position extends TypeCheckable {
|
|
|
264
197
|
*
|
|
265
198
|
* For example:
|
|
266
199
|
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
200
|
+
* ```ts
|
|
201
|
+
* getLastMatchingPosition( value => value.type == 'text' );
|
|
202
|
+
* // <paragraph>[]foo</paragraph> -> <paragraph>foo[]</paragraph>
|
|
269
203
|
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
204
|
+
* getLastMatchingPosition( value => value.type == 'text', { direction: 'backward' } );
|
|
205
|
+
* // <paragraph>foo[]</paragraph> -> <paragraph>[]foo</paragraph>
|
|
272
206
|
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
207
|
+
* getLastMatchingPosition( value => false );
|
|
208
|
+
* // Do not move the position.
|
|
209
|
+
* ```
|
|
275
210
|
*
|
|
276
|
-
* @param
|
|
211
|
+
* @param skip Callback function. Gets {@link module:engine/model/treewalker~TreeWalkerValue} and should
|
|
277
212
|
* return `true` if the value should be skipped or `false` if not.
|
|
278
|
-
* @param
|
|
213
|
+
* @param options Object with configuration options. See {@link module:engine/model/treewalker~TreeWalker}.
|
|
279
214
|
*
|
|
280
|
-
* @returns
|
|
215
|
+
* @returns The position after the last item which matches the `skip` callback test.
|
|
281
216
|
*/
|
|
282
217
|
getLastMatchingPosition(skip, options = {}) {
|
|
283
218
|
options.startPosition = this;
|
|
@@ -291,7 +226,7 @@ export default class Position extends TypeCheckable {
|
|
|
291
226
|
*
|
|
292
227
|
* This method is safe to use it on non-existing positions (for example during operational transformation).
|
|
293
228
|
*
|
|
294
|
-
* @returns
|
|
229
|
+
* @returns Path to the parent.
|
|
295
230
|
*/
|
|
296
231
|
getParentPath() {
|
|
297
232
|
return this.path.slice(0, -1);
|
|
@@ -299,7 +234,7 @@ export default class Position extends TypeCheckable {
|
|
|
299
234
|
/**
|
|
300
235
|
* Returns ancestors array of this position, that is this position's parent and its ancestors.
|
|
301
236
|
*
|
|
302
|
-
* @returns
|
|
237
|
+
* @returns Array with ancestors.
|
|
303
238
|
*/
|
|
304
239
|
getAncestors() {
|
|
305
240
|
const parent = this.parent;
|
|
@@ -313,8 +248,7 @@ export default class Position extends TypeCheckable {
|
|
|
313
248
|
/**
|
|
314
249
|
* Returns the parent element of the given name. Returns null if the position is not inside the desired parent.
|
|
315
250
|
*
|
|
316
|
-
* @param
|
|
317
|
-
* @returns {module:engine/model/element~Element|null}
|
|
251
|
+
* @param parentName The name of the parent element to find.
|
|
318
252
|
*/
|
|
319
253
|
findAncestor(parentName) {
|
|
320
254
|
const parent = this.parent;
|
|
@@ -329,8 +263,8 @@ export default class Position extends TypeCheckable {
|
|
|
329
263
|
*
|
|
330
264
|
* This method is safe to use it on non-existing positions (for example during operational transformation).
|
|
331
265
|
*
|
|
332
|
-
* @param
|
|
333
|
-
* @returns
|
|
266
|
+
* @param position The second position.
|
|
267
|
+
* @returns The common path.
|
|
334
268
|
*/
|
|
335
269
|
getCommonPath(position) {
|
|
336
270
|
if (this.root != position.root) {
|
|
@@ -346,8 +280,7 @@ export default class Position extends TypeCheckable {
|
|
|
346
280
|
* Returns an {@link module:engine/model/element~Element} or {@link module:engine/model/documentfragment~DocumentFragment}
|
|
347
281
|
* which is a common ancestor of both positions. The {@link #root roots} of these two positions must be identical.
|
|
348
282
|
*
|
|
349
|
-
* @param
|
|
350
|
-
* @returns {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment|null}
|
|
283
|
+
* @param position The second position.
|
|
351
284
|
*/
|
|
352
285
|
getCommonAncestor(position) {
|
|
353
286
|
const ancestorsA = this.getAncestors();
|
|
@@ -364,8 +297,8 @@ export default class Position extends TypeCheckable {
|
|
|
364
297
|
*
|
|
365
298
|
* This method is safe to use it on non-existing positions (for example during operational transformation).
|
|
366
299
|
*
|
|
367
|
-
* @param
|
|
368
|
-
* @returns
|
|
300
|
+
* @param shift Offset shift. Can be a negative value.
|
|
301
|
+
* @returns Shifted position.
|
|
369
302
|
*/
|
|
370
303
|
getShiftedBy(shift) {
|
|
371
304
|
const shifted = this.clone();
|
|
@@ -379,8 +312,8 @@ export default class Position extends TypeCheckable {
|
|
|
379
312
|
* This method is safe to use it on non-existing positions (for example during operational transformation).
|
|
380
313
|
*
|
|
381
314
|
* @see module:engine/model/position~Position#isBefore
|
|
382
|
-
* @param
|
|
383
|
-
* @returns
|
|
315
|
+
* @param otherPosition Position to compare with.
|
|
316
|
+
* @returns True if this position is after given position.
|
|
384
317
|
*/
|
|
385
318
|
isAfter(otherPosition) {
|
|
386
319
|
return this.compareWith(otherPosition) == 'after';
|
|
@@ -393,30 +326,36 @@ export default class Position extends TypeCheckable {
|
|
|
393
326
|
* `a.isAfter( b ) || a.isEqual( b )` or `!a.isBefore( p ) && a.root == b.root` in most scenarios. If your
|
|
394
327
|
* condition uses multiple `isAfter` and `isBefore` checks, build them so they do not use negated values, i.e.:
|
|
395
328
|
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
329
|
+
* ```ts
|
|
330
|
+
* if ( a.isBefore( b ) && c.isAfter( d ) ) {
|
|
331
|
+
* // do A.
|
|
332
|
+
* } else {
|
|
333
|
+
* // do B.
|
|
334
|
+
* }
|
|
335
|
+
* ```
|
|
401
336
|
*
|
|
402
337
|
* or, if you have only one if-branch:
|
|
403
338
|
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
406
|
-
*
|
|
339
|
+
* ```ts
|
|
340
|
+
* if ( !( a.isBefore( b ) && c.isAfter( d ) ) {
|
|
341
|
+
* // do B.
|
|
342
|
+
* }
|
|
343
|
+
* ```
|
|
407
344
|
*
|
|
408
345
|
* rather than:
|
|
409
346
|
*
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
*
|
|
347
|
+
* ```ts
|
|
348
|
+
* if ( !a.isBefore( b ) || && !c.isAfter( d ) ) {
|
|
349
|
+
* // do B.
|
|
350
|
+
* } else {
|
|
351
|
+
* // do A.
|
|
352
|
+
* }
|
|
353
|
+
* ```
|
|
415
354
|
*
|
|
416
355
|
* This method is safe to use it on non-existing positions (for example during operational transformation).
|
|
417
356
|
*
|
|
418
|
-
* @param
|
|
419
|
-
* @returns
|
|
357
|
+
* @param otherPosition Position to compare with.
|
|
358
|
+
* @returns True if this position is before given position.
|
|
420
359
|
*/
|
|
421
360
|
isBefore(otherPosition) {
|
|
422
361
|
return this.compareWith(otherPosition) == 'before';
|
|
@@ -426,8 +365,8 @@ export default class Position extends TypeCheckable {
|
|
|
426
365
|
*
|
|
427
366
|
* This method is safe to use it on non-existing positions (for example during operational transformation).
|
|
428
367
|
*
|
|
429
|
-
* @param
|
|
430
|
-
* @returns
|
|
368
|
+
* @param otherPosition Position to compare with.
|
|
369
|
+
* @returns True if positions are same.
|
|
431
370
|
*/
|
|
432
371
|
isEqual(otherPosition) {
|
|
433
372
|
return this.compareWith(otherPosition) == 'same';
|
|
@@ -437,8 +376,8 @@ export default class Position extends TypeCheckable {
|
|
|
437
376
|
* or empty nodes in a range between them. Technically, those positions are not equal but in many cases
|
|
438
377
|
* they are very similar or even indistinguishable.
|
|
439
378
|
*
|
|
440
|
-
* @param
|
|
441
|
-
* @returns
|
|
379
|
+
* @param otherPosition Position to compare with.
|
|
380
|
+
* @returns True if positions touch.
|
|
442
381
|
*/
|
|
443
382
|
isTouching(otherPosition) {
|
|
444
383
|
if (this.root !== otherPosition.root) {
|
|
@@ -487,8 +426,8 @@ export default class Position extends TypeCheckable {
|
|
|
487
426
|
*
|
|
488
427
|
* This method is safe to use it on non-existing positions (for example during operational transformation).
|
|
489
428
|
*
|
|
490
|
-
* @param
|
|
491
|
-
* @returns
|
|
429
|
+
* @param position Position to compare with.
|
|
430
|
+
* @returns `true` if positions have the same parent, `false` otherwise.
|
|
492
431
|
*/
|
|
493
432
|
hasSameParentAs(position) {
|
|
494
433
|
if (this.root !== position.root) {
|
|
@@ -508,8 +447,8 @@ export default class Position extends TypeCheckable {
|
|
|
508
447
|
*
|
|
509
448
|
* This method is safe to use it on non-existing positions (for example during operational transformation).
|
|
510
449
|
*
|
|
511
|
-
* @param
|
|
512
|
-
* @returns
|
|
450
|
+
* @param operation Operation to transform by.
|
|
451
|
+
* @returns Transformed position.
|
|
513
452
|
*/
|
|
514
453
|
getTransformedByOperation(operation) {
|
|
515
454
|
let result;
|
|
@@ -538,9 +477,6 @@ export default class Position extends TypeCheckable {
|
|
|
538
477
|
* Returns a copy of this position transformed by an insert operation.
|
|
539
478
|
*
|
|
540
479
|
* @internal
|
|
541
|
-
* @protected
|
|
542
|
-
* @param {module:engine/model/operation/insertoperation~InsertOperation} operation
|
|
543
|
-
* @returns {module:engine/model/position~Position}
|
|
544
480
|
*/
|
|
545
481
|
_getTransformedByInsertOperation(operation) {
|
|
546
482
|
return this._getTransformedByInsertion(operation.position, operation.howMany);
|
|
@@ -549,9 +485,6 @@ export default class Position extends TypeCheckable {
|
|
|
549
485
|
* Returns a copy of this position transformed by a move operation.
|
|
550
486
|
*
|
|
551
487
|
* @internal
|
|
552
|
-
* @protected
|
|
553
|
-
* @param {module:engine/model/operation/moveoperation~MoveOperation} operation
|
|
554
|
-
* @returns {module:engine/model/position~Position}
|
|
555
488
|
*/
|
|
556
489
|
_getTransformedByMoveOperation(operation) {
|
|
557
490
|
return this._getTransformedByMove(operation.sourcePosition, operation.targetPosition, operation.howMany);
|
|
@@ -560,9 +493,6 @@ export default class Position extends TypeCheckable {
|
|
|
560
493
|
* Returns a copy of this position transformed by a split operation.
|
|
561
494
|
*
|
|
562
495
|
* @internal
|
|
563
|
-
* @protected
|
|
564
|
-
* @param {module:engine/model/operation/splitoperation~SplitOperation} operation
|
|
565
|
-
* @returns {module:engine/model/position~Position}
|
|
566
496
|
*/
|
|
567
497
|
_getTransformedBySplitOperation(operation) {
|
|
568
498
|
const movedRange = operation.movedRange;
|
|
@@ -584,9 +514,6 @@ export default class Position extends TypeCheckable {
|
|
|
584
514
|
* Returns a copy of this position transformed by merge operation.
|
|
585
515
|
*
|
|
586
516
|
* @internal
|
|
587
|
-
* @protected
|
|
588
|
-
* @param {module:engine/model/operation/mergeoperation~MergeOperation} operation
|
|
589
|
-
* @returns {module:engine/model/position~Position}
|
|
590
517
|
*/
|
|
591
518
|
_getTransformedByMergeOperation(operation) {
|
|
592
519
|
const movedRange = operation.movedRange;
|
|
@@ -612,10 +539,9 @@ export default class Position extends TypeCheckable {
|
|
|
612
539
|
* It may happen that this position is in a removed node. If that is the case, `null` is returned instead.
|
|
613
540
|
*
|
|
614
541
|
* @internal
|
|
615
|
-
* @
|
|
616
|
-
* @param
|
|
617
|
-
* @
|
|
618
|
-
* @returns {module:engine/model/position~Position|null} Transformed position or `null`.
|
|
542
|
+
* @param deletePosition Position before the first removed node.
|
|
543
|
+
* @param howMany How many nodes are removed.
|
|
544
|
+
* @returns Transformed position or `null`.
|
|
619
545
|
*/
|
|
620
546
|
_getTransformedByDeletion(deletePosition, howMany) {
|
|
621
547
|
const transformed = Position._createAt(this);
|
|
@@ -659,10 +585,9 @@ export default class Position extends TypeCheckable {
|
|
|
659
585
|
* Returns a copy of this position that is updated by inserting `howMany` nodes at `insertPosition`.
|
|
660
586
|
*
|
|
661
587
|
* @internal
|
|
662
|
-
* @
|
|
663
|
-
* @param
|
|
664
|
-
* @
|
|
665
|
-
* @returns {module:engine/model/position~Position} Transformed position.
|
|
588
|
+
* @param insertPosition Position where nodes are inserted.
|
|
589
|
+
* @param howMany How many nodes are inserted.
|
|
590
|
+
* @returns Transformed position.
|
|
666
591
|
*/
|
|
667
592
|
_getTransformedByInsertion(insertPosition, howMany) {
|
|
668
593
|
const transformed = Position._createAt(this);
|
|
@@ -693,11 +618,10 @@ export default class Position extends TypeCheckable {
|
|
|
693
618
|
* Returns a copy of this position that is updated by moving `howMany` nodes from `sourcePosition` to `targetPosition`.
|
|
694
619
|
*
|
|
695
620
|
* @internal
|
|
696
|
-
* @
|
|
697
|
-
* @param
|
|
698
|
-
* @param
|
|
699
|
-
* @
|
|
700
|
-
* @returns {module:engine/model/position~Position} Transformed position.
|
|
621
|
+
* @param sourcePosition Position before the first element to move.
|
|
622
|
+
* @param targetPosition Position where moved elements will be inserted.
|
|
623
|
+
* @param howMany How many consecutive nodes to move, starting from `sourcePosition`.
|
|
624
|
+
* @returns Transformed position.
|
|
701
625
|
*/
|
|
702
626
|
_getTransformedByMove(sourcePosition, targetPosition, howMany) {
|
|
703
627
|
// Update target position, as it could be affected by nodes removal.
|
|
@@ -731,10 +655,12 @@ export default class Position extends TypeCheckable {
|
|
|
731
655
|
*
|
|
732
656
|
* Example:
|
|
733
657
|
*
|
|
734
|
-
*
|
|
735
|
-
*
|
|
736
|
-
*
|
|
737
|
-
*
|
|
658
|
+
* ```ts
|
|
659
|
+
* let original = model.createPositionFromPath( root, [ 2, 3, 1 ] );
|
|
660
|
+
* let source = model.createPositionFromPath( root, [ 2, 2 ] );
|
|
661
|
+
* let target = model.createPositionFromPath( otherRoot, [ 1, 1, 3 ] );
|
|
662
|
+
* original._getCombined( source, target ); // path is [ 1, 1, 4, 1 ], root is `otherRoot`
|
|
663
|
+
* ```
|
|
738
664
|
*
|
|
739
665
|
* Explanation:
|
|
740
666
|
*
|
|
@@ -746,10 +672,9 @@ export default class Position extends TypeCheckable {
|
|
|
746
672
|
* Finally, the transformed position will point to `[ 1, 1, 4, 1 ]`.
|
|
747
673
|
*
|
|
748
674
|
* @internal
|
|
749
|
-
* @
|
|
750
|
-
* @param
|
|
751
|
-
* @
|
|
752
|
-
* @returns {module:engine/model/position~Position} Combined position.
|
|
675
|
+
* @param source Beginning of the moved range.
|
|
676
|
+
* @param target Position where the range is moved.
|
|
677
|
+
* @returns Combined position.
|
|
753
678
|
*/
|
|
754
679
|
_getCombined(source, target) {
|
|
755
680
|
const i = source.path.length - 1;
|
|
@@ -776,8 +701,6 @@ export default class Position extends TypeCheckable {
|
|
|
776
701
|
}
|
|
777
702
|
/**
|
|
778
703
|
* Returns a new position that is equal to current position.
|
|
779
|
-
*
|
|
780
|
-
* @returns {module:engine/model/position~Position}
|
|
781
704
|
*/
|
|
782
705
|
clone() {
|
|
783
706
|
return new this.constructor(this.root, this.path, this.stickiness);
|
|
@@ -795,13 +718,9 @@ export default class Position extends TypeCheckable {
|
|
|
795
718
|
* * {@link module:engine/model/position~Position._createBefore},
|
|
796
719
|
* * {@link module:engine/model/position~Position._createAfter}.
|
|
797
720
|
*
|
|
798
|
-
* @param {module:engine/model/item~Item|module:engine/model/position~Position} itemOrPosition
|
|
799
|
-
* @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when the
|
|
800
|
-
* first parameter is a {@link module:engine/model/item~Item model item}.
|
|
801
|
-
* @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness. Used only when the
|
|
802
|
-
* first parameter is a {@link module:engine/model/item~Item model item}.
|
|
803
|
-
* @protected
|
|
804
721
|
* @internal
|
|
722
|
+
* @param offset Offset or one of the flags. Used only when the first parameter is a {@link module:engine/model/item~Item model item}.
|
|
723
|
+
* @param stickiness Position stickiness. Used only when the first parameter is a {@link module:engine/model/item~Item model item}.
|
|
805
724
|
*/
|
|
806
725
|
static _createAt(itemOrPosition, offset, stickiness = 'toNone') {
|
|
807
726
|
if (itemOrPosition instanceof Position) {
|
|
@@ -843,11 +762,9 @@ export default class Position extends TypeCheckable {
|
|
|
843
762
|
/**
|
|
844
763
|
* Creates a new position, after given {@link module:engine/model/item~Item model item}.
|
|
845
764
|
*
|
|
846
|
-
* @param {module:engine/model/item~Item} item Item after which the position should be placed.
|
|
847
|
-
* @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness.
|
|
848
|
-
* @returns {module:engine/model/position~Position}
|
|
849
|
-
* @protected
|
|
850
765
|
* @internal
|
|
766
|
+
* @param item Item after which the position should be placed.
|
|
767
|
+
* @param stickiness Position stickiness.
|
|
851
768
|
*/
|
|
852
769
|
static _createAfter(item, stickiness) {
|
|
853
770
|
if (!item.parent) {
|
|
@@ -855,7 +772,7 @@ export default class Position extends TypeCheckable {
|
|
|
855
772
|
* You can not make a position after a root element.
|
|
856
773
|
*
|
|
857
774
|
* @error model-position-after-root
|
|
858
|
-
* @param
|
|
775
|
+
* @param root
|
|
859
776
|
*/
|
|
860
777
|
throw new CKEditorError('model-position-after-root', [this, item], { root: item });
|
|
861
778
|
}
|
|
@@ -864,11 +781,9 @@ export default class Position extends TypeCheckable {
|
|
|
864
781
|
/**
|
|
865
782
|
* Creates a new position, before the given {@link module:engine/model/item~Item model item}.
|
|
866
783
|
*
|
|
867
|
-
* @param {module:engine/model/item~Item} item Item before which the position should be placed.
|
|
868
|
-
* @param {module:engine/model/position~PositionStickiness} [stickiness='toNone'] Position stickiness.
|
|
869
|
-
* @returns {module:engine/model/position~Position}
|
|
870
|
-
* @protected
|
|
871
784
|
* @internal
|
|
785
|
+
* @param item Item before which the position should be placed.
|
|
786
|
+
* @param stickiness Position stickiness.
|
|
872
787
|
*/
|
|
873
788
|
static _createBefore(item, stickiness) {
|
|
874
789
|
if (!item.parent) {
|
|
@@ -876,7 +791,7 @@ export default class Position extends TypeCheckable {
|
|
|
876
791
|
* You can not make a position before a root element.
|
|
877
792
|
*
|
|
878
793
|
* @error model-position-before-root
|
|
879
|
-
* @param
|
|
794
|
+
* @param root
|
|
880
795
|
*/
|
|
881
796
|
throw new CKEditorError('model-position-before-root', item, { root: item });
|
|
882
797
|
}
|
|
@@ -885,9 +800,9 @@ export default class Position extends TypeCheckable {
|
|
|
885
800
|
/**
|
|
886
801
|
* Creates a `Position` instance from given plain object (i.e. parsed JSON string).
|
|
887
802
|
*
|
|
888
|
-
* @param
|
|
889
|
-
* @param
|
|
890
|
-
* @returns
|
|
803
|
+
* @param json Plain object to be converted to `Position`.
|
|
804
|
+
* @param doc Document object that will be position owner.
|
|
805
|
+
* @returns `Position` instance created using given plain object.
|
|
891
806
|
*/
|
|
892
807
|
static fromJSON(json, doc) {
|
|
893
808
|
if (json.root === '$graveyard') {
|
|
@@ -900,27 +815,15 @@ export default class Position extends TypeCheckable {
|
|
|
900
815
|
* Cannot create position for document. Root with specified name does not exist.
|
|
901
816
|
*
|
|
902
817
|
* @error model-position-fromjson-no-root
|
|
903
|
-
* @param
|
|
818
|
+
* @param rootName
|
|
904
819
|
*/
|
|
905
820
|
throw new CKEditorError('model-position-fromjson-no-root', doc, { rootName: json.root });
|
|
906
821
|
}
|
|
907
822
|
return new Position(doc.getRoot(json.root), json.path, json.stickiness);
|
|
908
823
|
}
|
|
909
824
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
*
|
|
913
|
-
* position.is( 'position' ); // -> true
|
|
914
|
-
* position.is( 'model:position' ); // -> true
|
|
915
|
-
*
|
|
916
|
-
* position.is( 'view:position' ); // -> false
|
|
917
|
-
* position.is( 'documentSelection' ); // -> false
|
|
918
|
-
*
|
|
919
|
-
* {@link module:engine/model/node~Node#is Check the entire list of model objects} which implement the `is()` method.
|
|
920
|
-
*
|
|
921
|
-
* @param {String} type
|
|
922
|
-
* @returns {Boolean}
|
|
923
|
-
*/
|
|
825
|
+
// The magic of type inference using `is` method is centralized in `TypeCheckable` class.
|
|
826
|
+
// Proper overload would interfere with that.
|
|
924
827
|
Position.prototype.is = function (type) {
|
|
925
828
|
return type === 'position' || type === 'model:position';
|
|
926
829
|
};
|
|
@@ -940,10 +843,7 @@ Position.prototype.is = function (type) {
|
|
|
940
843
|
* * {@link module:engine/model/position~getNodeAfterPosition}
|
|
941
844
|
* * {@link module:engine/model/position~getNodeBeforePosition}
|
|
942
845
|
*
|
|
943
|
-
* @param
|
|
944
|
-
* @param {module:engine/model/element~Element|module:engine/model/documentfragment~DocumentFragment} positionParent The parent of the
|
|
945
|
-
* given position.
|
|
946
|
-
* @returns {module:engine/model/text~Text|null}
|
|
846
|
+
* @param positionParent The parent of the given position.
|
|
947
847
|
*/
|
|
948
848
|
export function getTextNodeAtPosition(position, positionParent) {
|
|
949
849
|
const node = positionParent.getChild(positionParent.offsetToIndex(position.offset));
|
|
@@ -971,11 +871,8 @@ export function getTextNodeAtPosition(position, positionParent) {
|
|
|
971
871
|
* * {@link module:engine/model/position~getTextNodeAtPosition}
|
|
972
872
|
* * {@link module:engine/model/position~getNodeBeforePosition}
|
|
973
873
|
*
|
|
974
|
-
* @param
|
|
975
|
-
* @param
|
|
976
|
-
* given position.
|
|
977
|
-
* @param {module:engine/model/text~Text|null} textNode Text node at the given position.
|
|
978
|
-
* @returns {module:engine/model/node~Node|null}
|
|
874
|
+
* @param positionParent The parent of the given position.
|
|
875
|
+
* @param textNode Text node at the given position.
|
|
979
876
|
*/
|
|
980
877
|
export function getNodeAfterPosition(position, positionParent, textNode) {
|
|
981
878
|
if (textNode !== null) {
|
|
@@ -993,11 +890,8 @@ export function getNodeAfterPosition(position, positionParent, textNode) {
|
|
|
993
890
|
* * {@link module:engine/model/position~getTextNodeAtPosition}
|
|
994
891
|
* * {@link module:engine/model/position~getNodeAfterPosition}
|
|
995
892
|
*
|
|
996
|
-
* @param
|
|
997
|
-
* @param
|
|
998
|
-
* given position.
|
|
999
|
-
* @param {module:engine/model/text~Text|null} textNode Text node at the given position.
|
|
1000
|
-
* @returns {module:engine/model/node~Node|null}
|
|
893
|
+
* @param positionParent The parent of the given position.
|
|
894
|
+
* @param textNode Text node at the given position.
|
|
1001
895
|
*/
|
|
1002
896
|
export function getNodeBeforePosition(position, positionParent, textNode) {
|
|
1003
897
|
if (textNode !== null) {
|
|
@@ -1005,18 +899,19 @@ export function getNodeBeforePosition(position, positionParent, textNode) {
|
|
|
1005
899
|
}
|
|
1006
900
|
return positionParent.getChild(positionParent.offsetToIndex(position.offset) - 1);
|
|
1007
901
|
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
902
|
+
/**
|
|
903
|
+
* This is a helper function for `Position#isTouching()`.
|
|
904
|
+
*
|
|
905
|
+
* It checks whether to given positions are touching, considering that they have the same root and paths
|
|
906
|
+
* until given level, and at given level they differ by 1 (so they are branching at `level` point).
|
|
907
|
+
*
|
|
908
|
+
* The exact requirements for touching positions are described in `Position#isTouching()` and also
|
|
909
|
+
* in the body of this function.
|
|
910
|
+
*
|
|
911
|
+
* @param left Position "on the left" (it is before `right`).
|
|
912
|
+
* @param right Position "on the right" (it is after `left`).
|
|
913
|
+
* @param level Level on which the positions are different.
|
|
914
|
+
*/
|
|
1020
915
|
function checkTouchingBranch(left, right, level) {
|
|
1021
916
|
if (level + 1 === left.path.length) {
|
|
1022
917
|
// Left position does not have any more entries after the point where the positions differ.
|
|
@@ -1045,14 +940,11 @@ function checkTouchingBranch(left, right, level) {
|
|
|
1045
940
|
// There are not elements between positions. The positions are touching.
|
|
1046
941
|
return true;
|
|
1047
942
|
}
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
// @param {Array.<Number>} arr Array to check.
|
|
1054
|
-
// @param {Number} idx Index to start checking from.
|
|
1055
|
-
// @returns {Boolean}
|
|
943
|
+
/**
|
|
944
|
+
* Checks whether for given array, starting from given index until the end of the array, all items are `0`s.
|
|
945
|
+
*
|
|
946
|
+
* This is a helper function for `Position#isTouching()`.
|
|
947
|
+
*/
|
|
1056
948
|
function checkOnlyZeroes(arr, idx) {
|
|
1057
949
|
while (idx < arr.length) {
|
|
1058
950
|
if (arr[idx] !== 0) {
|
|
@@ -1062,15 +954,12 @@ function checkOnlyZeroes(arr, idx) {
|
|
|
1062
954
|
}
|
|
1063
955
|
return true;
|
|
1064
956
|
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
// @param {module:engine/model/position~Position} pos Position to check.
|
|
1072
|
-
// @param {Number} level Level to start checking from.
|
|
1073
|
-
// @returns {Boolean}
|
|
957
|
+
/**
|
|
958
|
+
* Checks whether for given position, starting from given path level, whether the position is at the end of
|
|
959
|
+
* its parent and whether each element on the path to the position is also at at the end of its parent.
|
|
960
|
+
*
|
|
961
|
+
* This is a helper function for `Position#isTouching()`.
|
|
962
|
+
*/
|
|
1074
963
|
function checkOnlyMaxOffset(pos, level) {
|
|
1075
964
|
let parent = pos.parent;
|
|
1076
965
|
let idx = pos.path.length - 1;
|