Jelajahi Sumber

Improved code coverage for engine.view.Renderer. Minor typo fixes.

Szymon Kupś 9 tahun lalu
induk
melakukan
82a0f04aeb

+ 2 - 2
packages/ckeditor5-engine/src/view/filler.js

@@ -10,7 +10,7 @@ import { keyCodes } from '../../utils/keyboard.js';
 /**
  * Set of utils related to block and inline fillers handling.
  *
- * Browsers do not allow to put caret in elements which does not have hight. Because of it, we need to fill all
+ * Browsers do not allow to put caret in elements which does not have height. Because of it, we need to fill all
  * empty elements which should be selectable with elements or characters called "fillers". Unfortunately there is no one
  * universal filler, this is why two types are uses:
  *
@@ -25,7 +25,7 @@ import { keyCodes } from '../../utils/keyboard.js';
  * `<b>` surrendered by text: `foo<b></b>bar`, if we want to put the caret there. CKEditor uses a sequence of the zero-width
  * spaces as an {@link engine.view.filler.INLINE_FILLER inline filler} having the predetermined
  * {@link engine.view.filler.INLINE_FILLER_LENGTH length}. A sequence is used, instead of a single character to
- * avoid threating random zero-width spaces as the inline filler. Disadvantage of the inline filler is that it is not
+ * avoid treating random zero-width spaces as the inline filler. Disadvantage of the inline filler is that it is not
  * transparent for the selection. The arrow key moves the caret between zero-width spaces characters, so the additional
  * code is needed to handle the caret.
  *

+ 2 - 2
packages/ckeditor5-engine/src/view/renderer.js

@@ -146,7 +146,7 @@ export default class Renderer {
 
 	/**
 	 * Render method checks {@link engine.view.Renderer#markedAttributes},
-	 * {@link engine.view.Renderer#markedChildren} and {@link engine.view.Renderer#markedTexts} and updats all
+	 * {@link engine.view.Renderer#markedChildren} and {@link engine.view.Renderer#markedTexts} and updates all
 	 * nodes which need to be updated. Then it clears all three sets. Also, every time render is called it compares and
 	 * if needed updates the selection.
 	 *
@@ -161,7 +161,7 @@ export default class Renderer {
 	 * {@link engine.view.DomConverter#getCorrespondingDomText corresponding DOM text}. The change will be handled
 	 * in the parent element.
 	 *
-	 * For elements, which child lists have changed, it calculates a {@link diff} and adds or removs children which have changed.
+	 * For elements, which child lists have changed, it calculates a {@link diff} and adds or removes children which have changed.
 	 *
 	 * Rendering also handles {@link engine.view.filler fillers}. Especially, it checks if the inline filler is needed
 	 * at selection position and adds or removes it. To prevent breaking text composition inline filler will not be

+ 76 - 0
packages/ckeditor5-engine/tests/view/renderer.js

@@ -495,6 +495,82 @@ describe( 'Renderer', () => {
 			expect( domSelection.getRangeAt( 0 ).collapsed ).to.be.true;
 		} );
 
+		it( 'should move filler when selection is moved', () => {
+			// Step 1: <p>foo<b>"FILLER{}"</b></p>
+			const { view: viewP, selection: newSelection } = parse(
+				'<container:p>foo<attribute:b>[]</attribute:b><attribute:i></attribute:i></container:p>' );
+
+			viewRoot.appendChildren( viewP );
+			selection.setTo( newSelection );
+
+			renderer.markToSync( 'children', viewRoot );
+
+			renderer.render();
+
+			const domP = domRoot.childNodes[ 0 ];
+
+			expect( domP.childNodes.length ).to.equal( 3 );
+			expect( domP.childNodes[ 0 ].data ).to.equal( 'foo' );
+			expect( domP.childNodes[ 1 ].tagName.toLowerCase() ).to.equal( 'b' );
+			expect( domP.childNodes[ 1 ].childNodes.length ).to.equal( 1 );
+			expect( domP.childNodes[ 1 ].childNodes[ 0 ].data ).to.equal( INLINE_FILLER );
+			expect( domP.childNodes[ 2 ].tagName.toLowerCase() ).to.equal( 'i' );
+			expect( domP.childNodes[ 2 ].childNodes.length ).to.equal( 0 );
+
+			// Step 2: <p>foo<b></b><i>"FILLER{}"</i></p>
+			selection.removeAllRanges();
+			const viewI = viewP.getChild( 2 );
+			selection.addRange( ViewRange.createFromParentsAndOffsets( viewI, 0, viewI, 0 ) );
+
+			renderer.render();
+
+			expect( domP.childNodes.length ).to.equal( 3 );
+			expect( domP.childNodes[ 0 ].data ).to.equal( 'foo' );
+			expect( domP.childNodes[ 1 ].tagName.toLowerCase() ).to.equal( 'b' );
+			expect( domP.childNodes[ 1 ].childNodes.length ).to.equal( 0 );
+			expect( domP.childNodes[ 2 ].tagName.toLowerCase() ).to.equal( 'i' );
+			expect( domP.childNodes[ 2 ].childNodes.length ).to.equal( 1 );
+			expect( domP.childNodes[ 2 ].childNodes[ 0 ].data ).to.equal( INLINE_FILLER );
+		} );
+
+		it( 'should remove filler when text is added and selection removed', () => {
+			// Step 1: <p>foo<b>"FILLER{}"</b></p>
+			const { view: viewP, selection: newSelection } = parse( '<container:p>foo<attribute:b>[]</attribute:b></container:p>' );
+			const viewB = viewP.getChild( 1 );
+			viewRoot.appendChildren( viewP );
+			selection.setTo( newSelection );
+
+			renderer.markToSync( 'children', viewRoot );
+			renderer.render();
+
+			const domP = domRoot.childNodes[ 0 ];
+			expect( domP.childNodes.length ).to.equal( 2 );
+			expect( domP.childNodes[ 0 ].data ).to.equal( 'foo' );
+			expect( domP.childNodes[ 1 ].tagName.toLowerCase() ).to.equal( 'b' );
+			expect( domP.childNodes[ 1 ].childNodes.length ).to.equal( 1 );
+			expect( domP.childNodes[ 1 ].childNodes[ 0 ].data ).to.equal( INLINE_FILLER );
+
+			// Step 2: Add text node.
+			const viewText = new ViewText( 'x' );
+			viewB.appendChildren( viewText );
+			selection.removeAllRanges();
+			selection.addRange( ViewRange.createFromParentsAndOffsets( viewText, 1, viewText, 1 ) );
+
+			renderer.markToSync( 'children', viewB );
+			renderer.render();
+
+			// Step 3: Remove selection from the view.
+			selection.removeAllRanges();
+
+			renderer.render();
+
+			expect( domP.childNodes.length ).to.equal( 2 );
+			expect( domP.childNodes[ 0 ].data ).to.equal( 'foo' );
+			expect( domP.childNodes[ 1 ].tagName.toLowerCase() ).to.equal( 'b' );
+			expect( domP.childNodes[ 1 ].childNodes.length ).to.equal( 1 );
+			expect( domP.childNodes[ 1 ].childNodes[ 0 ].data ).to.equal( 'x' );
+		} );
+
 		it( 'should handle typing in empty block, do nothing if changes are already applied', () => {
 			const domSelection = document.getSelection();