diff --git a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts
index be5780a6e10..db619a63fb2 100644
--- a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts
+++ b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts
@@ -8,7 +8,7 @@
*/
import { Command, type Editor } from '@ckeditor/ckeditor5-core';
-import type { Element, Position } from '@ckeditor/ckeditor5-engine';
+import type { Element, Position, Writer } from '@ckeditor/ckeditor5-engine';
/**
* The insert paragraph command. It inserts a new paragraph at a specific
@@ -50,7 +50,7 @@ export default class InsertParagraphCommand extends Command {
const model = this.editor.model;
const attributes = options.attributes;
- let position = options.position;
+ let position: Position | null = options.position;
// Don't execute command if position is in non-editable place.
if ( !model.canEditAt( position ) ) {
@@ -58,53 +58,57 @@ export default class InsertParagraphCommand extends Command {
}
model.change( writer => {
- const paragraph = writer.createElement( 'paragraph' );
- const allowedParent = model.schema.findAllowedParent( position, paragraph );
+ position = this._findPositionToInsertParagraph( position!, writer );
- // It could be there's no ancestor limit that would allow paragraph.
- // In theory, "paragraph" could be disallowed even in the "$root".
- if ( !allowedParent ) {
+ if ( !position ) {
return;
}
+ const paragraph = writer.createElement( 'paragraph' );
+
if ( attributes ) {
model.schema.setAllowedAttributes( paragraph, attributes, writer );
}
- if ( position.path.length < 2 ) {
- model.insertContent( paragraph, position );
- writer.setSelection( paragraph, 'in' );
-
- return;
- }
+ model.insertContent( paragraph, position );
+ writer.setSelection( paragraph, 'in' );
+ } );
+ }
- const positionParent = position.parent as Element;
+ /**
+ * Returns the best position to insert a new paragraph.
+ */
+ private _findPositionToInsertParagraph( position: Position, writer: Writer ): Position | null {
+ const model = this.editor.model;
- // E.g.
- // [] ---> []
- const isInEmptyBlock = positionParent.isEmpty;
+ if ( model.schema.checkChild( position, 'paragraph' ) ) {
+ return position;
+ }
- // E.g.
- // foo[] ---> foo[]
- const isAtEndOfTextBlock = position.isAtEnd && !positionParent.isEmpty;
+ const allowedParent = model.schema.findAllowedParent( position, 'paragraph' );
- // E.g.
- // []foo ---> []foo
- const isAtStartOfTextBlock = position.isAtStart && !positionParent.isEmpty;
+ // 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 null;
+ }
- const canBeChild = model.schema.checkChild( positionParent, paragraph );
+ const positionParent = position.parent as Element;
+ const isTextAllowed = model.schema.checkChild( positionParent, '$text' );
- if ( isInEmptyBlock || isAtEndOfTextBlock ) {
- position = writer.createPositionAfter( positionParent );
- } else if ( isAtStartOfTextBlock ) {
- position = writer.createPositionBefore( positionParent );
- } else if ( !canBeChild ) {
- position = writer.split( position, allowedParent ).position;
- }
+ // At empty $block or at the end of $block.
+ // [] ---> []
+ // foo[] ---> foo[]
+ if ( positionParent.isEmpty || isTextAllowed && position.isAtEnd ) {
+ return model.createPositionAfter( positionParent );
+ }
- model.insertContent( paragraph, position );
+ // At the start of $block with text.
+ // []foo ---> []foo
+ if ( !positionParent.isEmpty && isTextAllowed && position.isAtStart ) {
+ return model.createPositionBefore( positionParent );
+ }
- writer.setSelection( paragraph, 'in' );
- } );
+ return writer.split( position, allowedParent ).position;
}
}
diff --git a/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js b/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js
index 03f1ccd2b7c..a4b2059eedc 100644
--- a/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js
+++ b/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js
@@ -137,6 +137,68 @@ describe( 'InsertParagraphCommand', () => {
);
} );
+ // See https://github.com/ckeditor/ckeditor5/issues/14714.
+ it( 'should insert paragraph bellow the block widget (inside container)', () => {
+ schema.register( 'blockContainer', { inheritAllFrom: '$container' } );
+ schema.register( 'blockWidget', { inheritAllFrom: '$blockObject', allowIn: 'allowP' } );
+
+ setData( model,
+ '' +
+ '[]' +
+ ''
+ );
+
+ command.execute( {
+ position: model.document.selection.getLastPosition()
+ } );
+
+ expect( getData( model ) ).to.equal(
+ '' +
+ '' +
+ '[]' +
+ ''
+ );
+ } );
+
+ // See https://github.com/ckeditor/ckeditor5/issues/14714.
+ it( 'should insert paragraph bellow the block widget (inside table cell)', () => {
+ schema.register( 'table', { inheritAllFrom: '$blockObject' } );
+ schema.register( 'tableRow', { allowIn: 'table', isLimit: true } );
+ schema.register( 'tableCell', {
+ allowContentOf: '$container',
+ allowIn: 'tableRow',
+ isLimit: true,
+ isSelectable: true
+ } );
+
+ schema.register( 'blockWidget', { inheritAllFrom: '$blockObject' } );
+
+ setData( model,
+ '
' +
+ '' +
+ '' +
+ '[]' +
+ '' +
+ '' +
+ '
'
+ );
+
+ command.execute( {
+ position: model.document.selection.getLastPosition()
+ } );
+
+ expect( getData( model ) ).to.equal(
+ '' +
+ '' +
+ '' +
+ '' +
+ '[]' +
+ '' +
+ '' +
+ '
'
+ );
+ } );
+
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 ) => {