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

Fixed walking trough part of view.Text.

Oskar Wrobel 9 лет назад
Родитель
Сommit
7f25cdc744

+ 29 - 6
packages/ckeditor5-engine/src/view/treewalker.js

@@ -223,11 +223,23 @@ export default class TreeWalker {
 				return formatReturnValue( 'TEXT', item, prevPosition, position, charactersCount );
 				return formatReturnValue( 'TEXT', item, prevPosition, position, charactersCount );
 			}
 			}
 		} else if ( typeof node == 'string' ) {
 		} else if ( typeof node == 'string' ) {
-			const textProxy = new TextProxy( parent, position.offset, 1 );
-			position.offset++;
+			let textLength;
+
+			if ( !this.singleCharacters ) {
+				// Check if text stick out of walker range.
+				const endOffset = parent === this._boundaryEndParent ? this.boundaries.end.offset : parent._data.length;
+
+				textLength = endOffset - position.offset;
+			} else {
+				textLength = 1;
+			}
+
+			const textProxy = new TextProxy( parent, position.offset, textLength );
+
+			position.offset += textLength;
 			this.position = position;
 			this.position = position;
 
 
-			return formatReturnValue( 'TEXT', textProxy, previousPosition, position, 1 );
+			return formatReturnValue( 'TEXT', textProxy, previousPosition, position, textLength );
 		} else {
 		} else {
 			// `node` is not set, we reached the end of current `parent`.
 			// `node` is not set, we reached the end of current `parent`.
 			position = Position.createAfter( parent );
 			position = Position.createAfter( parent );
@@ -321,13 +333,24 @@ export default class TreeWalker {
 				return formatReturnValue( 'TEXT', item, prevPosition, position, charactersCount );
 				return formatReturnValue( 'TEXT', item, prevPosition, position, charactersCount );
 			}
 			}
 		} else if ( typeof node == 'string' ) {
 		} else if ( typeof node == 'string' ) {
-			position.offset--;
+			let textLength;
+
+			if ( !this.singleCharacters ) {
+				// Check if text stick out of walker range.
+				const startOffset = parent === this._boundaryStartParent ? this.boundaries.start.offset : 0;
+
+				textLength = position.offset - startOffset;
+			} else {
+				textLength = 1;
+			}
+
+			position.offset -= textLength;
 
 
-			const textProxy = new TextProxy( parent, position.offset, 1 );
+			const textProxy = new TextProxy( parent, position.offset, textLength );
 
 
 			this.position = position;
 			this.position = position;
 
 
-			return formatReturnValue( 'TEXT', textProxy, previousPosition, position, 1 );
+			return formatReturnValue( 'TEXT', textProxy, previousPosition, position, textLength );
 		} else {
 		} else {
 			// `node` is not set, we reached the beginning of current `parent`.
 			// `node` is not set, we reached the beginning of current `parent`.
 			position = Position.createBefore( parent );
 			position = Position.createBefore( parent );

+ 75 - 28
packages/ckeditor5-engine/tests/view/treewalker.js

@@ -17,7 +17,7 @@ import Range from '/ckeditor5/engine/view/range.js';
 import CKEditorError from '/ckeditor5/utils/ckeditorerror.js';
 import CKEditorError from '/ckeditor5/utils/ckeditorerror.js';
 
 
 describe( 'TreeWalker', () => {
 describe( 'TreeWalker', () => {
-	let doc, root, img1, paragraph, bold, textBa, charR, img2, charX;
+	let doc, root, img1, paragraph, bold, textAbcd, charY, img2, charX;
 	let rootBeginning, rootEnding;
 	let rootBeginning, rootEnding;
 
 
 	before( () => {
 	before( () => {
@@ -28,22 +28,24 @@ describe( 'TreeWalker', () => {
 		//  |- img1
 		//  |- img1
 		//  |- p
 		//  |- p
 		//     |- b
 		//     |- b
-		//     |  |- B
 		//     |  |- A
 		//     |  |- A
+		//     |  |- B
+		//     |  |- C
+		//     |  |- D
 		//     |
 		//     |
-		//     |- R
+		//     |- Y
 		//     |
 		//     |
 		//     |- img2
 		//     |- img2
 		//     |
 		//     |
 		//     |- X
 		//     |- X
 
 
-		textBa = new Text( 'ba' );
-		bold = new AttributeElement( 'b', null, [ textBa ] );
-		charR = new Text( 'r' );
+		textAbcd = new Text( 'abcd' );
+		bold = new AttributeElement( 'b', null, [ textAbcd ] );
+		charY = new Text( 'y' );
 		img2 = new ContainerElement( 'img2' );
 		img2 = new ContainerElement( 'img2' );
 		charX = new Text( 'x' );
 		charX = new Text( 'x' );
 
 
-		paragraph = new ContainerElement( 'p', null, [ bold, charR, img2, charX ] );
+		paragraph = new ContainerElement( 'p', null, [ bold, charY, img2, charX ] );
 		img1 = new ContainerElement( 'img1' );
 		img1 = new ContainerElement( 'img1' );
 
 
 		root.insertChildren( 0, [ img1, paragraph ] );
 		root.insertChildren( 0, [ img1, paragraph ] );
@@ -83,9 +85,9 @@ describe( 'TreeWalker', () => {
 				{ type: 'ELEMENT_END', item: img1 },
 				{ type: 'ELEMENT_END', item: img1 },
 				{ type: 'ELEMENT_START', item: paragraph },
 				{ type: 'ELEMENT_START', item: paragraph },
 				{ type: 'ELEMENT_START', item: bold },
 				{ type: 'ELEMENT_START', item: bold },
-				{ type: 'TEXT', text: 'ba' },
+				{ type: 'TEXT', text: 'abcd' },
 				{ type: 'ELEMENT_END', item: bold },
 				{ type: 'ELEMENT_END', item: bold },
-				{ type: 'TEXT', text: 'r' },
+				{ type: 'TEXT', text: 'y' },
 				{ type: 'ELEMENT_START', item: img2 },
 				{ type: 'ELEMENT_START', item: img2 },
 				{ type: 'ELEMENT_END', item: img2 },
 				{ type: 'ELEMENT_END', item: img2 },
 				{ type: 'TEXT', text: 'x' },
 				{ type: 'TEXT', text: 'x' },
@@ -162,9 +164,9 @@ describe( 'TreeWalker', () => {
 				expected = [
 				expected = [
 					{ type: 'ELEMENT_START', item: paragraph },
 					{ type: 'ELEMENT_START', item: paragraph },
 					{ type: 'ELEMENT_START', item: bold },
 					{ type: 'ELEMENT_START', item: bold },
-					{ type: 'TEXT', text: 'ba' },
+					{ type: 'TEXT', text: 'abcd' },
 					{ type: 'ELEMENT_END', item: bold },
 					{ type: 'ELEMENT_END', item: bold },
-					{ type: 'TEXT', text: 'r' },
+					{ type: 'TEXT', text: 'y' },
 					{ type: 'ELEMENT_START', item: img2 },
 					{ type: 'ELEMENT_START', item: img2 },
 					{ type: 'ELEMENT_END', item: img2 }
 					{ type: 'ELEMENT_END', item: img2 }
 				];
 				];
@@ -200,14 +202,14 @@ describe( 'TreeWalker', () => {
 
 
 			before( () => {
 			before( () => {
 				expected = [
 				expected = [
-					{ type: 'TEXT', text: 'a' },
+					{ type: 'TEXT', text: 'bcd' },
 					{ type: 'ELEMENT_END', item: bold },
 					{ type: 'ELEMENT_END', item: bold },
-					{ type: 'TEXT', text: 'r' },
+					{ type: 'TEXT', text: 'y' },
 					{ type: 'ELEMENT_START', item: img2 },
 					{ type: 'ELEMENT_START', item: img2 },
 					{ type: 'ELEMENT_END', item: img2 }
 					{ type: 'ELEMENT_END', item: img2 }
 				];
 				];
 
 
-				range = Range.createFromParentsAndOffsets( textBa, 1, paragraph, 3 );
+				range = Range.createFromParentsAndOffsets( textAbcd, 1, paragraph, 3 );
 			} );
 			} );
 
 
 			it( 'should return part of the text', () => {
 			it( 'should return part of the text', () => {
@@ -246,10 +248,49 @@ describe( 'TreeWalker', () => {
 					{ type: 'ELEMENT_END', item: img1 },
 					{ type: 'ELEMENT_END', item: img1 },
 					{ type: 'ELEMENT_START', item: paragraph },
 					{ type: 'ELEMENT_START', item: paragraph },
 					{ type: 'ELEMENT_START', item: bold },
 					{ type: 'ELEMENT_START', item: bold },
-					{ type: 'TEXT', text: 'b' }
+					{ type: 'TEXT', text: 'ab' }
 				];
 				];
 
 
-				range = new Range( rootBeginning, new Position( textBa, 1 ) );
+				range = new Range( rootBeginning, new Position( textAbcd, 2 ) );
+			} );
+
+			it( 'should return part of the text', () => {
+				let iterator = new TreeWalker( { boundaries: range } );
+				let i = 0;
+
+				for ( let value of iterator ) {
+					expectValue( value, expected[ i++ ] );
+				}
+
+				expect( i ).to.equal( expected.length );
+			} );
+
+			it( 'should return part of the text going backward', () => {
+				let iterator = new TreeWalker( {
+					boundaries: range,
+					startPosition: range.end,
+					direction: 'BACKWARD'
+				} );
+
+				let i = expected.length;
+
+				for ( let value of iterator ) {
+					expectValue( value, expected[ --i ], { direction: 'BACKWARD' } );
+				}
+
+				expect( i ).to.equal( 0 );
+			} );
+		} );
+
+		describe( 'range starts and ends inside the same text', () => {
+			let expected, range;
+
+			before( () => {
+				expected = [
+					{ type: 'TEXT', text: 'bc' }
+				];
+
+				range = new Range( new Position( textAbcd, 1 ), new Position( textAbcd, 3 ) );
 			} );
 			} );
 
 
 			it( 'should return part of the text', () => {
 			it( 'should return part of the text', () => {
@@ -283,7 +324,7 @@ describe( 'TreeWalker', () => {
 		describe( 'custom start position', () => {
 		describe( 'custom start position', () => {
 			it( 'should iterating from the start position', () => {
 			it( 'should iterating from the start position', () => {
 				let expected = [
 				let expected = [
-					{ type: 'TEXT', text: 'r' },
+					{ type: 'TEXT', text: 'y' },
 					{ type: 'ELEMENT_START', item: img2 },
 					{ type: 'ELEMENT_START', item: img2 },
 					{ type: 'ELEMENT_END', item: img2 }
 					{ type: 'ELEMENT_END', item: img2 }
 				];
 				];
@@ -305,12 +346,12 @@ describe( 'TreeWalker', () => {
 
 
 			it( 'should iterating from the start position going backward', () => {
 			it( 'should iterating from the start position going backward', () => {
 				let expected = [
 				let expected = [
-					{ type: 'TEXT', text: 'r' },
+					{ type: 'TEXT', text: 'y' },
 					{ type: 'ELEMENT_END', item: bold },
 					{ type: 'ELEMENT_END', item: bold },
-					{ type: 'TEXT', text: 'a' }
+					{ type: 'TEXT', text: 'bcd' }
 				];
 				];
 
 
-				let range = new Range( new Position( textBa, 1 ), new Position( paragraph, 3 ) );
+				let range = new Range( new Position( textAbcd, 1 ), new Position( paragraph, 3 ) );
 
 
 				let iterator = new TreeWalker( {
 				let iterator = new TreeWalker( {
 					boundaries: range,
 					boundaries: range,
@@ -338,10 +379,12 @@ describe( 'TreeWalker', () => {
 					{ type: 'ELEMENT_END', item: img1 },
 					{ type: 'ELEMENT_END', item: img1 },
 					{ type: 'ELEMENT_START', item: paragraph },
 					{ type: 'ELEMENT_START', item: paragraph },
 					{ type: 'ELEMENT_START', item: bold },
 					{ type: 'ELEMENT_START', item: bold },
-					{ type: 'TEXT', text: 'b' },
 					{ type: 'TEXT', text: 'a' },
 					{ type: 'TEXT', text: 'a' },
+					{ type: 'TEXT', text: 'b' },
+					{ type: 'TEXT', text: 'c' },
+					{ type: 'TEXT', text: 'd' },
 					{ type: 'ELEMENT_END', item: bold },
 					{ type: 'ELEMENT_END', item: bold },
-					{ type: 'TEXT', text: 'r' },
+					{ type: 'TEXT', text: 'y' },
 					{ type: 'ELEMENT_START', item: img2 },
 					{ type: 'ELEMENT_START', item: img2 },
 					{ type: 'ELEMENT_END', item: img2 },
 					{ type: 'ELEMENT_END', item: img2 },
 					{ type: 'TEXT', text: 'x' },
 					{ type: 'TEXT', text: 'x' },
@@ -381,10 +424,12 @@ describe( 'TreeWalker', () => {
 
 
 			before( () => {
 			before( () => {
 				expected = [
 				expected = [
-					{ type: 'TEXT', text: 'b' },
 					{ type: 'TEXT', text: 'a' },
 					{ type: 'TEXT', text: 'a' },
+					{ type: 'TEXT', text: 'b' },
+					{ type: 'TEXT', text: 'c' },
+					{ type: 'TEXT', text: 'd' },
 					{ type: 'ELEMENT_END', item: bold },
 					{ type: 'ELEMENT_END', item: bold },
-					{ type: 'TEXT', text: 'r' },
+					{ type: 'TEXT', text: 'y' },
 					{ type: 'ELEMENT_START', item: img2 }
 					{ type: 'ELEMENT_START', item: img2 }
 				];
 				];
 
 
@@ -461,8 +506,8 @@ describe( 'TreeWalker', () => {
 					{ type: 'ELEMENT_START', item: img1 },
 					{ type: 'ELEMENT_START', item: img1 },
 					{ type: 'ELEMENT_START', item: paragraph },
 					{ type: 'ELEMENT_START', item: paragraph },
 					{ type: 'ELEMENT_START', item: bold },
 					{ type: 'ELEMENT_START', item: bold },
-					{ type: 'TEXT', text: 'ba' },
-					{ type: 'TEXT', text: 'r' },
+					{ type: 'TEXT', text: 'abcd' },
+					{ type: 'TEXT', text: 'y' },
 					{ type: 'ELEMENT_START', item: img2 },
 					{ type: 'ELEMENT_START', item: img2 },
 					{ type: 'TEXT', text: 'x' }
 					{ type: 'TEXT', text: 'x' }
 				];
 				];
@@ -503,9 +548,11 @@ describe( 'TreeWalker', () => {
 					{ type: 'ELEMENT_START', item: img1 },
 					{ type: 'ELEMENT_START', item: img1 },
 					{ type: 'ELEMENT_START', item: paragraph },
 					{ type: 'ELEMENT_START', item: paragraph },
 					{ type: 'ELEMENT_START', item: bold },
 					{ type: 'ELEMENT_START', item: bold },
-					{ type: 'TEXT', text: 'b' },
 					{ type: 'TEXT', text: 'a' },
 					{ type: 'TEXT', text: 'a' },
-					{ type: 'TEXT', text: 'r' },
+					{ type: 'TEXT', text: 'b' },
+					{ type: 'TEXT', text: 'c' },
+					{ type: 'TEXT', text: 'd' },
+					{ type: 'TEXT', text: 'y' },
 					{ type: 'ELEMENT_START', item: img2 },
 					{ type: 'ELEMENT_START', item: img2 },
 					{ type: 'TEXT', text: 'x' }
 					{ type: 'TEXT', text: 'x' }
 				];
 				];