diff --git a/src/controller/insertcontent.js b/src/controller/insertcontent.js index 52a2e9902..c5ba075aa 100644 --- a/src/controller/insertcontent.js +++ b/src/controller/insertcontent.js @@ -354,6 +354,11 @@ class Insertion { } if ( this._checkIsAllowed( node, [ paragraph ] ) ) { + // Prevent having same node in two parents. + if ( node.parent ) { + node.remove(); + } + paragraph.appendChildren( node ); this._handleNode( paragraph, context ); } diff --git a/src/view/writer.js b/src/view/writer.js index ec16ee8b0..b350f5cf1 100644 --- a/src/view/writer.js +++ b/src/view/writer.js @@ -212,7 +212,7 @@ export function mergeAttributes( position ) { else if ( nodeBefore.is( 'attributeElement' ) && nodeAfter.is( 'attributeElement' ) && nodeBefore.isSimilar( nodeAfter ) ) { // Move all children nodes from node placed after selection and remove that node. const count = nodeBefore.childCount; - nodeBefore.appendChildren( nodeAfter.getChildren() ); + nodeBefore.appendChildren( nodeAfter.removeChildren( 0, nodeAfter.childCount ) ); nodeAfter.remove(); // New position is located inside the first node, before new nodes. @@ -831,8 +831,8 @@ function unwrapChildren( parent, startOffset, endOffset, attribute ) { // If attributes are the similar, then unwrap. if ( child.isSimilar( attribute ) ) { - const unwrapped = child.getChildren(); const count = child.childCount; + const unwrapped = child.removeChildren( 0, count ); // Replace wrapper element with its children child.remove(); @@ -904,7 +904,7 @@ function wrapChildren( parent, startOffset, endOffset, attribute ) { // Clone attribute. const newAttribute = attribute.clone(); - // Wrap current node with new attribute; + // Wrap current node with new attribute. child.remove(); newAttribute.appendChildren( child ); parent.insertChildren( i, newAttribute ); diff --git a/tests/controller/insertcontent.js b/tests/controller/insertcontent.js index 64d0373af..476a31135 100644 --- a/tests/controller/insertcontent.js +++ b/tests/controller/insertcontent.js @@ -294,6 +294,16 @@ describe( 'DataController', () => { expect( getData( doc ) ).to.equal( 'bar[]' ); } ); + it( 'autoparagraphs when just text is inserted', () => { + doc.schema.disallow( { name: '$text', inside: 'blockWidget' } ); + doc.schema.allow( { name: 'paragraph', inside: 'blockWidget' } ); + + setData( doc, '[]' ); + insertContent( dataController, new Text( 'foo' ), doc.selection ); + + expect( getData( doc ) ).to.equal( 'foo[]' ); + } ); + describe( 'block to block handling', () => { it( 'inserts one paragraph', () => { setData( doc, 'f[]oo' ); diff --git a/tests/view/writer/mergeattributes.js b/tests/view/writer/mergeattributes.js index caa908fe5..d71d36a3b 100644 --- a/tests/view/writer/mergeattributes.js +++ b/tests/view/writer/mergeattributes.js @@ -143,5 +143,18 @@ describe( 'writer', () => { '[]' ); } ); + + it( 'should correctly move nodes when merging', () => { + // Check if nodes has been removed from old parent before adding to new parent. + const { view, selection } = parse( + 'foo[]bar' + ); + + const b = view.getChild( 1 ); + + mergeAttributes( selection.getFirstPosition() ); + + expect( b.childCount ).to.equal( 0 ); + } ); } ); } ); diff --git a/tests/view/writer/unwrap.js b/tests/view/writer/unwrap.js index 217c526a5..aab15373f 100644 --- a/tests/view/writer/unwrap.js +++ b/tests/view/writer/unwrap.js @@ -83,6 +83,16 @@ describe( 'writer', () => { } ).to.throw( CKEditorError, 'view-writer-invalid-range-container' ); } ); + it( 'should correctly move unwrapped nodes', () => { + // Check if nodes has been removed from old parent before adding to new parent. + const { view, selection } = parse( '[x]' ); + const b = view.getChild( 0 ); + + unwrap( selection.getFirstRange(), parse( '' ) ); + + expect( b.childCount ).to.equal( 0 ); + } ); + it( 'should unwrap single node', () => { test( '[foobar]',