@ckeditor/ckeditor5-engine 45.2.1-alpha.9 → 46.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2563 -2257
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/controller/datacontroller.d.ts +33 -32
- package/src/controller/datacontroller.js +29 -28
- package/src/controller/editingcontroller.d.ts +8 -8
- package/src/controller/editingcontroller.js +10 -10
- package/src/conversion/conversion.d.ts +18 -19
- package/src/conversion/conversion.js +4 -4
- package/src/conversion/conversionhelpers.d.ts +1 -1
- package/src/conversion/conversionhelpers.js +1 -1
- package/src/conversion/downcastdispatcher.d.ts +63 -69
- package/src/conversion/downcastdispatcher.js +16 -16
- package/src/conversion/downcasthelpers.d.ts +94 -83
- package/src/conversion/downcasthelpers.js +63 -53
- package/src/conversion/mapper.d.ts +27 -27
- package/src/conversion/mapper.js +15 -15
- package/src/conversion/modelconsumable.d.ts +26 -26
- package/src/conversion/modelconsumable.js +23 -23
- package/src/conversion/upcastdispatcher.d.ts +33 -32
- package/src/conversion/upcastdispatcher.js +19 -19
- package/src/conversion/upcasthelpers.d.ts +46 -38
- package/src/conversion/upcasthelpers.js +33 -24
- package/src/conversion/viewconsumable.d.ts +50 -45
- package/src/conversion/viewconsumable.js +32 -27
- package/src/dataprocessor/basichtmlwriter.d.ts +4 -2
- package/src/dataprocessor/basichtmlwriter.js +3 -1
- package/src/dataprocessor/dataprocessor.d.ts +7 -6
- package/src/dataprocessor/htmldataprocessor.d.ts +10 -10
- package/src/dataprocessor/htmldataprocessor.js +6 -6
- package/src/dataprocessor/htmlwriter.d.ts +1 -1
- package/src/dataprocessor/xmldataprocessor.d.ts +10 -10
- package/src/dataprocessor/xmldataprocessor.js +6 -6
- package/src/dev-utils/model.d.ts +25 -26
- package/src/dev-utils/model.js +35 -36
- package/src/dev-utils/operationreplayer.d.ts +5 -3
- package/src/dev-utils/operationreplayer.js +4 -2
- package/src/dev-utils/utils.d.ts +8 -0
- package/src/dev-utils/utils.js +8 -0
- package/src/dev-utils/view.d.ts +66 -63
- package/src/dev-utils/view.js +144 -134
- package/src/index.d.ts +135 -106
- package/src/index.js +120 -71
- package/src/legacyerrors.d.ts +5 -0
- package/src/legacyerrors.js +17 -0
- package/src/model/batch.d.ts +2 -15
- package/src/model/batch.js +1 -23
- package/src/model/differ.d.ts +54 -31
- package/src/model/differ.js +15 -15
- package/src/model/document.d.ts +31 -31
- package/src/model/document.js +13 -13
- package/src/model/documentfragment.d.ts +45 -45
- package/src/model/documentfragment.js +40 -40
- package/src/model/documentselection.d.ts +92 -92
- package/src/model/documentselection.js +71 -70
- package/src/model/element.d.ts +31 -31
- package/src/model/element.js +29 -29
- package/src/model/history.d.ts +3 -3
- package/src/model/history.js +2 -2
- package/src/model/item.d.ts +4 -5
- package/src/model/liveposition.d.ts +31 -31
- package/src/model/liveposition.js +18 -18
- package/src/model/liverange.d.ts +42 -38
- package/src/model/liverange.js +17 -16
- package/src/model/markercollection.d.ts +41 -40
- package/src/model/markercollection.js +22 -20
- package/src/model/model.d.ts +82 -81
- package/src/model/model.js +54 -54
- package/src/model/node.d.ts +48 -48
- package/src/model/node.js +31 -31
- package/src/model/nodelist.d.ts +17 -17
- package/src/model/nodelist.js +11 -11
- package/src/model/operation/attributeoperation.d.ts +10 -10
- package/src/model/operation/attributeoperation.js +7 -7
- package/src/model/operation/detachoperation.d.ts +11 -9
- package/src/model/operation/detachoperation.js +8 -6
- package/src/model/operation/insertoperation.d.ts +13 -13
- package/src/model/operation/insertoperation.js +15 -15
- package/src/model/operation/markeroperation.d.ts +12 -12
- package/src/model/operation/markeroperation.js +5 -5
- package/src/model/operation/mergeoperation.d.ts +16 -16
- package/src/model/operation/mergeoperation.js +18 -18
- package/src/model/operation/moveoperation.d.ts +16 -16
- package/src/model/operation/moveoperation.js +18 -15
- package/src/model/operation/nooperation.d.ts +4 -4
- package/src/model/operation/nooperation.js +2 -2
- package/src/model/operation/operation.d.ts +10 -10
- package/src/model/operation/operation.js +5 -5
- package/src/model/operation/operationfactory.d.ts +4 -4
- package/src/model/operation/operationfactory.js +12 -12
- package/src/model/operation/renameoperation.d.ts +10 -10
- package/src/model/operation/renameoperation.js +7 -7
- package/src/model/operation/rootattributeoperation.d.ts +12 -12
- package/src/model/operation/rootattributeoperation.js +8 -8
- package/src/model/operation/rootoperation.d.ts +8 -8
- package/src/model/operation/rootoperation.js +3 -3
- package/src/model/operation/splitoperation.d.ts +17 -17
- package/src/model/operation/splitoperation.js +19 -19
- package/src/model/operation/transform.d.ts +11 -8
- package/src/model/operation/transform.js +66 -49
- package/src/model/operation/utils.d.ts +24 -23
- package/src/model/operation/utils.js +20 -20
- package/src/model/position.d.ts +101 -97
- package/src/model/position.js +69 -64
- package/src/model/range.d.ts +90 -90
- package/src/model/range.js +87 -87
- package/src/model/rootelement.d.ts +11 -11
- package/src/model/rootelement.js +9 -9
- package/src/model/schema.d.ts +158 -154
- package/src/model/schema.js +93 -90
- package/src/model/selection.d.ts +73 -73
- package/src/model/selection.js +62 -62
- package/src/model/text.d.ts +11 -10
- package/src/model/text.js +11 -10
- package/src/model/textproxy.d.ts +39 -38
- package/src/model/textproxy.js +31 -30
- package/src/model/treewalker.d.ts +37 -37
- package/src/model/treewalker.js +14 -14
- package/src/model/typecheckable.d.ts +45 -45
- package/src/model/typecheckable.js +1 -1
- package/src/model/utils/autoparagraphing.d.ts +7 -7
- package/src/model/utils/deletecontent.d.ts +7 -5
- package/src/model/utils/deletecontent.js +13 -11
- package/src/model/utils/getselectedcontent.d.ts +6 -5
- package/src/model/utils/getselectedcontent.js +2 -1
- package/src/model/utils/insertcontent.d.ts +9 -8
- package/src/model/utils/insertcontent.js +41 -40
- package/src/model/utils/insertobject.d.ts +9 -9
- package/src/model/utils/insertobject.js +4 -4
- package/src/model/utils/modifyselection.d.ts +5 -4
- package/src/model/utils/modifyselection.js +12 -11
- package/src/model/utils/selection-post-fixer.d.ts +12 -8
- package/src/model/utils/selection-post-fixer.js +15 -11
- package/src/model/writer.d.ts +102 -101
- package/src/model/writer.js +99 -98
- package/src/view/attributeelement.d.ts +29 -29
- package/src/view/attributeelement.js +25 -25
- package/src/view/containerelement.d.ts +16 -15
- package/src/view/containerelement.js +15 -14
- package/src/view/datatransfer.d.ts +7 -7
- package/src/view/datatransfer.js +1 -1
- package/src/view/document.d.ts +25 -25
- package/src/view/document.js +15 -15
- package/src/view/documentfragment.d.ts +21 -21
- package/src/view/documentfragment.js +14 -14
- package/src/view/documentselection.d.ts +65 -63
- package/src/view/documentselection.js +27 -25
- package/src/view/domconverter.d.ts +94 -89
- package/src/view/domconverter.js +78 -73
- package/src/view/downcastwriter.d.ts +185 -181
- package/src/view/downcastwriter.js +222 -210
- package/src/view/editableelement.d.ts +13 -13
- package/src/view/editableelement.js +8 -8
- package/src/view/element.d.ts +75 -74
- package/src/view/element.js +58 -58
- package/src/view/elementdefinition.d.ts +3 -4
- package/src/view/emptyelement.d.ts +13 -13
- package/src/view/emptyelement.js +13 -13
- package/src/view/filler.d.ts +14 -3
- package/src/view/filler.js +12 -1
- package/src/view/item.d.ts +4 -5
- package/src/view/matcher.d.ts +22 -19
- package/src/view/matcher.js +6 -6
- package/src/view/node.d.ts +33 -33
- package/src/view/node.js +9 -9
- package/src/view/observer/arrowkeysobserver.d.ts +10 -10
- package/src/view/observer/arrowkeysobserver.js +5 -5
- package/src/view/observer/bubblingemittermixin.d.ts +5 -5
- package/src/view/observer/bubblingemittermixin.js +2 -9
- package/src/view/observer/bubblingeventinfo.d.ts +9 -9
- package/src/view/observer/bubblingeventinfo.js +1 -1
- package/src/view/observer/clickobserver.d.ts +8 -8
- package/src/view/observer/clickobserver.js +4 -4
- package/src/view/observer/compositionobserver.d.ts +19 -19
- package/src/view/observer/compositionobserver.js +6 -6
- package/src/view/observer/domeventdata.d.ts +9 -9
- package/src/view/observer/domeventdata.js +2 -2
- package/src/view/observer/domeventobserver.d.ts +3 -3
- package/src/view/observer/domeventobserver.js +5 -5
- package/src/view/observer/fakeselectionobserver.d.ts +9 -9
- package/src/view/observer/fakeselectionobserver.js +8 -8
- package/src/view/observer/focusobserver.d.ts +16 -16
- package/src/view/observer/focusobserver.js +7 -7
- package/src/view/observer/inputobserver.d.ts +18 -18
- package/src/view/observer/inputobserver.js +5 -5
- package/src/view/observer/keyobserver.d.ts +11 -11
- package/src/view/observer/keyobserver.js +3 -3
- package/src/view/observer/mouseobserver.d.ts +16 -16
- package/src/view/observer/mouseobserver.js +3 -3
- package/src/view/observer/mutationobserver.d.ts +21 -21
- package/src/view/observer/mutationobserver.js +7 -7
- package/src/view/observer/observer.d.ts +12 -12
- package/src/view/observer/observer.js +6 -6
- package/src/view/observer/selectionobserver.d.ts +33 -33
- package/src/view/observer/selectionobserver.js +14 -14
- package/src/view/observer/tabobserver.d.ts +10 -10
- package/src/view/observer/tabobserver.js +5 -5
- package/src/view/observer/touchobserver.d.ts +13 -13
- package/src/view/observer/touchobserver.js +3 -3
- package/src/view/placeholder.d.ts +21 -21
- package/src/view/placeholder.js +23 -23
- package/src/view/position.d.ts +49 -49
- package/src/view/position.js +42 -42
- package/src/view/range.d.ts +76 -74
- package/src/view/range.js +67 -65
- package/src/view/rawelement.d.ts +19 -19
- package/src/view/rawelement.js +16 -16
- package/src/view/renderer.d.ts +14 -14
- package/src/view/renderer.js +7 -7
- package/src/view/rooteditableelement.d.ts +8 -7
- package/src/view/rooteditableelement.js +7 -6
- package/src/view/selection.d.ts +66 -64
- package/src/view/selection.js +50 -48
- package/src/view/styles/background.d.ts +2 -2
- package/src/view/styles/background.js +9 -9
- package/src/view/styles/border.d.ts +2 -2
- package/src/view/styles/border.js +13 -13
- package/src/view/styles/margin.d.ts +2 -2
- package/src/view/styles/margin.js +5 -5
- package/src/view/styles/padding.d.ts +2 -2
- package/src/view/styles/padding.js +5 -5
- package/src/view/styles/utils.d.ts +24 -24
- package/src/view/styles/utils.js +25 -25
- package/src/view/stylesmap.d.ts +28 -32
- package/src/view/stylesmap.js +52 -39
- package/src/view/text.d.ts +11 -11
- package/src/view/text.js +10 -10
- package/src/view/textproxy.d.ts +33 -32
- package/src/view/textproxy.js +23 -22
- package/src/view/tokenlist.d.ts +14 -14
- package/src/view/tokenlist.js +10 -10
- package/src/view/treewalker.d.ts +42 -40
- package/src/view/treewalker.js +36 -35
- package/src/view/typecheckable.d.ts +76 -75
- package/src/view/typecheckable.js +1 -1
- package/src/view/uielement.d.ts +22 -21
- package/src/view/uielement.js +17 -16
- package/src/view/upcastwriter.d.ts +70 -70
- package/src/view/upcastwriter.js +42 -42
- package/src/view/view.d.ts +70 -69
- package/src/view/view.js +56 -55
|
@@ -5,18 +5,18 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @module engine/model/operation/transform
|
|
7
7
|
*/
|
|
8
|
-
import InsertOperation from './insertoperation.js';
|
|
9
|
-
import AttributeOperation from './attributeoperation.js';
|
|
10
|
-
import RenameOperation from './renameoperation.js';
|
|
11
|
-
import MarkerOperation from './markeroperation.js';
|
|
12
|
-
import MoveOperation from './moveoperation.js';
|
|
13
|
-
import RootAttributeOperation from './rootattributeoperation.js';
|
|
14
|
-
import RootOperation from './rootoperation.js';
|
|
15
|
-
import MergeOperation from './mergeoperation.js';
|
|
16
|
-
import SplitOperation from './splitoperation.js';
|
|
17
|
-
import NoOperation from './nooperation.js';
|
|
18
|
-
import
|
|
19
|
-
import
|
|
8
|
+
import { InsertOperation } from './insertoperation.js';
|
|
9
|
+
import { AttributeOperation } from './attributeoperation.js';
|
|
10
|
+
import { RenameOperation } from './renameoperation.js';
|
|
11
|
+
import { MarkerOperation } from './markeroperation.js';
|
|
12
|
+
import { MoveOperation } from './moveoperation.js';
|
|
13
|
+
import { RootAttributeOperation } from './rootattributeoperation.js';
|
|
14
|
+
import { RootOperation } from './rootoperation.js';
|
|
15
|
+
import { MergeOperation } from './mergeoperation.js';
|
|
16
|
+
import { SplitOperation } from './splitoperation.js';
|
|
17
|
+
import { NoOperation } from './nooperation.js';
|
|
18
|
+
import { ModelRange } from '../range.js';
|
|
19
|
+
import { ModelPosition } from '../position.js';
|
|
20
20
|
import { compareArrays } from '@ckeditor/ckeditor5-utils';
|
|
21
21
|
const transformations = new Map();
|
|
22
22
|
/**
|
|
@@ -71,6 +71,7 @@ function noUpdateTransformation(a) {
|
|
|
71
71
|
* @param b Operation to transform by.
|
|
72
72
|
* @param context Transformation context for this transformation.
|
|
73
73
|
* @returns Transformation result.
|
|
74
|
+
* @internal
|
|
74
75
|
*/
|
|
75
76
|
export function transform(a, b, context = {}) {
|
|
76
77
|
const transformationFunction = getTransformation(a.constructor, b.constructor);
|
|
@@ -97,7 +98,7 @@ export function transform(a, b, context = {}) {
|
|
|
97
98
|
* both transformed `operationsA` and transformed `operationsB` are returned.
|
|
98
99
|
*
|
|
99
100
|
* Note, that the first operation in each set should base on the same document state (
|
|
100
|
-
* {@link module:engine/model/document~
|
|
101
|
+
* {@link module:engine/model/document~ModelDocument#version document version}).
|
|
101
102
|
*
|
|
102
103
|
* It is assumed that `operationsA` are "more important" during conflict resolution between two operations.
|
|
103
104
|
*
|
|
@@ -126,7 +127,7 @@ export function transform(a, b, context = {}) {
|
|
|
126
127
|
* so the removed nodes won't end up back in the document root. When set to `true`, context data will be used.
|
|
127
128
|
* @returns Transformation result.
|
|
128
129
|
*/
|
|
129
|
-
export function
|
|
130
|
+
export function transformOperationSets(operationsA, operationsB, options) {
|
|
130
131
|
// Create new arrays so the originally passed arguments are not changed.
|
|
131
132
|
// No need to clone operations, they are cloned as they are transformed.
|
|
132
133
|
operationsA = operationsA.slice();
|
|
@@ -420,6 +421,12 @@ class ContextFactory {
|
|
|
420
421
|
else if (opA.targetPosition.isAfter(opB.sourcePosition)) {
|
|
421
422
|
this._setRelation(opA, opB, 'moveTargetAfter');
|
|
422
423
|
}
|
|
424
|
+
else if (opA.howMany > 1 && opA.sourcePosition.isEqual(opB.deletionPosition)) {
|
|
425
|
+
this._setRelation(opA, opB, 'firstToMoveMerged');
|
|
426
|
+
}
|
|
427
|
+
else if (opA.howMany > 1 && opA.sourcePosition.getShiftedBy(opA.howMany - 1).isEqual(opB.deletionPosition)) {
|
|
428
|
+
this._setRelation(opA, opB, 'lastToMoveMerged');
|
|
429
|
+
}
|
|
423
430
|
}
|
|
424
431
|
else if (opB instanceof MoveOperation) {
|
|
425
432
|
if (opA.targetPosition.isEqual(opB.sourcePosition) || opA.targetPosition.isBefore(opB.sourcePosition)) {
|
|
@@ -441,7 +448,7 @@ class ContextFactory {
|
|
|
441
448
|
this._setRelation(opA, opB, 'splitBefore');
|
|
442
449
|
}
|
|
443
450
|
else {
|
|
444
|
-
const range =
|
|
451
|
+
const range = ModelRange._createFromPositionAndShift(opB.sourcePosition, opB.howMany);
|
|
445
452
|
if (opA.splitPosition.hasSameParentAs(opB.sourcePosition) && range.containsPosition(opA.splitPosition)) {
|
|
446
453
|
// TODO: Potential bug -- we are saving offset value directly and it is not later updated during OT.
|
|
447
454
|
// TODO: This may cause a bug it here was an non-undone operation that may have impacted this offset.
|
|
@@ -646,7 +653,7 @@ function handlePartialMarkerOperations(operations) {
|
|
|
646
653
|
}
|
|
647
654
|
for (const { op, ranges } of markerOps.values()) {
|
|
648
655
|
if (ranges.length) {
|
|
649
|
-
op.newRange =
|
|
656
|
+
op.newRange = ModelRange._createFromRanges(ranges);
|
|
650
657
|
}
|
|
651
658
|
else {
|
|
652
659
|
op.newRange = null;
|
|
@@ -769,7 +776,7 @@ function _getComplementaryAttributeOperations(insertOperation, key, newValue) {
|
|
|
769
776
|
if (insertValue == newValue) {
|
|
770
777
|
return null;
|
|
771
778
|
}
|
|
772
|
-
const range = new
|
|
779
|
+
const range = new ModelRange(insertOperation.position, insertOperation.position.getShiftedBy(insertOperation.howMany));
|
|
773
780
|
return new AttributeOperation(range, key, insertValue, newValue, 0);
|
|
774
781
|
}
|
|
775
782
|
setTransformation(AttributeOperation, MergeOperation, (a, b) => {
|
|
@@ -781,7 +788,7 @@ setTransformation(AttributeOperation, MergeOperation, (a, b) => {
|
|
|
781
788
|
//
|
|
782
789
|
if (a.range.start.hasSameParentAs(b.deletionPosition)) {
|
|
783
790
|
if (a.range.containsPosition(b.deletionPosition) || a.range.start.isEqual(b.deletionPosition)) {
|
|
784
|
-
ranges.push(
|
|
791
|
+
ranges.push(ModelRange._createFromPositionAndShift(b.graveyardPosition, 1));
|
|
785
792
|
}
|
|
786
793
|
}
|
|
787
794
|
const range = a.range._getTransformedByMergeOperation(b);
|
|
@@ -811,7 +818,7 @@ setTransformation(AttributeOperation, MoveOperation, (a, b) => {
|
|
|
811
818
|
* track only how those nodes have been affected by `MoveOperation`.
|
|
812
819
|
*/
|
|
813
820
|
function _breakRangeByMoveOperation(range, moveOp) {
|
|
814
|
-
const moveRange =
|
|
821
|
+
const moveRange = ModelRange._createFromPositionAndShift(moveOp.sourcePosition, moveOp.howMany);
|
|
815
822
|
// We are transforming `range` (original range) by `moveRange` (range moved by move operation). As usual when it comes to
|
|
816
823
|
// transforming a ranges, we may have a common part of the ranges and we may have a difference part (zero to two ranges).
|
|
817
824
|
let common = null;
|
|
@@ -894,7 +901,7 @@ setTransformation(AttributeOperation, SplitOperation, (a, b) => {
|
|
|
894
901
|
//
|
|
895
902
|
if (a.range.start.hasSameParentAs(b.splitPosition) && a.range.containsPosition(b.splitPosition)) {
|
|
896
903
|
const secondPart = a.clone();
|
|
897
|
-
secondPart.range = new
|
|
904
|
+
secondPart.range = new ModelRange(b.moveTargetPosition.clone(), a.range.end._getCombined(b.splitPosition, b.moveTargetPosition));
|
|
898
905
|
a.range.end = b.splitPosition.clone();
|
|
899
906
|
a.range.end.stickiness = 'toPrevious';
|
|
900
907
|
return [a, secondPart];
|
|
@@ -994,7 +1001,7 @@ setTransformation(MarkerOperation, MergeOperation, (a, b) => {
|
|
|
994
1001
|
setTransformation(MarkerOperation, MoveOperation, (a, b) => {
|
|
995
1002
|
const result = [a];
|
|
996
1003
|
if (a.oldRange) {
|
|
997
|
-
a.oldRange =
|
|
1004
|
+
a.oldRange = ModelRange._createFromRanges(a.oldRange._getTransformedByMoveOperation(b));
|
|
998
1005
|
}
|
|
999
1006
|
if (a.newRange) {
|
|
1000
1007
|
// In many simple cases the marker range will be kept integral after the transformation. For example, if some nodes
|
|
@@ -1050,7 +1057,7 @@ setTransformation(MarkerOperation, SplitOperation, (a, b, context) => {
|
|
|
1050
1057
|
// <p>Foo</p>[<p>Bar]</p> -- merge -> <p>Foo[Bar]</p> -- default split -> <p>Foo</p><p>[Bar]</p>
|
|
1051
1058
|
// <p>Foo</p>[<p>Bar]</p> -- merge -> <p>Foo[Bar]</p> --- fixed split --> <p>Foo</p>[<p>Bar]</p>
|
|
1052
1059
|
//
|
|
1053
|
-
a.newRange.start =
|
|
1060
|
+
a.newRange.start = ModelPosition._createAt(b.insertionPosition);
|
|
1054
1061
|
}
|
|
1055
1062
|
else if (context.abRelation.wasInLeftElement) {
|
|
1056
1063
|
// If the marker start was initially in the "left" element, keep the start position there.
|
|
@@ -1058,7 +1065,7 @@ setTransformation(MarkerOperation, SplitOperation, (a, b, context) => {
|
|
|
1058
1065
|
// <p>Foo[</p><p>Bar]</p> -- merge -> <p>Foo[Bar]</p> -- default split -> <p>Foo</p><p>[Bar]</p>
|
|
1059
1066
|
// <p>Foo[</p><p>Bar]</p> -- merge -> <p>Foo[Bar]</p> --- fixed split --> <p>Foo[</p><p>Bar]</p>
|
|
1060
1067
|
//
|
|
1061
|
-
a.newRange.start =
|
|
1068
|
+
a.newRange.start = ModelPosition._createAt(a.newRange.start);
|
|
1062
1069
|
}
|
|
1063
1070
|
else {
|
|
1064
1071
|
// Finally, the start position must have been at the beginning of the "right" (merged) element.
|
|
@@ -1071,7 +1078,7 @@ setTransformation(MarkerOperation, SplitOperation, (a, b, context) => {
|
|
|
1071
1078
|
// <p>Foo</p><p>[]Bar</p> -- merge -> <p>Foo[]Bar</p> -- default split -> <p>Foo[]</p><p>Bar</p>
|
|
1072
1079
|
// <p>Foo</p><p>[]Bar</p> -- merge -> <p>Foo[]Bar</p> --- fixed split --> <p>Foo</p><p>[]Bar</p>
|
|
1073
1080
|
//
|
|
1074
|
-
a.newRange.start =
|
|
1081
|
+
a.newRange.start = ModelPosition._createAt(b.moveTargetPosition);
|
|
1075
1082
|
}
|
|
1076
1083
|
}
|
|
1077
1084
|
else {
|
|
@@ -1089,7 +1096,7 @@ setTransformation(MarkerOperation, SplitOperation, (a, b, context) => {
|
|
|
1089
1096
|
// <p>[Foo</p>]<p>Bar</p> -- merge -> <p>[Foo]Bar</p> -- default split -> <p>[Foo]</p><p>Bar</p>
|
|
1090
1097
|
// <p>[Foo</p>]<p>Bar</p> -- merge -> <p>[Foo]Bar</p> --- fixed split --> <p>[Foo</p>]<p>Bar</p>
|
|
1091
1098
|
//
|
|
1092
|
-
a.newRange.end =
|
|
1099
|
+
a.newRange.end = ModelPosition._createAt(b.insertionPosition);
|
|
1093
1100
|
}
|
|
1094
1101
|
else if (context.abRelation.wasInRightElement) {
|
|
1095
1102
|
// If the marker was initially in the "right" element, keep the end position there.
|
|
@@ -1097,7 +1104,7 @@ setTransformation(MarkerOperation, SplitOperation, (a, b, context) => {
|
|
|
1097
1104
|
// <p>[Foo</p><p>]Bar</p> -- merge -> <p>[Foo]Bar</p> -- default split -> <p>[Foo]</p><p>Bar</p>
|
|
1098
1105
|
// <p>[Foo</p><p>]Bar</p> -- merge -> <p>[Foo]Bar</p> --- fixed split --> <p>[Foo</p><p>]Bar</p>
|
|
1099
1106
|
//
|
|
1100
|
-
a.newRange.end =
|
|
1107
|
+
a.newRange.end = ModelPosition._createAt(b.moveTargetPosition);
|
|
1101
1108
|
}
|
|
1102
1109
|
else {
|
|
1103
1110
|
// Finally, the end position must have been at the end of the "left" (merged) element.
|
|
@@ -1105,7 +1112,7 @@ setTransformation(MarkerOperation, SplitOperation, (a, b, context) => {
|
|
|
1105
1112
|
//
|
|
1106
1113
|
// Note, that this is what the default transformation does, so we could use `aNewRange.end`, but this is more clear.
|
|
1107
1114
|
//
|
|
1108
|
-
a.newRange.end =
|
|
1115
|
+
a.newRange.end = ModelPosition._createAt(a.newRange.end);
|
|
1109
1116
|
}
|
|
1110
1117
|
}
|
|
1111
1118
|
else {
|
|
@@ -1154,7 +1161,7 @@ setTransformation(MergeOperation, MergeOperation, (a, b, context) => {
|
|
|
1154
1161
|
else {
|
|
1155
1162
|
const path = b.graveyardPosition.path.slice();
|
|
1156
1163
|
path.push(0);
|
|
1157
|
-
a.sourcePosition = new
|
|
1164
|
+
a.sourcePosition = new ModelPosition(b.graveyardPosition.root, path);
|
|
1158
1165
|
a.howMany = 0;
|
|
1159
1166
|
return [a];
|
|
1160
1167
|
}
|
|
@@ -1232,7 +1239,7 @@ setTransformation(MergeOperation, MoveOperation, (a, b, context) => {
|
|
|
1232
1239
|
//
|
|
1233
1240
|
// The exception to this rule would be if the remove operation was later undone.
|
|
1234
1241
|
//
|
|
1235
|
-
const removedRange =
|
|
1242
|
+
const removedRange = ModelRange._createFromPositionAndShift(b.sourcePosition, b.howMany);
|
|
1236
1243
|
if (b.type == 'remove' && !context.bWasUndone) {
|
|
1237
1244
|
if (a.deletionPosition.hasSameParentAs(b.sourcePosition) && removedRange.containsPosition(a.sourcePosition)) {
|
|
1238
1245
|
return [new NoOperation(0)];
|
|
@@ -1434,7 +1441,7 @@ setTransformation(MergeOperation, SplitOperation, (a, b, context) => {
|
|
|
1434
1441
|
});
|
|
1435
1442
|
// -----------------------
|
|
1436
1443
|
setTransformation(MoveOperation, InsertOperation, (a, b) => {
|
|
1437
|
-
const moveRange =
|
|
1444
|
+
const moveRange = ModelRange._createFromPositionAndShift(a.sourcePosition, a.howMany);
|
|
1438
1445
|
const transformed = moveRange._getTransformedByInsertOperation(b, false)[0];
|
|
1439
1446
|
a.sourcePosition = transformed.start;
|
|
1440
1447
|
a.howMany = transformed.end.offset - transformed.start.offset;
|
|
@@ -1454,8 +1461,8 @@ setTransformation(MoveOperation, MoveOperation, (a, b, context) => {
|
|
|
1454
1461
|
// Setting and evaluating some variables that will be used in special cases and default algorithm.
|
|
1455
1462
|
//
|
|
1456
1463
|
// Create ranges from `MoveOperations` properties.
|
|
1457
|
-
const rangeA =
|
|
1458
|
-
const rangeB =
|
|
1464
|
+
const rangeA = ModelRange._createFromPositionAndShift(a.sourcePosition, a.howMany);
|
|
1465
|
+
const rangeB = ModelRange._createFromPositionAndShift(b.sourcePosition, b.howMany);
|
|
1459
1466
|
// Assign `context.aIsStrong` to a different variable, because the value may change during execution of
|
|
1460
1467
|
// this algorithm and we do not want to override original `context.aIsStrong` that will be used in later transformations.
|
|
1461
1468
|
let aIsStrong = context.aIsStrong;
|
|
@@ -1614,22 +1621,31 @@ setTransformation(MoveOperation, SplitOperation, (a, b, context) => {
|
|
|
1614
1621
|
}
|
|
1615
1622
|
// Case 1:
|
|
1616
1623
|
//
|
|
1624
|
+
// Split operation brings back an element that was earlier a part of the move operation (first element of the original move operation).
|
|
1625
|
+
//
|
|
1626
|
+
if (a.sourcePosition.isEqual(b.insertionPosition) && context.abRelation == 'firstToMoveMerged') {
|
|
1627
|
+
a.howMany++;
|
|
1628
|
+
a.targetPosition = newTargetPosition;
|
|
1629
|
+
return [a];
|
|
1630
|
+
}
|
|
1631
|
+
// Case 2:
|
|
1632
|
+
//
|
|
1617
1633
|
// Last element in the moved range got split.
|
|
1618
1634
|
//
|
|
1619
1635
|
// In this case the default range transformation will not work correctly as the element created by
|
|
1620
1636
|
// split operation would be outside the range. The range to move needs to be fixed manually.
|
|
1621
1637
|
//
|
|
1622
|
-
const moveRange =
|
|
1638
|
+
const moveRange = ModelRange._createFromPositionAndShift(a.sourcePosition, a.howMany);
|
|
1623
1639
|
if (moveRange.end.isEqual(b.insertionPosition)) {
|
|
1624
1640
|
// Do it only if this is a "natural" split, not a one that comes from undo.
|
|
1625
1641
|
// If this is undo split, only `targetPosition` needs to be changed (if the move is a remove).
|
|
1626
|
-
if (!b.graveyardPosition) {
|
|
1642
|
+
if (!b.graveyardPosition || context.abRelation == 'lastToMoveMerged') {
|
|
1627
1643
|
a.howMany++;
|
|
1628
1644
|
}
|
|
1629
1645
|
a.targetPosition = newTargetPosition;
|
|
1630
1646
|
return [a];
|
|
1631
1647
|
}
|
|
1632
|
-
// Case
|
|
1648
|
+
// Case 3:
|
|
1633
1649
|
//
|
|
1634
1650
|
// Split happened between the moved nodes. In this case two ranges to move need to be generated.
|
|
1635
1651
|
//
|
|
@@ -1646,15 +1662,15 @@ setTransformation(MoveOperation, SplitOperation, (a, b, context) => {
|
|
|
1646
1662
|
// <p>F</p><p>r</p><p>Xyzozba</p>
|
|
1647
1663
|
//
|
|
1648
1664
|
if (moveRange.start.hasSameParentAs(b.splitPosition) && moveRange.containsPosition(b.splitPosition)) {
|
|
1649
|
-
let rightRange = new
|
|
1665
|
+
let rightRange = new ModelRange(b.splitPosition, moveRange.end);
|
|
1650
1666
|
rightRange = rightRange._getTransformedBySplitOperation(b);
|
|
1651
1667
|
const ranges = [
|
|
1652
|
-
new
|
|
1668
|
+
new ModelRange(moveRange.start, b.splitPosition),
|
|
1653
1669
|
rightRange
|
|
1654
1670
|
];
|
|
1655
1671
|
return _makeMoveOperationsFromRanges(ranges, newTargetPosition);
|
|
1656
1672
|
}
|
|
1657
|
-
// Case
|
|
1673
|
+
// Case 4:
|
|
1658
1674
|
//
|
|
1659
1675
|
// Move operation targets at the split position. We need to decide if the nodes should be inserted
|
|
1660
1676
|
// at the end of the split element or at the beginning of the new element.
|
|
@@ -1662,7 +1678,7 @@ setTransformation(MoveOperation, SplitOperation, (a, b, context) => {
|
|
|
1662
1678
|
if (a.targetPosition.isEqual(b.splitPosition) && context.abRelation == 'insertAtSource') {
|
|
1663
1679
|
newTargetPosition = b.moveTargetPosition;
|
|
1664
1680
|
}
|
|
1665
|
-
// Case
|
|
1681
|
+
// Case 5:
|
|
1666
1682
|
//
|
|
1667
1683
|
// Move operation targets just after the split element. We need to decide if the nodes should be inserted
|
|
1668
1684
|
// between two parts of split element, or after the new element.
|
|
@@ -1690,20 +1706,20 @@ setTransformation(MoveOperation, SplitOperation, (a, b, context) => {
|
|
|
1690
1706
|
//
|
|
1691
1707
|
const transformed = moveRange._getTransformedBySplitOperation(b);
|
|
1692
1708
|
const ranges = [transformed];
|
|
1693
|
-
// Case
|
|
1709
|
+
// Case 6:
|
|
1694
1710
|
//
|
|
1695
1711
|
// Moved range contains graveyard element used by split operation. Add extra move operation to the result.
|
|
1696
1712
|
//
|
|
1697
1713
|
if (b.graveyardPosition) {
|
|
1698
1714
|
const movesGraveyardElement = moveRange.start.isEqual(b.graveyardPosition) || moveRange.containsPosition(b.graveyardPosition);
|
|
1699
1715
|
if (a.howMany > 1 && movesGraveyardElement && !context.aWasUndone) {
|
|
1700
|
-
ranges.push(
|
|
1716
|
+
ranges.push(ModelRange._createFromPositionAndShift(b.insertionPosition, 1));
|
|
1701
1717
|
}
|
|
1702
1718
|
}
|
|
1703
1719
|
return _makeMoveOperationsFromRanges(ranges, newTargetPosition);
|
|
1704
1720
|
});
|
|
1705
1721
|
setTransformation(MoveOperation, MergeOperation, (a, b, context) => {
|
|
1706
|
-
const movedRange =
|
|
1722
|
+
const movedRange = ModelRange._createFromPositionAndShift(a.sourcePosition, a.howMany);
|
|
1707
1723
|
if (b.deletionPosition.hasSameParentAs(a.sourcePosition) && movedRange.containsPosition(b.sourcePosition)) {
|
|
1708
1724
|
if (a.type == 'remove' && !context.forceWeakRemove) {
|
|
1709
1725
|
// Case 1:
|
|
@@ -1730,7 +1746,7 @@ setTransformation(MoveOperation, MergeOperation, (a, b, context) => {
|
|
|
1730
1746
|
const gyMove = new MoveOperation(gyMoveSource, 1, gyMoveTarget, 0);
|
|
1731
1747
|
const splitNodesMoveTargetPath = gyMove.getMovedRangeStart().path.slice();
|
|
1732
1748
|
splitNodesMoveTargetPath.push(0);
|
|
1733
|
-
const splitNodesMoveTarget = new
|
|
1749
|
+
const splitNodesMoveTarget = new ModelPosition(gyMove.targetPosition.root, splitNodesMoveTargetPath);
|
|
1734
1750
|
splitNodesMoveSource = splitNodesMoveSource._getTransformedByMove(gyMoveSource, gyMoveTarget, 1);
|
|
1735
1751
|
const splitNodesMove = new MoveOperation(splitNodesMoveSource, b.howMany, splitNodesMoveTarget, 0);
|
|
1736
1752
|
results.push(gyMove);
|
|
@@ -1759,7 +1775,7 @@ setTransformation(MoveOperation, MergeOperation, (a, b, context) => {
|
|
|
1759
1775
|
}
|
|
1760
1776
|
// The default case.
|
|
1761
1777
|
//
|
|
1762
|
-
const moveRange =
|
|
1778
|
+
const moveRange = ModelRange._createFromPositionAndShift(a.sourcePosition, a.howMany);
|
|
1763
1779
|
const transformed = moveRange._getTransformedByMergeOperation(b);
|
|
1764
1780
|
a.sourcePosition = transformed.start;
|
|
1765
1781
|
a.howMany = transformed.end.offset - transformed.start.offset;
|
|
@@ -1910,8 +1926,8 @@ setTransformation(SplitOperation, MergeOperation, (a, b, context) => {
|
|
|
1910
1926
|
if (!a.graveyardPosition && !context.bWasUndone && a.splitPosition.hasSameParentAs(b.sourcePosition)) {
|
|
1911
1927
|
const splitPath = b.graveyardPosition.path.slice();
|
|
1912
1928
|
splitPath.push(0);
|
|
1913
|
-
const splitPosition = new
|
|
1914
|
-
const insertionPosition = SplitOperation.getInsertionPosition(new
|
|
1929
|
+
const splitPosition = new ModelPosition(b.graveyardPosition.root, splitPath);
|
|
1930
|
+
const insertionPosition = SplitOperation.getInsertionPosition(new ModelPosition(b.graveyardPosition.root, splitPath));
|
|
1915
1931
|
const additionalSplit = new SplitOperation(splitPosition, 0, insertionPosition, null, 0);
|
|
1916
1932
|
a.splitPosition = a.splitPosition._getTransformedByMergeOperation(b);
|
|
1917
1933
|
a.insertionPosition = SplitOperation.getInsertionPosition(a.splitPosition);
|
|
@@ -1935,7 +1951,7 @@ setTransformation(SplitOperation, MergeOperation, (a, b, context) => {
|
|
|
1935
1951
|
return [a];
|
|
1936
1952
|
});
|
|
1937
1953
|
setTransformation(SplitOperation, MoveOperation, (a, b, context) => {
|
|
1938
|
-
const rangeToMove =
|
|
1954
|
+
const rangeToMove = ModelRange._createFromPositionAndShift(b.sourcePosition, b.howMany);
|
|
1939
1955
|
if (a.graveyardPosition) {
|
|
1940
1956
|
// Case 1:
|
|
1941
1957
|
//
|
|
@@ -1949,7 +1965,7 @@ setTransformation(SplitOperation, MoveOperation, (a, b, context) => {
|
|
|
1949
1965
|
const newParentPosition = a.graveyardPosition._getTransformedByMoveOperation(b);
|
|
1950
1966
|
const newTargetPath = newParentPosition.path.slice();
|
|
1951
1967
|
newTargetPath.push(0);
|
|
1952
|
-
const newTargetPosition = new
|
|
1968
|
+
const newTargetPosition = new ModelPosition(newParentPosition.root, newTargetPath);
|
|
1953
1969
|
const moveOp = new MoveOperation(sourcePosition, a.howMany, newTargetPosition, 0);
|
|
1954
1970
|
return [moveOp];
|
|
1955
1971
|
}
|
|
@@ -1973,6 +1989,7 @@ setTransformation(SplitOperation, MoveOperation, (a, b, context) => {
|
|
|
1973
1989
|
const { howMany, offset } = context.abRelation;
|
|
1974
1990
|
a.howMany += howMany;
|
|
1975
1991
|
a.splitPosition = a.splitPosition.getShiftedBy(offset);
|
|
1992
|
+
// TODO: `insertionPosition` change missing?
|
|
1976
1993
|
return [a];
|
|
1977
1994
|
}
|
|
1978
1995
|
// Case 3:
|
|
@@ -2119,7 +2136,7 @@ setTransformation(SplitOperation, SplitOperation, (a, b, context) => {
|
|
|
2119
2136
|
if (b.splitPosition.isEqual(a.insertionPosition) && context.baRelation == 'splitBefore') {
|
|
2120
2137
|
const newPositionPath = b.insertionPosition.path.slice();
|
|
2121
2138
|
newPositionPath.push(0);
|
|
2122
|
-
const newPosition = new
|
|
2139
|
+
const newPosition = new ModelPosition(b.insertionPosition.root, newPositionPath);
|
|
2123
2140
|
const moveOp = new MoveOperation(a.insertionPosition, 1, newPosition, 0);
|
|
2124
2141
|
return [a, moveOp];
|
|
2125
2142
|
}
|
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @module engine/model/operation/utils
|
|
7
7
|
*/
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import type
|
|
11
|
-
import type
|
|
12
|
-
import type
|
|
13
|
-
import type
|
|
8
|
+
import { ModelNode } from '../node.js';
|
|
9
|
+
import { ModelRange } from '../range.js';
|
|
10
|
+
import { type ModelDocumentFragment } from '../documentfragment.js';
|
|
11
|
+
import { type ModelItem } from '../item.js';
|
|
12
|
+
import { type ModelNodeList } from '../nodelist.js';
|
|
13
|
+
import { type ModelPosition } from '../position.js';
|
|
14
14
|
/**
|
|
15
15
|
* Inserts given nodes at given position.
|
|
16
16
|
*
|
|
@@ -19,23 +19,23 @@ import type Position from '../position.js';
|
|
|
19
19
|
* @param nodes Nodes to insert.
|
|
20
20
|
* @returns Range spanning over inserted elements.
|
|
21
21
|
*/
|
|
22
|
-
export declare function _insert(position:
|
|
22
|
+
export declare function _insert(position: ModelPosition, nodes: ModelNodeSet): ModelRange;
|
|
23
23
|
/**
|
|
24
|
-
* Removed nodes in given range. Only {@link module:engine/model/range~
|
|
24
|
+
* Removed nodes in given range. Only {@link module:engine/model/range~ModelRange#isFlat flat} ranges are accepted.
|
|
25
25
|
*
|
|
26
26
|
* @internal
|
|
27
27
|
* @param range Range containing nodes to remove.
|
|
28
28
|
*/
|
|
29
|
-
export declare function _remove(this: any, range:
|
|
29
|
+
export declare function _remove(this: any, range: ModelRange): Array<ModelNode>;
|
|
30
30
|
/**
|
|
31
|
-
* Moves nodes in given range to given target position. Only {@link module:engine/model/range~
|
|
31
|
+
* Moves nodes in given range to given target position. Only {@link module:engine/model/range~ModelRange#isFlat flat} ranges are accepted.
|
|
32
32
|
*
|
|
33
33
|
* @internal
|
|
34
34
|
* @param sourceRange Range containing nodes to move.
|
|
35
35
|
* @param targetPosition Position to which nodes should be moved.
|
|
36
36
|
* @returns Range containing moved nodes.
|
|
37
37
|
*/
|
|
38
|
-
export declare function _move(this: any, sourceRange:
|
|
38
|
+
export declare function _move(this: any, sourceRange: ModelRange, targetPosition: ModelPosition): ModelRange;
|
|
39
39
|
/**
|
|
40
40
|
* Sets given attribute on nodes in given range. The attributes are only set on top-level nodes of the range, not on its children.
|
|
41
41
|
*
|
|
@@ -44,28 +44,29 @@ export declare function _move(this: any, sourceRange: Range, targetPosition: Pos
|
|
|
44
44
|
* @param key Key of attribute to set.
|
|
45
45
|
* @param value Attribute value.
|
|
46
46
|
*/
|
|
47
|
-
export declare function _setAttribute(range:
|
|
47
|
+
export declare function _setAttribute(range: ModelRange, key: string, value: unknown): void;
|
|
48
48
|
/**
|
|
49
|
-
* Normalizes given object or an array of objects to an array of {@link module:engine/model/node~
|
|
50
|
-
* {@link ~
|
|
49
|
+
* Normalizes given object or an array of objects to an array of {@link module:engine/model/node~ModelNode nodes}. See
|
|
50
|
+
* {@link ~ModelNodeSet NodeSet} for details on how normalization is performed.
|
|
51
51
|
*
|
|
52
52
|
* @internal
|
|
53
53
|
* @param nodes Objects to normalize.
|
|
54
54
|
* @returns Normalized nodes.
|
|
55
55
|
*/
|
|
56
|
-
export declare function _normalizeNodes(nodes:
|
|
56
|
+
export declare function _normalizeNodes(nodes: ModelNodeSet): Array<ModelNode>;
|
|
57
57
|
/**
|
|
58
|
-
* Value that can be normalized to an array of {@link module:engine/model/node~
|
|
58
|
+
* Value that can be normalized to an array of {@link module:engine/model/node~ModelNode nodes}.
|
|
59
59
|
*
|
|
60
60
|
* Non-arrays are normalized as follows:
|
|
61
|
-
* * {@link module:engine/model/node~
|
|
62
|
-
* * {@link module:engine/model/textproxy~
|
|
63
|
-
*
|
|
64
|
-
* * {@link module:engine/model/
|
|
65
|
-
* *
|
|
61
|
+
* * {@link module:engine/model/node~ModelNode Node} is left as is,
|
|
62
|
+
* * {@link module:engine/model/textproxy~ModelTextProxy TextProxy} and `string` are normalized to
|
|
63
|
+
* {@link module:engine/model/text~ModelText Text},
|
|
64
|
+
* * {@link module:engine/model/nodelist~ModelNodeList NodeList} is normalized to an array containing all nodes that are in that node list,
|
|
65
|
+
* * {@link module:engine/model/documentfragment~ModelDocumentFragment ModelDocumentFragment} is normalized to an array containing all of
|
|
66
|
+
* it's children.
|
|
66
67
|
*
|
|
67
68
|
* Arrays are processed item by item like non-array values and flattened to one array. Normalization always results in
|
|
68
|
-
* a flat array of {@link module:engine/model/node~
|
|
69
|
+
* a flat array of {@link module:engine/model/node~ModelNode nodes}. Consecutive text nodes (or items normalized to text nodes) will be
|
|
69
70
|
* merged if they have same attributes.
|
|
70
71
|
*/
|
|
71
|
-
export type
|
|
72
|
+
export type ModelNodeSet = ModelItem | string | ModelNodeList | ModelDocumentFragment | Iterable<ModelItem | string | ModelNodeList | ModelDocumentFragment>;
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* @module engine/model/operation/utils
|
|
7
7
|
*/
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
8
|
+
import { ModelNode } from '../node.js';
|
|
9
|
+
import { ModelRange } from '../range.js';
|
|
10
|
+
import { ModelText } from '../text.js';
|
|
11
|
+
import { ModelTextProxy } from '../textproxy.js';
|
|
12
12
|
import { CKEditorError, isIterable } from '@ckeditor/ckeditor5-utils';
|
|
13
13
|
/**
|
|
14
14
|
* Inserts given nodes at given position.
|
|
@@ -32,10 +32,10 @@ export function _insert(position, nodes) {
|
|
|
32
32
|
// Merge text nodes, if possible. Merging is needed only at points where inserted nodes "touch" "old" nodes.
|
|
33
33
|
_mergeNodesAtIndex(parent, index + normalizedNodes.length);
|
|
34
34
|
_mergeNodesAtIndex(parent, index);
|
|
35
|
-
return new
|
|
35
|
+
return new ModelRange(position, position.getShiftedBy(offset));
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
* Removed nodes in given range. Only {@link module:engine/model/range~
|
|
38
|
+
* Removed nodes in given range. Only {@link module:engine/model/range~ModelRange#isFlat flat} ranges are accepted.
|
|
39
39
|
*
|
|
40
40
|
* @internal
|
|
41
41
|
* @param range Range containing nodes to remove.
|
|
@@ -61,7 +61,7 @@ export function _remove(range) {
|
|
|
61
61
|
return removed;
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
|
-
* Moves nodes in given range to given target position. Only {@link module:engine/model/range~
|
|
64
|
+
* Moves nodes in given range to given target position. Only {@link module:engine/model/range~ModelRange#isFlat flat} ranges are accepted.
|
|
65
65
|
*
|
|
66
66
|
* @internal
|
|
67
67
|
* @param sourceRange Range containing nodes to move.
|
|
@@ -97,7 +97,7 @@ export function _setAttribute(range, key, value) {
|
|
|
97
97
|
_splitNodeAtPosition(range.end);
|
|
98
98
|
// Iterate over all items in the range.
|
|
99
99
|
for (const item of range.getItems({ shallow: true })) {
|
|
100
|
-
// Iterator will return `
|
|
100
|
+
// Iterator will return `ModelTextProxy` instances but we know that those text proxies will
|
|
101
101
|
// always represent full text nodes (this is guaranteed thanks to splitting we did before).
|
|
102
102
|
// So, we can operate on those text proxies' text nodes.
|
|
103
103
|
const node = item.is('$textProxy') ? item.textNode : item;
|
|
@@ -114,8 +114,8 @@ export function _setAttribute(range, key, value) {
|
|
|
114
114
|
_mergeNodesAtIndex(range.end.parent, range.end.index);
|
|
115
115
|
}
|
|
116
116
|
/**
|
|
117
|
-
* Normalizes given object or an array of objects to an array of {@link module:engine/model/node~
|
|
118
|
-
* {@link ~
|
|
117
|
+
* Normalizes given object or an array of objects to an array of {@link module:engine/model/node~ModelNode nodes}. See
|
|
118
|
+
* {@link ~ModelNodeSet NodeSet} for details on how normalization is performed.
|
|
119
119
|
*
|
|
120
120
|
* @internal
|
|
121
121
|
* @param nodes Objects to normalize.
|
|
@@ -125,12 +125,12 @@ export function _normalizeNodes(nodes) {
|
|
|
125
125
|
const normalized = [];
|
|
126
126
|
function convert(nodes) {
|
|
127
127
|
if (typeof nodes == 'string') {
|
|
128
|
-
normalized.push(new
|
|
128
|
+
normalized.push(new ModelText(nodes));
|
|
129
129
|
}
|
|
130
|
-
else if (nodes instanceof
|
|
131
|
-
normalized.push(new
|
|
130
|
+
else if (nodes instanceof ModelTextProxy) {
|
|
131
|
+
normalized.push(new ModelText(nodes.data, nodes.getAttributes()));
|
|
132
132
|
}
|
|
133
|
-
else if (nodes instanceof
|
|
133
|
+
else if (nodes instanceof ModelNode) {
|
|
134
134
|
normalized.push(nodes);
|
|
135
135
|
}
|
|
136
136
|
else if (isIterable(nodes)) {
|
|
@@ -149,16 +149,16 @@ export function _normalizeNodes(nodes) {
|
|
|
149
149
|
for (let i = 1; i < normalized.length; i++) {
|
|
150
150
|
const node = normalized[i];
|
|
151
151
|
const prev = normalized[i - 1];
|
|
152
|
-
if (node instanceof
|
|
152
|
+
if (node instanceof ModelText && prev instanceof ModelText && _haveSameAttributes(node, prev)) {
|
|
153
153
|
// Doing this instead changing `prev.data` because `data` is readonly.
|
|
154
|
-
normalized.splice(i - 1, 2, new
|
|
154
|
+
normalized.splice(i - 1, 2, new ModelText(prev.data + node.data, prev.getAttributes()));
|
|
155
155
|
i--;
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
return normalized;
|
|
159
159
|
}
|
|
160
160
|
/**
|
|
161
|
-
* Checks if nodes before and after given index in given element are {@link module:engine/model/text~
|
|
161
|
+
* Checks if nodes before and after given index in given element are {@link module:engine/model/text~ModelText text nodes} and
|
|
162
162
|
* merges them into one node if they have same attributes.
|
|
163
163
|
*
|
|
164
164
|
* Merging is done by removing two text nodes and inserting a new text node containing data from both merged text nodes.
|
|
@@ -172,7 +172,7 @@ function _mergeNodesAtIndex(element, index) {
|
|
|
172
172
|
// Check if both of those nodes are text objects with same attributes.
|
|
173
173
|
if (nodeBefore && nodeAfter && nodeBefore.is('$text') && nodeAfter.is('$text') && _haveSameAttributes(nodeBefore, nodeAfter)) {
|
|
174
174
|
// Append text of text node after index to the before one.
|
|
175
|
-
const mergedNode = new
|
|
175
|
+
const mergedNode = new ModelText(nodeBefore.data + nodeAfter.data, nodeBefore.getAttributes());
|
|
176
176
|
// Remove separate text nodes.
|
|
177
177
|
element._removeChildren(index - 1, 2);
|
|
178
178
|
// Insert merged text node.
|
|
@@ -192,8 +192,8 @@ function _splitNodeAtPosition(position) {
|
|
|
192
192
|
const offsetDiff = position.offset - textNode.startOffset;
|
|
193
193
|
const index = textNode.index;
|
|
194
194
|
element._removeChildren(index, 1);
|
|
195
|
-
const firstPart = new
|
|
196
|
-
const secondPart = new
|
|
195
|
+
const firstPart = new ModelText(textNode.data.substr(0, offsetDiff), textNode.getAttributes());
|
|
196
|
+
const secondPart = new ModelText(textNode.data.substr(offsetDiff), textNode.getAttributes());
|
|
197
197
|
element._insertChild(index, [firstPart, secondPart]);
|
|
198
198
|
}
|
|
199
199
|
}
|