Przeglądaj źródła

The InsertParagraphCommand should split position ancestors to find a place where a paragraph is allowed.

Aleksander Nowodzinski 5 lat temu
rodzic
commit
95cab0f6eb

+ 18 - 5
packages/ckeditor5-paragraph/src/insertparagraphcommand.js

@@ -18,6 +18,10 @@ import Command from '@ckeditor/ckeditor5-core/src/command';
  *			position: editor.model.createPositionBefore( element )
  *		} );
  *
+ * If a paragraph is disallowed in the context of the specific position, the command
+ * will attempt to split position ancestors to find a place where it is possible
+ * to insert a paragraph.
+ *
  * **Note**: This command moves the selection to the inserted paragraph.
  *
  * @extends module:core/command~Command
@@ -33,15 +37,24 @@ export default class InsertParagraphCommand extends Command {
 	 */
 	execute( options ) {
 		const model = this.editor.model;
-
-		if ( !model.schema.checkChild( options.position, 'paragraph' ) ) {
-			return;
-		}
+		let position = options.position;
 
 		model.change( writer => {
 			const paragraph = writer.createElement( 'paragraph' );
 
-			model.insertContent( paragraph, options.position );
+			if ( !model.schema.checkChild( position.parent, paragraph ) ) {
+				const allowedParent = model.schema.findAllowedParent( position, paragraph );
+
+				// It could be there's no ancestor limit that would allow paragraph.
+				// In theory, "paragraph" could be disallowed even in the "$root".
+				if ( !allowedParent ) {
+					return;
+				}
+
+				position = writer.split( position, allowedParent ).position;
+			}
+
+			model.insertContent( paragraph, position );
 
 			writer.setSelection( paragraph, 'in' );
 		} );

+ 28 - 6
packages/ckeditor5-paragraph/tests/insertparagraphcommand.js

@@ -23,7 +23,9 @@ describe( 'InsertParagraphCommand', () => {
 			editor.commands.add( 'insertParagraph', command );
 			schema.register( 'paragraph', { inheritAllFrom: '$block' } );
 			schema.register( 'heading1', { inheritAllFrom: '$block', allowIn: 'headersOnly' } );
-			schema.register( 'headersOnly', { inheritAllFrom: '$block' } );
+			schema.register( 'allowP', { inheritAllFrom: '$block' } );
+			schema.register( 'disallowP', { inheritAllFrom: '$block', allowIn: [ 'allowP' ] } );
+			model.schema.extend( 'paragraph', { allowIn: [ 'allowP' ] } );
 		} );
 	} );
 
@@ -42,18 +44,38 @@ describe( 'InsertParagraphCommand', () => {
 			expect( getData( model ) ).to.equal( '<paragraph>[]</paragraph><heading1>foo</heading1>' );
 		} );
 
-		it( 'should do nothing if the paragraph is not allowed at the provided position', () => {
-			setData( model, '<headersOnly><heading1>foo[]</heading1></headersOnly>' );
+		it( 'should split ancestors down to a limit where a paragraph is allowed', () => {
+			setData( model, '<allowP><disallowP>foo</disallowP></allowP>' );
 
 			command.execute( {
-				position: model.createPositionBefore( root.getChild( 0 ).getChild( 0 ) )
+				// fo[]o
+				position: model.createPositionAt( root.getChild( 0 ).getChild( 0 ), 2 )
 			} );
 
+			expect( getData( model ) ).to.equal(
+				'<allowP>' +
+					'<disallowP>fo</disallowP>' +
+					'<paragraph>[]</paragraph>' +
+					'<disallowP>o</disallowP>' +
+				'</allowP>'
+			);
+		} );
+
+		it( 'should do nothing if the paragraph is not allowed at the provided position', () => {
+			// Create a situation where "paragraph" is disallowed even in the "root".
+			schema.addChildCheck( ( context, childDefinition ) => {
+				if ( context.endsWith( '$root' ) && childDefinition.name == 'paragraph' ) {
+					return false;
+				}
+			} );
+
+			setData( model, '<heading1>foo[]</heading1>' );
+
 			command.execute( {
-				position: model.createPositionAfter( root.getChild( 0 ).getChild( 0 ) )
+				position: model.createPositionBefore( root.getChild( 0 ) )
 			} );
 
-			expect( getData( model ) ).to.equal( '<headersOnly><heading1>foo[]</heading1></headersOnly>' );
+			expect( getData( model ) ).to.equal( '<heading1>foo[]</heading1>' );
 		} );
 
 		describe( 'interation with existing paragraphs in the content', () => {