8
0
Piotrek Koszuliński 8 лет назад
Родитель
Сommit
9dcce468f4

+ 16 - 3
packages/ckeditor5-engine/src/controller/deletecontent.js

@@ -98,7 +98,9 @@ function mergeBranches( batch, startPos, endPos ) {
 	startPos = Position.createAfter( startParent );
 	startPos = Position.createAfter( startParent );
 	endPos = Position.createBefore( endParent );
 	endPos = Position.createBefore( endParent );
 
 
-	if ( endParent.childCount > 0 ) {
+	if ( endParent.isEmpty ) {
+		batch.remove( endParent );
+	} else {
 		// At the moment, next startPos is also the position to which the endParent
 		// At the moment, next startPos is also the position to which the endParent
 		// needs to be moved:
 		// needs to be moved:
 		// <a><b>x[]</b></a><c><d>{}y</d></c>
 		// <a><b>x[]</b></a><c><d>{}y</d></c>
@@ -114,8 +116,19 @@ function mergeBranches( batch, startPos, endPos ) {
 		// To then become:
 		// To then become:
 		// <a><b>xy</b>[]</a><c>{}</c>
 		// <a><b>xy</b>[]</a><c>{}</c>
 		batch.merge( startPos );
 		batch.merge( startPos );
-	} else {
-		batch.remove( endParent );
+	}
+
+	// Removes empty end ancestors:
+	// <a>fo[o</a><b><a><c>bar]</c></a></b>
+	// becomes:
+	// <a>fo[]</a><b><a>{}</a></b>
+	// So we can remove <a> and <b>.
+	while ( endPos.parent.isEmpty ) {
+		const parentToRemove = endPos.parent;
+
+		endPos = Position.createBefore( parentToRemove );
+
+		batch.remove( parentToRemove );
 	}
 	}
 
 
 	// Continue merging next level.
 	// Continue merging next level.

+ 52 - 0
packages/ckeditor5-engine/tests/controller/deletecontent.js

@@ -233,6 +233,13 @@ describe( 'DataController', () => {
 				{ merge: true }
 				{ merge: true }
 			);
 			);
 
 
+			test(
+				'merges empty element into the first element',
+				'<heading1>f[oo</heading1><paragraph>bar]</paragraph><paragraph>x</paragraph>',
+				'<heading1>f[]</heading1><paragraph>x</paragraph>',
+				{ merge: true }
+			);
+
 			test(
 			test(
 				'leaves just one element when all selected',
 				'leaves just one element when all selected',
 				'<heading1>[x</heading1><paragraph>foo</paragraph><paragraph>y]</paragraph>',
 				'<heading1>[x</heading1><paragraph>foo</paragraph><paragraph>y]</paragraph>',
@@ -367,6 +374,51 @@ describe( 'DataController', () => {
 					expect( getData( doc ) )
 					expect( getData( doc ) )
 						.to.equal( '<pparent>x<paragraph>foo<pchild>ba[]om</pchild></paragraph></pparent>' );
 						.to.equal( '<pparent>x<paragraph>foo<pchild>ba[]om</pchild></paragraph></pparent>' );
 				} );
 				} );
+
+				test(
+					'merges elements when right end deep nested (in an empty container)',
+					'<paragraph>fo[o</paragraph><paragraph><pchild>bar]</pchild></paragraph>',
+					'<paragraph>fo[]</paragraph>',
+					{ merge: true }
+				);
+
+				test(
+					'merges elements when left end deep nested (in an empty container)',
+					'<paragraph><pchild>[foo</pchild></paragraph><paragraph>b]ar</paragraph><paragraph>x</paragraph>',
+					'<paragraph><pchild>[]ar</pchild></paragraph><paragraph>x</paragraph>',
+					{ merge: true }
+				);
+
+				it( 'merges elements when left end deep nested (3rd level)', () => {
+					const root = doc.getRoot();
+
+					// We need to use the raw API due to https://github.com/ckeditor/ckeditor5-engine/issues/905.
+					// <paragraph>fo[o</paragraph><pparent><paragraph><pchild>bar]</pchild></paragraph></pparent>
+
+					root.appendChildren(
+						new Element( 'paragraph', null, 'foo' )
+					);
+
+					root.appendChildren(
+						new Element( 'pparent', null, [
+							new Element( 'paragraph', null, [
+								new Element( 'pchild', null, 'bar' )
+							] )
+						] )
+					);
+
+					const range = new Range(
+						new Position( doc.getRoot(), [ 0, 2 ] ), // f[oo
+						new Position( doc.getRoot(), [ 1, 0, 0, 3 ] ) // bar]
+					);
+
+					doc.selection.setRanges( [ range ] );
+
+					deleteContent( doc.selection, doc.batch(), { merge: true } );
+
+					expect( getData( doc ) )
+						.to.equal( '<paragraph>fo[]</paragraph>' );
+				} );
 			} );
 			} );
 
 
 			describe( 'with object elements', () => {
 			describe( 'with object elements', () => {