Przeglądaj źródła

Improved a mechanism that handles the selection after inserting a horizontal rule.

Kamil Piechaczek 6 lat temu
rodzic
commit
05a56c460e

+ 25 - 2
packages/ckeditor5-horizontal-line/src/horizontalrulecommand.js

@@ -38,9 +38,32 @@ export default class HorizontalRuleCommand extends Command {
 		const model = this.editor.model;
 
 		model.change( writer => {
-			const modelElement = writer.createElement( 'horizontalRule' );
+			const horizontalElement = writer.createElement( 'horizontalRule' );
 
-			model.insertContent( modelElement );
+			model.insertContent( horizontalElement );
+
+			let nextElement = horizontalElement.nextSibling;
+
+			// Check whether the element next to inserted horizontal rule can contain a text.
+			// If so, let's put a selection at the beginning of the element.
+			if ( nextElement && model.schema.checkChild( nextElement, '$text' ) ) {
+				writer.setSelection( nextElement, 0 );
+
+				return;
+			}
+
+			// If the element is missing or it's not a paragraph, but the paragraph could be inserted
+			// next to the horizontal rule, let's add it.
+			if ( !( nextElement && nextElement.is( 'paragraph' ) ) && model.schema.checkChild( horizontalElement.parent, 'paragraph' ) ) {
+				nextElement = writer.createElement( 'paragraph' );
+
+				writer.insert( nextElement, writer.createPositionAfter( horizontalElement ) );
+			}
+
+			// Put the selection at the beginning of the element.
+			if ( nextElement ) {
+				writer.setSelection( nextElement, 0 );
+			}
 		} );
 	}
 }

+ 128 - 3
packages/ckeditor5-horizontal-line/tests/horizontalrulecommand.js

@@ -111,6 +111,14 @@ describe( 'HorizontalRuleCommand', () => {
 	} );
 
 	describe( 'execute()', () => {
+		beforeEach( () => {
+			model.schema.register( 'heading1', { inheritAllFrom: '$block' } );
+			editor.conversion.elementToElement( { model: 'heading1', view: 'h1' } );
+
+			model.schema.register( 'media', { allowWhere: '$block' } );
+			editor.conversion.elementToElement( { model: 'media', view: 'div' } );
+		} );
+
 		it( 'should create a single batch', () => {
 			setModelData( model, '<paragraph>foo[]</paragraph>' );
 
@@ -123,7 +131,14 @@ describe( 'HorizontalRuleCommand', () => {
 			sinon.assert.calledOnce( spy );
 		} );
 
-		it( 'should insert a horizontal rule in an empty root and select it', () => {
+		it( 'should insert a horizontal rule in an empty root and select it (a paragraph cannot be inserted)', () => {
+			// Block a paragraph in $root.
+			model.schema.addChildCheck( ( context, childDefinition ) => {
+				if ( childDefinition.name === 'paragraph' && context.last.name === '$root' ) {
+					return false;
+				}
+			} );
+
 			setModelData( model, '[]' );
 
 			command.execute();
@@ -137,7 +152,7 @@ describe( 'HorizontalRuleCommand', () => {
 			command.execute();
 
 			expect( getModelData( model ) ).to.equal(
-				'<paragraph>f</paragraph>[<horizontalRule></horizontalRule>]<paragraph>o</paragraph>'
+				'<paragraph>f</paragraph><horizontalRule></horizontalRule><paragraph>[]o</paragraph>'
 			);
 		} );
 
@@ -147,7 +162,117 @@ describe( 'HorizontalRuleCommand', () => {
 			command.execute();
 
 			expect( getModelData( model ) ).to.equal(
-				'<paragraph>fo</paragraph>[<horizontalRule></horizontalRule>]<paragraph>o</paragraph>'
+				'<paragraph>fo</paragraph><horizontalRule></horizontalRule><paragraph>[]o</paragraph>'
+			);
+		} );
+
+		it( 'should create an empty paragraph after inserting a horizontal rule after a paragraph and place selection inside', () => {
+			setModelData( model, '<paragraph>foo[]</paragraph>' );
+
+			command.execute();
+
+			expect( getModelData( model ) ).to.equal(
+				'<paragraph>foo</paragraph><horizontalRule></horizontalRule><paragraph>[]</paragraph>'
+			);
+		} );
+
+		it( 'should create an empty paragraph after inserting a horizontal rule after a heading and place selection inside', () => {
+			setModelData( model, '<heading1>foo[]</heading1>' );
+
+			command.execute();
+
+			expect( getModelData( model ) ).to.equal(
+				'<heading1>foo</heading1><horizontalRule></horizontalRule><paragraph>[]</paragraph>'
+			);
+		} );
+
+		it( 'should create an empty paragraph after inserting a horizontal rule and next element must not having text', () => {
+			setModelData( model, '<paragraph>foo[]</paragraph><media></media>' );
+
+			command.execute();
+
+			expect( getModelData( model ) ).to.equal(
+				'<paragraph>foo</paragraph><horizontalRule></horizontalRule><paragraph>[]</paragraph><media></media>'
+			);
+		} );
+
+		it( 'should create an empty paragraph after inserting a horizontal rule in heading and next element must not having text', () => {
+			setModelData( model, '<heading1>foo[]</heading1><media></media>' );
+
+			command.execute();
+
+			expect( getModelData( model ) ).to.equal(
+				'<heading1>foo</heading1><horizontalRule></horizontalRule><paragraph>[]</paragraph><media></media>'
+			);
+		} );
+
+		it( 'should not create an empty paragraph if a horizontal rule split an element with text', () => {
+			setModelData( model, '<heading1>foo[]bar</heading1>' );
+
+			command.execute();
+
+			expect( getModelData( model ) ).to.equal(
+				'<heading1>foo</heading1><horizontalRule></horizontalRule><heading1>[]bar</heading1>'
+			);
+		} );
+
+		it( 'should replace an empty paragraph with a horizontal rule and insert another paragraph next to', () => {
+			setModelData( model, '<paragraph>[]</paragraph>' );
+
+			command.execute();
+
+			expect( getModelData( model ) ).to.equal(
+				'<horizontalRule></horizontalRule><paragraph>[]</paragraph>'
+			);
+		} );
+
+		it( 'should replace an empty paragraph with a horizontal rule and move the selection to next paragraph', () => {
+			setModelData( model, '<paragraph>foo</paragraph><paragraph>[]</paragraph><paragraph>bar</paragraph>' );
+
+			command.execute();
+
+			expect( getModelData( model ) ).to.equal(
+				'<paragraph>foo</paragraph><horizontalRule></horizontalRule><paragraph>[]bar</paragraph>'
+			);
+		} );
+
+		it( 'should replace an empty paragraph with a horizontal rule and move the selection to next element that has text', () => {
+			setModelData( model, '<paragraph>foo</paragraph><paragraph>[]</paragraph><heading1>bar</heading1>' );
+
+			command.execute();
+
+			expect( getModelData( model ) ).to.equal(
+				'<paragraph>foo</paragraph><horizontalRule></horizontalRule><heading1>[]bar</heading1>'
+			);
+		} );
+
+		it( 'should replace an empty block element with a horizontal rule and insert a paragraph next to', () => {
+			setModelData( model, '<heading1>[]</heading1>' );
+
+			command.execute();
+
+			expect( getModelData( model ) ).to.equal(
+				'<horizontalRule></horizontalRule><paragraph>[]</paragraph>'
+			);
+		} );
+
+		it( 'should move the selection to next element if it allows having text (paragraph + heading)', () => {
+			setModelData( model, '<paragraph>foo[]</paragraph><heading1>bar</heading1>' );
+
+			command.execute();
+
+			expect( getModelData( model ) ).to.equal(
+				'<paragraph>foo</paragraph><horizontalRule></horizontalRule><heading1>[]bar</heading1>'
+			);
+		} );
+
+		it( 'should move the selection to next element if it allows having text (heading + paragraph)', () => {
+			setModelData( model, '<heading1>foo[]</heading1><paragraph>bar</paragraph>' );
+
+			command.execute();
+
+			expect( getModelData( model ) ).to.equal(
+				'<heading1>foo</heading1><horizontalRule></horizontalRule><paragraph>[]bar</paragraph>'
 			);
 		} );
 	} );