Browse Source

Merge branch 'master' into t/ckeditor5/401

Krzysztof Krztoń 6 years ago
parent
commit
e134fa19d6

+ 25 - 7
packages/ckeditor5-engine/src/model/operation/transform.js

@@ -541,7 +541,7 @@ class ContextFactory {
 						if ( ( affectedLeft || affectedRight ) && !movedRange.containsRange( markerRange ) ) {
 							this._setRelation( opA, opB, {
 								side: affectedLeft ? 'left' : 'right',
-								offset: affectedLeft ? markerRange.start.offset : markerRange.end.offset
+								path: affectedLeft ? markerRange.start.path.slice() : markerRange.end.path.slice()
 							} );
 						}
 
@@ -550,10 +550,17 @@ class ContextFactory {
 
 					case MergeOperation: {
 						const wasInLeftElement = markerRange.start.isEqual( opB.targetPosition );
+						const wasStartBeforeMergedElement = markerRange.start.isEqual( opB.deletionPosition );
+						const wasEndBeforeMergedElement = markerRange.end.isEqual( opB.deletionPosition );
 						const wasInRightElement = markerRange.end.isEqual( opB.sourcePosition );
 
-						if ( wasInLeftElement || wasInRightElement ) {
-							this._setRelation( opA, opB, { wasInLeftElement, wasInRightElement } );
+						if ( wasInLeftElement || wasStartBeforeMergedElement || wasEndBeforeMergedElement || wasInRightElement ) {
+							this._setRelation( opA, opB, {
+								wasInLeftElement,
+								wasStartBeforeMergedElement,
+								wasEndBeforeMergedElement,
+								wasInRightElement
+							} );
 						}
 
 						break;
@@ -1122,13 +1129,16 @@ setTransformation( MarkerOperation, MoveOperation, ( a, b, context ) => {
 
 	if ( a.newRange ) {
 		if ( context.abRelation ) {
+			const aNewRange = Range._createFromRanges( a.newRange._getTransformedByMoveOperation( b ) );
+
 			if ( context.abRelation.side == 'left' && b.targetPosition.isEqual( a.newRange.start ) ) {
-				a.newRange.start.offset = context.abRelation.offset;
-				a.newRange.end.offset += b.howMany;
+				a.newRange.start.path = context.abRelation.path;
+				a.newRange.end = aNewRange.end;
 
 				return [ a ];
 			} else if ( context.abRelation.side == 'right' && b.targetPosition.isEqual( a.newRange.end ) ) {
-				a.newRange.end.offset = context.abRelation.offset;
+				a.newRange.start = aNewRange.start;
+				a.newRange.end.path = context.abRelation.path;
 
 				return [ a ];
 			}
@@ -1147,12 +1157,20 @@ setTransformation( MarkerOperation, SplitOperation, ( a, b, context ) => {
 
 	if ( a.newRange ) {
 		if ( context.abRelation ) {
-			if ( a.newRange.start.isEqual( b.splitPosition ) && !context.abRelation.wasInLeftElement ) {
+			const aNewRange = a.newRange._getTransformedBySplitOperation( b );
+
+			if ( a.newRange.start.isEqual( b.splitPosition ) && context.abRelation.wasStartBeforeMergedElement ) {
+				a.newRange.start = Position._createAt( b.insertionPosition );
+			} else if ( a.newRange.start.isEqual( b.splitPosition ) && !context.abRelation.wasInLeftElement ) {
 				a.newRange.start = Position._createAt( b.moveTargetPosition );
 			}
 
 			if ( a.newRange.end.isEqual( b.splitPosition ) && context.abRelation.wasInRightElement ) {
 				a.newRange.end = Position._createAt( b.moveTargetPosition );
+			} else if ( a.newRange.end.isEqual( b.splitPosition ) && context.abRelation.wasEndBeforeMergedElement ) {
+				a.newRange.end = Position._createAt( b.insertionPosition );
+			} else {
+				a.newRange.end = aNewRange.end;
 			}
 
 			return [ a ];

+ 3 - 4
packages/ckeditor5-engine/src/model/writer.js

@@ -504,13 +504,12 @@ export default class Writer {
 		this._assertWriterUsedCorrectly();
 
 		const rangeToRemove = itemOrRange instanceof Range ? itemOrRange : Range._createOn( itemOrRange );
-
-		// If part of the marker is removed, create additional marker operation for undo purposes.
-		this._addOperationForAffectedMarkers( 'move', rangeToRemove );
-
 		const ranges = rangeToRemove.getMinimalFlatRanges().reverse();
 
 		for ( const flat of ranges ) {
+			// If part of the marker is removed, create additional marker operation for undo purposes.
+			this._addOperationForAffectedMarkers( 'move', flat );
+
 			applyRemoveOperation( flat.start, flat.end.offset - flat.start.offset, this.batch, this.model );
 		}
 	}

+ 64 - 0
packages/ckeditor5-engine/tests/model/operation/transform/undo.js

@@ -463,4 +463,68 @@ describe( 'transform', () => {
 
 		expectClients( '<paragraph><m1:start></m1:start>Foo<m1:end></m1:end>bar</paragraph><paragraph></paragraph>' );
 	} );
+
+	it( 'marker on closing and opening tag - remove multiple elements #1', () => {
+		john.setData(
+			'<paragraph>Abc</paragraph>' +
+			'<paragraph>Foo[</paragraph>' +
+			'<paragraph>]Bar</paragraph>'
+		);
+
+		john.setMarker( 'm1' );
+		john.setSelection( [ 0, 1 ], [ 2, 2 ] );
+		john._processExecute( 'delete' );
+
+		expectClients( '<paragraph>A<m1:start></m1:start>r</paragraph>' );
+
+		john.undo();
+
+		expectClients(
+			'<paragraph>Abc</paragraph>' +
+			'<paragraph>Foo<m1:start></m1:start></paragraph>' +
+			'<paragraph><m1:end></m1:end>Bar</paragraph>'
+		);
+	} );
+
+	it( 'marker on closing and opening tag - remove multiple elements #2', () => {
+		john.setData(
+			'<paragraph>Foo[</paragraph>' +
+			'<paragraph>]Bar</paragraph>' +
+			'<paragraph>Xyz</paragraph>'
+		);
+
+		john.setMarker( 'm1' );
+		john.setSelection( [ 0, 1 ], [ 2, 2 ] );
+		john._processExecute( 'delete' );
+
+		expectClients( '<paragraph>F<m1:start></m1:start>z</paragraph>' );
+
+		john.undo();
+
+		expectClients(
+			'<paragraph>Foo<m1:start></m1:start></paragraph>' +
+			'<paragraph><m1:end></m1:end>Bar</paragraph>' +
+			'<paragraph>Xyz</paragraph>'
+		);
+	} );
+
+	it( 'marker on closing and opening tag + some text - merge elements + remove text', () => {
+		john.setData(
+			'<paragraph>Foo[</paragraph>' +
+			'<paragraph>B]ar</paragraph>'
+		);
+
+		john.setMarker( 'm1' );
+		john.setSelection( [ 0, 1 ], [ 1, 2 ] );
+		john._processExecute( 'delete' );
+
+		expectClients( '<paragraph>F<m1:start></m1:start>r</paragraph>' );
+
+		john.undo();
+
+		expectClients(
+			'<paragraph>Foo<m1:start></m1:start></paragraph>' +
+			'<paragraph>B<m1:end></m1:end>ar</paragraph>'
+		);
+	} );
 } );