8
0
Просмотр исходного кода

Changed: Minor changes in deltas transformations.

Szymon Cofalik 8 лет назад
Родитель
Сommit
92dd1e19c3

+ 59 - 46
packages/ckeditor5-engine/src/model/delta/basic-transformations.js

@@ -55,31 +55,34 @@ addTransformationCase( AttributeDelta, SplitDelta, ( a, b, context ) => {
 
 
 	const deltas = defaultTransform( a, b, context );
 	const deltas = defaultTransform( a, b, context );
 
 
-	if ( !undoMode ) {
-		for ( const operation of a.operations ) {
-			// If a node that has been split has it's attribute updated, we should also update attribute of
-			// the node created during splitting.
-			if ( operation.range.containsPosition( splitPosition ) || operation.range.start.isEqual( splitPosition ) ) {
-				const additionalAttributeDelta = new AttributeDelta();
-
-				const rangeStart = splitPosition.getShiftedBy( 1 );
-				const rangeEnd = Position.createFromPosition( rangeStart );
-				rangeEnd.path.push( 0 );
-
-				const oldValue = b._cloneOperation.nodes.getNode( 0 ).getAttribute( operation.key );
-
-				additionalAttributeDelta.addOperation( new AttributeOperation(
-					new Range( rangeStart, rangeEnd ),
-					operation.key,
-					oldValue === undefined ? null : oldValue,
-					operation.newValue,
-					0
-				) );
-
-				deltas.push( additionalAttributeDelta );
-
-				break;
-			}
+	// Special case applies only if undo is not a context and only if `SplitDelta` has `InsertOperation` (not `ReinsertOperation`).
+	if ( undoMode || !( b._cloneOperation instanceof InsertOperation ) ) {
+		return deltas;
+	}
+
+	for ( const operation of a.operations ) {
+		// If a node that has been split has it's attribute updated, we should also update attribute of
+		// the node created during splitting.
+		if ( operation.range.containsPosition( splitPosition ) || operation.range.start.isEqual( splitPosition ) ) {
+			const additionalAttributeDelta = new AttributeDelta();
+
+			const rangeStart = splitPosition.getShiftedBy( 1 );
+			const rangeEnd = Position.createFromPosition( rangeStart );
+			rangeEnd.path.push( 0 );
+
+			const oldValue = b._cloneOperation.nodes.getNode( 0 ).getAttribute( operation.key );
+
+			additionalAttributeDelta.addOperation( new AttributeOperation(
+				new Range( rangeStart, rangeEnd ),
+				operation.key,
+				oldValue === undefined ? null : oldValue,
+				operation.newValue,
+				0
+			) );
+
+			deltas.push( additionalAttributeDelta );
+
+			break;
 		}
 		}
 	}
 	}
 
 
@@ -273,19 +276,22 @@ addTransformationCase( SplitDelta, AttributeDelta, ( a, b, context ) => {
 	const undoMode = context.aWasUndone || context.bWasUndone;
 	const undoMode = context.aWasUndone || context.bWasUndone;
 	const splitPosition = new Position( a.position.root, a.position.path.slice( 0, -1 ) );
 	const splitPosition = new Position( a.position.root, a.position.path.slice( 0, -1 ) );
 
 
-	if ( !undoMode && a._cloneOperation instanceof InsertOperation ) {
-		// If element to split had it's attribute changed, we have to reflect this change in an element
-		// that is in SplitDelta's InsertOperation.
-		for ( const operation of b.operations ) {
-			if ( operation.range.containsPosition( splitPosition ) || operation.range.start.isEqual( splitPosition ) ) {
-				if ( operation.newValue !== null ) {
-					a._cloneOperation.nodes.getNode( 0 ).setAttribute( operation.key, operation.newValue );
-				} else {
-					a._cloneOperation.nodes.getNode( 0 ).removeAttribute( operation.key );
-				}
-
-				break;
+	// Special case applies only if undo is not a context and only if `SplitDelta` has `InsertOperation` (not `ReinsertOperation`).
+	if ( undoMode || !( a._cloneOperation instanceof InsertOperation ) ) {
+		return [ a ];
+	}
+
+	// If element to split had it's attribute changed, we have to reflect this change in an element
+	// that is in SplitDelta's InsertOperation.
+	for ( const operation of b.operations ) {
+		if ( operation.range.containsPosition( splitPosition ) || operation.range.start.isEqual( splitPosition ) ) {
+			if ( operation.newValue !== null ) {
+				a._cloneOperation.nodes.getNode( 0 ).setAttribute( operation.key, operation.newValue );
+			} else {
+				a._cloneOperation.nodes.getNode( 0 ).removeAttribute( operation.key );
 			}
 			}
+
+			break;
 		}
 		}
 	}
 	}
 
 
@@ -357,7 +363,12 @@ addTransformationCase( RenameDelta, SplitDelta, ( a, b, context ) => {
 
 
 	const deltas = defaultTransform( a, b, context );
 	const deltas = defaultTransform( a, b, context );
 
 
-	if ( !undoMode && a.operations[ 0 ].position.isEqual( posBeforeSplitParent ) ) {
+	// Special case applies only if undo is not a context and only if `SplitDelta` has `InsertOperation` (not `ReinsertOperation`).
+	if ( undoMode || !( b._cloneOperation instanceof InsertOperation ) ) {
+		return deltas;
+	}
+
+	if ( a.operations[ 0 ].position.isEqual( posBeforeSplitParent ) ) {
 		// If a node that has been split has it's name changed, we should also change name of
 		// If a node that has been split has it's name changed, we should also change name of
 		// the node created during splitting.
 		// the node created during splitting.
 		const additionalRenameDelta = a.clone();
 		const additionalRenameDelta = a.clone();
@@ -371,24 +382,26 @@ addTransformationCase( RenameDelta, SplitDelta, ( a, b, context ) => {
 
 
 // Add special case for SplitDelta x RenameDelta transformation.
 // Add special case for SplitDelta x RenameDelta transformation.
 addTransformationCase( SplitDelta, RenameDelta, ( a, b, context ) => {
 addTransformationCase( SplitDelta, RenameDelta, ( a, b, context ) => {
+	a = a.clone();
+
 	const undoMode = context.aWasUndone || context.bWasUndone;
 	const undoMode = context.aWasUndone || context.bWasUndone;
 	const posBeforeSplitParent = new Position( a.position.root, a.position.path.slice( 0, -1 ) );
 	const posBeforeSplitParent = new Position( a.position.root, a.position.path.slice( 0, -1 ) );
 
 
+	// Special case applies only if undo is not a context and only if `SplitDelta` has `InsertOperation` (not `ReinsertOperation`).
+	if ( undoMode || !( a._cloneOperation instanceof InsertOperation ) ) {
+		return [ a ];
+	}
+
 	// If element to split had it's name changed, we have to reflect this by creating additional rename operation.
 	// If element to split had it's name changed, we have to reflect this by creating additional rename operation.
-	if ( !undoMode && b.operations[ 0 ].position.isEqual( posBeforeSplitParent ) ) {
+	if ( b.operations[ 0 ].position.isEqual( posBeforeSplitParent ) ) {
 		const additionalRenameDelta = b.clone();
 		const additionalRenameDelta = b.clone();
 		additionalRenameDelta.operations[ 0 ].position = posBeforeSplitParent.getShiftedBy( 1 );
 		additionalRenameDelta.operations[ 0 ].position = posBeforeSplitParent.getShiftedBy( 1 );
-
-		// `nodes` is a property that is available only if `SplitDelta` `a` has `InsertOperation`.
-		// `SplitDelta` may have `ReinsertOperation` instead of `InsertOperation`.
-		// However, such delta is only created when `MergeDelta` is reversed.
-		// So if this is not undo mode, it means that `SplitDelta` has `InsertOperation`.
 		additionalRenameDelta.operations[ 0 ].oldName = a._cloneOperation.nodes.getNode( 0 ).name;
 		additionalRenameDelta.operations[ 0 ].oldName = a._cloneOperation.nodes.getNode( 0 ).name;
 
 
-		return [ a.clone(), additionalRenameDelta ];
+		return [ a, additionalRenameDelta ];
 	}
 	}
 
 
-	return [ a.clone() ];
+	return [ a ];
 } );
 } );
 
 
 // Add special case for RemoveDelta x SplitDelta transformation.
 // Add special case for RemoveDelta x SplitDelta transformation.

+ 33 - 0
packages/ckeditor5-engine/tests/model/delta/transform/renamedelta.js

@@ -76,6 +76,39 @@ describe( 'transform', () => {
 				} );
 				} );
 			} );
 			} );
 
 
+			it( 'split element is renamed but split delta was undone', () => {
+				const renameDelta = new RenameDelta();
+				renameDelta.addOperation( new RenameOperation(
+					new Position( root, [ 3, 3 ] ),
+					'p',
+					'li',
+					baseVersion
+				) );
+
+				const splitPosition = new Position( root, [ 3, 3, 3 ] );
+				const splitDelta = getSplitDelta( splitPosition, new Element( 'p' ), 9, baseVersion );
+
+				context.bWasUndone = true;
+
+				const transformed = transform( renameDelta, splitDelta, context );
+
+				baseVersion = splitDelta.length;
+
+				expect( transformed.length ).to.equal( 1 );
+
+				expectDelta( transformed[ 0 ], {
+					type: RenameDelta,
+					operations: [
+						{
+							type: RenameOperation,
+							oldName: 'p',
+							newName: 'li',
+							position: new Position( root, [ 3, 3 ] )
+						}
+					]
+				} );
+			} );
+
 			it( 'split element is different than renamed element', () => {
 			it( 'split element is different than renamed element', () => {
 				const renameDelta = new RenameDelta();
 				const renameDelta = new RenameDelta();
 				renameDelta.addOperation( new RenameOperation(
 				renameDelta.addOperation( new RenameOperation(