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