From 945dba623da5578c5ff602bc9e9ce83f5841f4cc Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Sun, 2 Jul 2023 17:07:03 +0200 Subject: [PATCH 01/11] Fix (paragraph): 'insertParagraph' should not insert two paragraphs --- .../src/insertparagraphcommand.ts | 32 +++++++++++++++---- .../tests/insertparagraphcommand.js | 26 +++++++++++++++ 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts index 9806ee3c5cc..2e93ccae910 100644 --- a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts +++ b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts @@ -59,20 +59,38 @@ export default class InsertParagraphCommand extends Command { model.change( writer => { const paragraph = writer.createElement( 'paragraph' ); + const parent = position.parent; if ( attributes ) { model.schema.setAllowedAttributes( paragraph, attributes, writer ); } - if ( !model.schema.checkChild( position.parent as Element, paragraph ) ) { - const allowedParent = model.schema.findAllowedParent( position, 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; - } + // 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; + } + if ( position.offset === 0 && position.path.length > 1 ) { + // When position is at the start of the line we want to insert paragraph before + // []foo ---> []foo + position = writer.createPositionFromPath( allowedParent, position.getParentPath() ); + } else if ( parent.maxOffset === position.offset && position.path.length > 1 ) { + // When position is at the end of the line we want to insert paragraph after + // foo[] ---> foo[] + const length = position.getParentPath().length; + const path = [ ...position.getParentPath().slice( 0, length - 1 ), position.getParentPath()[ length - 1 ] + 1 ]; + position = writer.createPositionFromPath( allowedParent, path ); + } else if ( !model.schema.checkChild( position.parent as Element, paragraph ) ) { + // When position is inside the content we want to split it + // fo[]o + // | + // ↓ + // fo + // [] + // o position = writer.split( position, allowedParent ).position; } diff --git a/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js b/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js index 6768ed9a582..8346fbe4df7 100644 --- a/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js +++ b/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js @@ -70,6 +70,32 @@ describe( 'InsertParagraphCommand', () => { ); } ); + it( 'should insert paragraph when position is at the end of line', () => { + setData( model, 'foo[]' ); + + command.execute( { + position: model.document.selection.getFirstPosition() + } ); + + expect( getData( model ) ).to.equal( + 'foo' + + '[]' + ); + } ); + + it( 'should insert paragraph when position is at the start of line', () => { + setData( model, '[]foo' ); + + command.execute( { + position: model.document.selection.getLastPosition() + } ); + + expect( getData( model ) ).to.equal( + '[]' + + 'foo' + ); + } ); + 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 ) => { From 0e693e64a63c701e7acc62662b76fce96175974f Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Mon, 3 Jul 2023 01:00:06 +0200 Subject: [PATCH 02/11] Fix (paragraph): handle case with non-text nodes --- .../src/insertparagraphcommand.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts index 2e93ccae910..174ded0c0b0 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, Text } from '@ckeditor/ckeditor5-engine'; /** * The insert paragraph command. It inserts a new paragraph at a specific @@ -59,7 +59,6 @@ export default class InsertParagraphCommand extends Command { model.change( writer => { const paragraph = writer.createElement( 'paragraph' ); - const parent = position.parent; if ( attributes ) { model.schema.setAllowedAttributes( paragraph, attributes, writer ); @@ -73,15 +72,16 @@ export default class InsertParagraphCommand extends Command { return; } - if ( position.offset === 0 && position.path.length > 1 ) { + if ( position.isAtStart && position.path.length > 1 && ( position.nodeAfter! as Text ).data ) { // When position is at the start of the line we want to insert paragraph before // []foo ---> []foo position = writer.createPositionFromPath( allowedParent, position.getParentPath() ); - } else if ( parent.maxOffset === position.offset && position.path.length > 1 ) { + } else if ( position.isAtEnd && position.path.length > 1 && ( position.nodeBefore! as Text ).data ) { // When position is at the end of the line we want to insert paragraph after // foo[] ---> foo[] - const length = position.getParentPath().length; - const path = [ ...position.getParentPath().slice( 0, length - 1 ), position.getParentPath()[ length - 1 ] + 1 ]; + const parentPath = position.getParentPath(); + const length = parentPath.length; + const path = [ ...parentPath.slice( 0, length - 1 ), parentPath[ length - 1 ] + 1 ]; position = writer.createPositionFromPath( allowedParent, path ); } else if ( !model.schema.checkChild( position.parent as Element, paragraph ) ) { // When position is inside the content we want to split it From 02f5384b3cb59416761f72f372aa229af8f7f5c0 Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Mon, 3 Jul 2023 01:13:44 +0200 Subject: [PATCH 03/11] Fix (paragraph): typescript fix --- packages/ckeditor5-paragraph/src/insertparagraphcommand.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts index 174ded0c0b0..34ff9293391 100644 --- a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts +++ b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts @@ -72,11 +72,11 @@ export default class InsertParagraphCommand extends Command { return; } - if ( position.isAtStart && position.path.length > 1 && ( position.nodeAfter! as Text ).data ) { + if ( position.isAtStart && position.path.length > 1 && ( position.nodeAfter as Text )?.data ) { // When position is at the start of the line we want to insert paragraph before // []foo ---> []foo position = writer.createPositionFromPath( allowedParent, position.getParentPath() ); - } else if ( position.isAtEnd && position.path.length > 1 && ( position.nodeBefore! as Text ).data ) { + } else if ( position.isAtEnd && position.path.length > 1 && ( position.nodeBefore as Text )?.data ) { // When position is at the end of the line we want to insert paragraph after // foo[] ---> foo[] const parentPath = position.getParentPath(); From cd7175e18b040c7443301ba94c25a43a810289f6 Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Mon, 3 Jul 2023 10:48:44 +0200 Subject: [PATCH 04/11] Fix (paragraph): back coverage to 100% --- .../src/insertparagraphcommand.ts | 30 +++++++++++++------ .../tests/insertparagraphcommand.js | 29 +++++++++++++++++- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts index 34ff9293391..4f19451732a 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, Text } from '@ckeditor/ckeditor5-engine'; +import type { Element, Position, Text, Writer } from '@ckeditor/ckeditor5-engine'; /** * The insert paragraph command. It inserts a new paragraph at a specific @@ -72,17 +72,20 @@ export default class InsertParagraphCommand extends Command { return; } - if ( position.isAtStart && position.path.length > 1 && ( position.nodeAfter as Text )?.data ) { - // When position is at the start of the line we want to insert paragraph before + if ( position.isAtStart && position.isAtEnd && position.path.length > 1 ) { + // NOTE: In case when paragraph is empty. + // When position is at the start and at the end of the line we want to insert paragraph after. + // [] ---> [] + position = createPositionBellow( writer, position, allowedParent ); + console.log( position ); + } else if ( position.isAtStart && position.path.length > 1 && ( position.nodeAfter as Text ).data ) { + // When position is at the start of the line we want to insert paragraph above. // []foo ---> []foo position = writer.createPositionFromPath( allowedParent, position.getParentPath() ); - } else if ( position.isAtEnd && position.path.length > 1 && ( position.nodeBefore as Text )?.data ) { - // When position is at the end of the line we want to insert paragraph after + } else if ( position.isAtEnd && position.path.length > 1 && ( position.nodeBefore as Text ).data ) { + // When position is at the end of the line we want to insert paragraph after. // foo[] ---> foo[] - const parentPath = position.getParentPath(); - const length = parentPath.length; - const path = [ ...parentPath.slice( 0, length - 1 ), parentPath[ length - 1 ] + 1 ]; - position = writer.createPositionFromPath( allowedParent, path ); + position = createPositionBellow( writer, position, allowedParent ); } else if ( !model.schema.checkChild( position.parent as Element, paragraph ) ) { // When position is inside the content we want to split it // fo[]o @@ -100,3 +103,12 @@ export default class InsertParagraphCommand extends Command { } ); } } + +// Creates bellow position where should be inserted new paragraph. +export function createPositionBellow( writer: Writer, position: Position, allowedParent: Element ): Position { + const parentPath = position.getParentPath(); + const length = parentPath.length; + const path = [ ...parentPath.slice( 0, length - 1 ), parentPath[ length - 1 ] + 1 ]; + + return writer.createPositionFromPath( allowedParent, path ); +} diff --git a/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js b/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js index 8346fbe4df7..3c13f5fb983 100644 --- a/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js +++ b/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js @@ -4,7 +4,7 @@ */ import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor'; -import InsertParagraphCommand from '../src/insertparagraphcommand'; +import InsertParagraphCommand, { createPositionBellow } from '../src/insertparagraphcommand'; import { setData, getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; @@ -96,6 +96,33 @@ describe( 'InsertParagraphCommand', () => { ); } ); + it( 'should insert paragraph when position is at the start of line asd', () => { + setData( model, '[]' ); + + command.execute( { + position: model.document.selection.getLastPosition() + } ); + + expect( getData( model ) ).to.equal( + '' + + '[]' + ); + } ); + + it( 'Should create position bellow', () => { + model.change( writer => { + let position = model.createPositionFromPath( root, [ 0, 2 ] ); + let expectedPosition = model.createPositionFromPath( root, [ 1 ] ); + expect( createPositionBellow( writer, position, root ), '[ 0, 2 ] --> [ 1 ]' ) + .to.eql( expectedPosition ); + + position = model.createPositionFromPath( root, [ 1, 2, 3 ] ); + expectedPosition = model.createPositionFromPath( root, [ 1, 3 ] ); + expect( createPositionBellow( writer, position, root ), '[ 1, 2, 3 ] --> [ 1, 3 ]' ) + .to.eql( expectedPosition ); + } ); + } ); + 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 ) => { From b0b99af145367e5d1259528a42993ea837cb1f63 Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Mon, 3 Jul 2023 10:53:37 +0200 Subject: [PATCH 05/11] Docs (paragraph): typo fix --- packages/ckeditor5-paragraph/src/insertparagraphcommand.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts index 4f19451732a..8d3dc23ba4b 100644 --- a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts +++ b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts @@ -74,7 +74,6 @@ export default class InsertParagraphCommand extends Command { if ( position.isAtStart && position.isAtEnd && position.path.length > 1 ) { // NOTE: In case when paragraph is empty. - // When position is at the start and at the end of the line we want to insert paragraph after. // [] ---> [] position = createPositionBellow( writer, position, allowedParent ); console.log( position ); From 872fd6ff3d60e14ad397c2de42ca5f19a23b90ee Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Mon, 3 Jul 2023 10:54:25 +0200 Subject: [PATCH 06/11] Fix (paragraph): console.log remove --- packages/ckeditor5-paragraph/src/insertparagraphcommand.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts index 8d3dc23ba4b..d3f30b83c89 100644 --- a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts +++ b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts @@ -76,7 +76,6 @@ export default class InsertParagraphCommand extends Command { // NOTE: In case when paragraph is empty. // [] ---> [] position = createPositionBellow( writer, position, allowedParent ); - console.log( position ); } else if ( position.isAtStart && position.path.length > 1 && ( position.nodeAfter as Text ).data ) { // When position is at the start of the line we want to insert paragraph above. // []foo ---> []foo From 16507124be0dcc3627b666b173afafba3e6c97b4 Mon Sep 17 00:00:00 2001 From: Illia Sheremetov Date: Wed, 5 Jul 2023 12:00:21 +0200 Subject: [PATCH 07/11] Fix (paragraph): code review fixes --- .../src/insertparagraphcommand.ts | 28 +++++++++---------- .../tests/insertparagraphcommand.js | 18 ++---------- 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts index d3f30b83c89..a29ea93ebb6 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, Text, Writer } from '@ckeditor/ckeditor5-engine'; +import type { Element, Position, Text, Item } from '@ckeditor/ckeditor5-engine'; /** * The insert paragraph command. It inserts a new paragraph at a specific @@ -72,18 +72,25 @@ export default class InsertParagraphCommand extends Command { return; } - if ( position.isAtStart && position.isAtEnd && position.path.length > 1 ) { + if ( position.path.length < 2 ) { + model.insertContent( paragraph, position ); + writer.setSelection( paragraph, 'in' ); + + return; + } + + if ( position.isAtStart && position.isAtEnd ) { // NOTE: In case when paragraph is empty. // [] ---> [] - position = createPositionBellow( writer, position, allowedParent ); - } else if ( position.isAtStart && position.path.length > 1 && ( position.nodeAfter as Text ).data ) { + position = writer.createPositionAfter( position.parent as Item ); + } else if ( position.isAtStart && ( position.nodeAfter as Text ).data ) { // When position is at the start of the line we want to insert paragraph above. // []foo ---> []foo position = writer.createPositionFromPath( allowedParent, position.getParentPath() ); - } else if ( position.isAtEnd && position.path.length > 1 && ( position.nodeBefore as Text ).data ) { + } else if ( position.isAtEnd && ( position.nodeBefore as Text ).data ) { // When position is at the end of the line we want to insert paragraph after. // foo[] ---> foo[] - position = createPositionBellow( writer, position, allowedParent ); + position = writer.createPositionAfter( position.parent as Item ); } else if ( !model.schema.checkChild( position.parent as Element, paragraph ) ) { // When position is inside the content we want to split it // fo[]o @@ -101,12 +108,3 @@ export default class InsertParagraphCommand extends Command { } ); } } - -// Creates bellow position where should be inserted new paragraph. -export function createPositionBellow( writer: Writer, position: Position, allowedParent: Element ): Position { - const parentPath = position.getParentPath(); - const length = parentPath.length; - const path = [ ...parentPath.slice( 0, length - 1 ), parentPath[ length - 1 ] + 1 ]; - - return writer.createPositionFromPath( allowedParent, path ); -} diff --git a/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js b/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js index 3c13f5fb983..8feec9e0a40 100644 --- a/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js +++ b/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js @@ -4,7 +4,7 @@ */ import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor'; -import InsertParagraphCommand, { createPositionBellow } from '../src/insertparagraphcommand'; +import InsertParagraphCommand from '../src/insertparagraphcommand'; import { setData, getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; @@ -96,7 +96,7 @@ describe( 'InsertParagraphCommand', () => { ); } ); - it( 'should insert paragraph when position is at the start of line asd', () => { + it( 'should insert paragraph bellow when paragraph is empty', () => { setData( model, '[]' ); command.execute( { @@ -109,20 +109,6 @@ describe( 'InsertParagraphCommand', () => { ); } ); - it( 'Should create position bellow', () => { - model.change( writer => { - let position = model.createPositionFromPath( root, [ 0, 2 ] ); - let expectedPosition = model.createPositionFromPath( root, [ 1 ] ); - expect( createPositionBellow( writer, position, root ), '[ 0, 2 ] --> [ 1 ]' ) - .to.eql( expectedPosition ); - - position = model.createPositionFromPath( root, [ 1, 2, 3 ] ); - expectedPosition = model.createPositionFromPath( root, [ 1, 3 ] ); - expect( createPositionBellow( writer, position, root ), '[ 1, 2, 3 ] --> [ 1, 3 ]' ) - .to.eql( expectedPosition ); - } ); - } ); - 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 ) => { From 6937732ea4675c3048d5fb33315b6b1ee15a690b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dariusz=20Jarz=C4=99bski?= Date: Wed, 5 Jul 2023 17:08:14 +0200 Subject: [PATCH 08/11] Refactor. --- .../src/insertparagraphcommand.ts | 48 +++++++++---------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts index a29ea93ebb6..0bbba39a24c 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, Text, Item } from '@ckeditor/ckeditor5-engine'; +import type { Element, Position, Item } from '@ckeditor/ckeditor5-engine'; /** * The insert paragraph command. It inserts a new paragraph at a specific @@ -59,11 +59,6 @@ export default class InsertParagraphCommand extends Command { model.change( writer => { const paragraph = writer.createElement( 'paragraph' ); - - if ( attributes ) { - model.schema.setAllowedAttributes( paragraph, attributes, writer ); - } - const allowedParent = model.schema.findAllowedParent( position, paragraph ); // It could be there's no ancestor limit that would allow paragraph. @@ -72,6 +67,10 @@ export default class InsertParagraphCommand extends Command { return; } + if ( attributes ) { + model.schema.setAllowedAttributes( paragraph, attributes, writer ); + } + if ( position.path.length < 2 ) { model.insertContent( paragraph, position ); writer.setSelection( paragraph, 'in' ); @@ -79,26 +78,25 @@ export default class InsertParagraphCommand extends Command { return; } - if ( position.isAtStart && position.isAtEnd ) { - // NOTE: In case when paragraph is empty. - // [] ---> [] - position = writer.createPositionAfter( position.parent as Item ); - } else if ( position.isAtStart && ( position.nodeAfter as Text ).data ) { - // When position is at the start of the line we want to insert paragraph above. - // []foo ---> []foo - position = writer.createPositionFromPath( allowedParent, position.getParentPath() ); - } else if ( position.isAtEnd && ( position.nodeBefore as Text ).data ) { - // When position is at the end of the line we want to insert paragraph after. - // foo[] ---> foo[] + // E.g. + // [] ---> [] + const isInEmptyBlock = position.isAtStart && position.isAtEnd; + + // E.g. + // foo[] ---> foo[] + const isAtEndOfTextBlock = position.isAtEnd && position.nodeBefore?.is( '$text' ); + + // E.g. + // []foo ---> []foo + const isAtStartOfTextBlock = position.isAtStart && position.nodeAfter?.is( '$text' ); + + const canBeChild = model.schema.checkChild( position.parent as Element, paragraph ); + + if ( isInEmptyBlock || isAtEndOfTextBlock ) { position = writer.createPositionAfter( position.parent as Item ); - } else if ( !model.schema.checkChild( position.parent as Element, paragraph ) ) { - // When position is inside the content we want to split it - // fo[]o - // | - // ↓ - // fo - // [] - // o + } else if ( isAtStartOfTextBlock ) { + position = writer.createPositionBefore( position.parent as Item ); + } else if ( !canBeChild ) { position = writer.split( position, allowedParent ).position; } From 4ee16231e4a32ba24bd40ea581c534ccb72f5b5b Mon Sep 17 00:00:00 2001 From: Kuba Niegowski Date: Thu, 6 Jul 2023 16:31:37 +0200 Subject: [PATCH 09/11] Review fixes. --- .../src/insertparagraphcommand.ts | 14 ++++++---- .../tests/insertparagraphcommand.js | 28 +++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts index 0bbba39a24c..6e35e676780 100644 --- a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts +++ b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts @@ -78,24 +78,26 @@ export default class InsertParagraphCommand extends Command { return; } + const positionParent = position.parent as Element; + // E.g. // [] ---> [] - const isInEmptyBlock = position.isAtStart && position.isAtEnd; + const isInEmptyBlock = positionParent.isEmpty; // E.g. // foo[] ---> foo[] - const isAtEndOfTextBlock = position.isAtEnd && position.nodeBefore?.is( '$text' ); + const isAtEndOfTextBlock = position.isAtEnd && !positionParent.isEmpty; // E.g. // []foo ---> []foo - const isAtStartOfTextBlock = position.isAtStart && position.nodeAfter?.is( '$text' ); + const isAtStartOfTextBlock = position.isAtStart && !positionParent.isEmpty; - const canBeChild = model.schema.checkChild( position.parent as Element, paragraph ); + const canBeChild = model.schema.checkChild( positionParent, paragraph ); if ( isInEmptyBlock || isAtEndOfTextBlock ) { - position = writer.createPositionAfter( position.parent as Item ); + position = writer.createPositionAfter( positionParent ); } else if ( isAtStartOfTextBlock ) { - position = writer.createPositionBefore( position.parent as Item ); + position = writer.createPositionBefore( positionParent ); } else if ( !canBeChild ) { position = writer.split( position, allowedParent ).position; } diff --git a/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js b/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js index 8feec9e0a40..03f1ccd2b7c 100644 --- a/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js +++ b/packages/ckeditor5-paragraph/tests/insertparagraphcommand.js @@ -83,6 +83,20 @@ describe( 'InsertParagraphCommand', () => { ); } ); + it( 'should insert paragraph when position is at the end of line with an inline widget', () => { + schema.register( 'inlineWidget', { inheritAllFrom: '$inlineObject' } ); + setData( model, '[]' ); + + command.execute( { + position: model.document.selection.getFirstPosition() + } ); + + expect( getData( model ) ).to.equal( + '' + + '[]' + ); + } ); + it( 'should insert paragraph when position is at the start of line', () => { setData( model, '[]foo' ); @@ -96,6 +110,20 @@ describe( 'InsertParagraphCommand', () => { ); } ); + it( 'should insert paragraph when position is at the start of line with an inline widget', () => { + schema.register( 'inlineWidget', { inheritAllFrom: '$inlineObject' } ); + setData( model, '[]' ); + + command.execute( { + position: model.document.selection.getLastPosition() + } ); + + expect( getData( model ) ).to.equal( + '[]' + + '' + ); + } ); + it( 'should insert paragraph bellow when paragraph is empty', () => { setData( model, '[]' ); From 1b6f19222426da471413af399364925e2b29578c Mon Sep 17 00:00:00 2001 From: Kuba Niegowski Date: Thu, 6 Jul 2023 16:32:35 +0200 Subject: [PATCH 10/11] Removed unused import. --- packages/ckeditor5-paragraph/src/insertparagraphcommand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts b/packages/ckeditor5-paragraph/src/insertparagraphcommand.ts index 6e35e676780..be5780a6e10 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, Item } from '@ckeditor/ckeditor5-engine'; +import type { Element, Position } from '@ckeditor/ckeditor5-engine'; /** * The insert paragraph command. It inserts a new paragraph at a specific From e613d399c8ca52dddcf3470608686c73f7663010 Mon Sep 17 00:00:00 2001 From: Kuba Niegowski Date: Thu, 6 Jul 2023 17:22:37 +0200 Subject: [PATCH 11/11] Updated tests in WTA. --- .../widgettypearound/widgettypearound.js | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/packages/ckeditor5-widget/tests/widgettypearound/widgettypearound.js b/packages/ckeditor5-widget/tests/widgettypearound/widgettypearound.js index 61bc0994a56..2fa790bccf6 100644 --- a/packages/ckeditor5-widget/tests/widgettypearound/widgettypearound.js +++ b/packages/ckeditor5-widget/tests/widgettypearound/widgettypearound.js @@ -1053,7 +1053,7 @@ describe( 'WidgetTypeAround', () => { expect( modelSelection.getAttribute( TYPE_AROUND_SELECTION_ATTRIBUTE ) ).to.be.undefined; } ); - it( 'should split ancestors to find a place that allows a widget', () => { + it( 'should split ancestors to find a place that allows a widget (no content after widget)', () => { model.schema.register( 'allowP', { inheritAllFrom: '$block' } ); @@ -1083,7 +1083,41 @@ describe( 'WidgetTypeAround', () => { '' + '' + '[]' + - '' + + '' + ); + } ); + + it( 'should split ancestors to find a place that allows a widget (with content after widget)', () => { + model.schema.register( 'allowP', { + inheritAllFrom: '$block' + } ); + model.schema.register( 'disallowP', { + inheritAllFrom: '$block', + allowIn: [ 'allowP' ] + } ); + model.schema.extend( 'blockWidget', { + allowIn: [ 'allowP', 'disallowP' ] + } ); + model.schema.extend( 'paragraph', { + allowIn: [ 'allowP' ] + } ); + + editor.conversion.for( 'downcast' ).elementToElement( { model: 'allowP', view: 'allowP' } ); + editor.conversion.for( 'downcast' ).elementToElement( { model: 'disallowP', view: 'disallowP' } ); + + setModelData( model, + '' + + '[]' + + '' + ); + + fireEnter(); + + expect( getModelData( model ) ).to.equal( + '' + + '' + + '[]' + + '' + '' ); } );