8
0
Quellcode durchsuchen

Added: engine.treeModel.Range#getTransformedByMove.

Szymon Cofalik vor 9 Jahren
Ursprung
Commit
15c80dc6a2

+ 29 - 0
packages/ckeditor5-engine/src/treemodel/range.js

@@ -396,6 +396,35 @@ export default class Range {
 		}
 	}
 
+	/**
+	 * Returns an array containing {engine.treeModel.Range ranges} that are a result of transforming this
+	 * {@link engine.treeModel.Range range} by moving `howMany` nodes from `sourcePosition` to `targetPosition`.
+	 *
+	 * @param {engine.treeModel.Position} sourcePosition Position from which nodes are moved.
+	 * @param {engine.treeModel.Position} targetPosition Position to where nodes are moved.
+	 * @param {Number} howMany How many nodes are moved.
+	 * @returns {Array.<engine.treeModel.Range>} Result of the transformation.
+	 */
+	getTransformedByMove( sourcePosition, targetPosition, howMany ) {
+		const moveRange = new Range( sourcePosition, sourcePosition.getShiftedBy( howMany ) );
+
+		let containsStart = moveRange.containsPosition( this.start ) || moveRange.start.isEqual( this.start );
+		let containsEnd = moveRange.containsPosition( this.end ) || moveRange.end.isEqual( this.end );
+
+		const result = new Range( this.start, this.end );
+
+		if ( containsStart && !containsEnd ) {
+			result.start = moveRange.end;
+		} else if ( containsEnd && !containsStart ) {
+			result.end = moveRange.start;
+		}
+
+		result.start = result.start.getTransformedByMove( sourcePosition, targetPosition, howMany, true, containsStart && containsEnd );
+		result.end = result.end.getTransformedByMove( sourcePosition, targetPosition, howMany, result.isCollapsed, containsStart && containsEnd );
+
+		return [ result ];
+	}
+
 	/**
 	 * Two ranges equal if their start and end positions equal.
 	 *

+ 76 - 0
packages/ckeditor5-engine/tests/treemodel/range.js

@@ -441,6 +441,82 @@ describe( 'Range', () => {
 		} );
 	} );
 
+	describe( 'getTransformedByMove', () => {
+		it( 'should return an array of Range objects', () => {
+			const range = new Range( new Position( root, [ 0 ] ), new Position( root, [ 1 ] ) );
+			const transformed = range.getTransformedByMove( new Position( root, [ 2 ] ), new Position( root, [ 5 ] ), 2 );
+
+			expect( transformed ).to.be.instanceof( Array );
+			expect( transformed[ 0 ] ).to.be.instanceof( Range );
+		} );
+
+		it( 'should update it\'s positions offsets if target is before range and they are affected', () => {
+			const range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 3, 4 ] ) );
+			const transformed = range.getTransformedByMove( new Position( root, [ 8, 1 ] ), new Position( root, [ 3, 1 ] ), 2 );
+
+			expect( transformed[ 0 ].start.offset ).to.equal( 4 );
+			expect( transformed[ 0 ].end.offset ).to.equal( 6 );
+		} );
+
+		it( 'should update it\'s positions paths if target is before range and they are affected', () => {
+			const range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 4, 4 ] ) );
+			const transformed = range.getTransformedByMove( new Position( root, [ 8 ] ), new Position( root, [ 0 ] ), 2 );
+
+			expect( transformed[ 0 ].start.path[ 0 ] ).to.equal( 5 );
+			expect( transformed[ 0 ].end.path[ 0 ] ).to.equal( 6 );
+		} );
+
+		it( 'should expand range if target was in the middle of range', () => {
+			const range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 5, 4 ] ) );
+			const transformed = range.getTransformedByMove( new Position( root, [ 8 ] ), new Position( root, [ 5, 0 ] ), 4 );
+
+			expect( transformed.length ).to.equal( 1 );
+
+			expect( transformed[ 0 ].start.path ).to.deep.equal( [ 3, 2 ] );
+			expect( transformed[ 0 ].end.path ).to.deep.equal( [ 5, 8 ] );
+		} );
+
+		it( 'should not expand range if insertion is equal to start boundary of the range', () => {
+			const range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 3, 8 ] ) );
+			const transformed = range.getTransformedByMove( new Position( root, [ 8, 2 ] ), new Position( root, [ 3, 2 ] ), 3 );
+
+			expect( transformed[ 0 ].start.path ).to.deep.equal( [ 3, 5 ] );
+			expect( transformed[ 0 ].end.path ).to.deep.equal( [ 3, 11 ] );
+		} );
+
+		it( 'should not expand range if insertion is equal to end boundary of the range', () => {
+			const range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 4, 4 ] ) );
+			const transformed = range.getTransformedByMove( new Position( root, [ 8, 4 ] ), new Position( root, [ 4, 4 ] ), 3 );
+
+			expect( transformed[ 0 ].start.path ).to.deep.equal( [ 3, 2 ] );
+			expect( transformed[ 0 ].end.path ).to.deep.equal( [ 4, 4 ] );
+		} );
+
+		it( 'should update it\'s positions offsets if source is before range and they are affected', () => {
+			const range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 3, 4 ] ) );
+			const transformed = range.getTransformedByMove( new Position( root, [ 3, 0 ] ), new Position( root, [ 8, 1 ] ), 2 );
+
+			expect( transformed[ 0 ].start.offset ).to.equal( 0 );
+			expect( transformed[ 0 ].end.offset ).to.equal( 2 );
+		} );
+
+		it( 'should update it\'s positions paths if source is before range and they are affected', () => {
+			const range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 4, 4 ] ) );
+			const transformed = range.getTransformedByMove( new Position( root, [ 0 ] ), new Position( root, [ 8 ] ), 2 );
+
+			expect( transformed[ 0 ].start.path[ 0 ] ).to.equal( 1 );
+			expect( transformed[ 0 ].end.path[ 0 ] ).to.equal( 2 );
+		} );
+
+		it( 'should shrink range if source was in the middle of range', () => {
+			const range = new Range( new Position( root, [ 3, 2 ] ), new Position( root, [ 5, 4 ] ) );
+			const transformed = range.getTransformedByMove( new Position( root, [ 5, 0 ] ), new Position( root, [ 8 ] ), 4 );
+
+			expect( transformed[ 0 ].start.path ).to.deep.equal( [ 3, 2 ] );
+			expect( transformed[ 0 ].end.path ).to.deep.equal( [ 5, 0 ] );
+		} );
+	} );
+
 	describe( 'getDifference', () => {
 		let range;