Răsfoiți Sursa

Changed: Merging empty paragraphs should result in one paragraph.

Maciej Gołaszewski 7 ani în urmă
părinte
comite
4fdeac1710

+ 29 - 3
packages/ckeditor5-table/src/commands/mergecellcommand.js

@@ -97,9 +97,7 @@ export default class MergeCellCommand extends Command {
 			// Cache the parent of cell to remove for later check.
 			const removedTableCellRow = cellToRemove.parent;
 
-			// Remove table cell and merge it contents with merged cell.
-			writer.move( Range.createIn( cellToRemove ), Position.createAt( cellToExpand, 'end' ) );
-			writer.remove( cellToRemove );
+			mergeTableCells( cellToRemove, cellToExpand, writer );
 
 			const spanAttribute = this.isHorizontal ? 'colspan' : 'rowspan';
 			const cellSpan = parseInt( tableCell.getAttribute( spanAttribute ) || 1 );
@@ -254,3 +252,31 @@ function removeEmptyRow( removedTableCellRow, writer ) {
 
 	writer.remove( removedTableCellRow );
 }
+
+// Merges two table cells - will ensure that after merging cells with empty paragraph the result table cell will only have one paragraph.
+// If one of the merged table cell is empty the merged table cell will have contents of the non-empty table cell.
+// If both are empty the merged table cell will have only one empty paragraph.
+//
+// @param {module:engine/model/element~Element} cellToRemove
+// @param {module:engine/model/element~Element} cellToExpand
+// @param {module:engine/model/writer~Writer} writer
+function mergeTableCells( cellToRemove, cellToExpand, writer ) {
+	if ( !isEmpty( cellToRemove ) ) {
+		if ( isEmpty( cellToExpand ) ) {
+			writer.remove( Range.createIn( cellToExpand ) );
+		}
+
+		writer.move( Range.createIn( cellToRemove ), Position.createAt( cellToExpand, 'end' ) );
+	}
+
+	// Remove merged table cell.
+	writer.remove( cellToRemove );
+}
+
+// Checks if passed table cell contains empty paragraph.
+//
+// @param {module:engine/model/element~Element} tableCell
+// @returns {Boolean}
+function isEmpty( tableCell ) {
+	return tableCell.childCount == 1 && tableCell.getChild( 0 ).is( 'paragraph' ) && tableCell.getChild( 0 ).isEmpty;
+}

+ 232 - 0
packages/ckeditor5-table/tests/commands/mergecellcommand.js

@@ -155,6 +155,60 @@ describe( 'MergeCellCommand', () => {
 					[ { colspan: 2, contents: '<paragraph>[00</paragraph><paragraph>01]</paragraph>' } ]
 				] ) );
 			} );
+
+			it( 'should result in single empty paragraph if both cells are empty', () => {
+				setData( model, modelTable( [
+					[ '[]', '' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { colspan: 2, contents: '<paragraph>[]</paragraph>' } ]
+				] ) );
+			} );
+
+			it( 'should result in single paragraph (other cell is empty)', () => {
+				setData( model, modelTable( [
+					[ 'foo[]', '' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ]
+				] ) );
+			} );
+
+			it( 'should result in single paragraph (selection cell is empty)', () => {
+				setData( model, modelTable( [
+					[ '[]', 'foo' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ]
+				] ) );
+			} );
+
+			it( 'should not merge other empty blocks to single block', () => {
+				model.schema.register( 'block', {
+					allowWhere: '$block',
+					allowContentOf: '$block',
+					isBlock: true
+				} );
+
+				setData( model, modelTable( [
+					[ '<block>[]</block>', '<block></block>' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { colspan: 2, contents: '<block>[</block><block>]</block>' } ]
+				] ) );
+			} );
 		} );
 	} );
 
@@ -281,6 +335,60 @@ describe( 'MergeCellCommand', () => {
 					[ { colspan: 2, contents: '<paragraph>[00</paragraph><paragraph>01]</paragraph>' } ]
 				] ) );
 			} );
+
+			it( 'should result in single empty paragraph if both cells are empty', () => {
+				setData( model, modelTable( [
+					[ '', '[]' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { colspan: 2, contents: '<paragraph>[]</paragraph>' } ]
+				] ) );
+			} );
+
+			it( 'should result in single paragraph (other cell is empty)', () => {
+				setData( model, modelTable( [
+					[ '', 'foo[]' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ]
+				] ) );
+			} );
+
+			it( 'should result in single paragraph (selection cell is empty)', () => {
+				setData( model, modelTable( [
+					[ 'foo', '[]' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ]
+				] ) );
+			} );
+
+			it( 'should not merge other empty blocks to single block', () => {
+				model.schema.register( 'block', {
+					allowWhere: '$block',
+					allowContentOf: '$block',
+					isBlock: true
+				} );
+
+				setData( model, modelTable( [
+					[ '<block></block>', '<block>[]</block>' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { colspan: 2, contents: '<block>[</block><block>]</block>' } ]
+				] ) );
+			} );
 		} );
 	} );
 
@@ -421,6 +529,68 @@ describe( 'MergeCellCommand', () => {
 				] ) );
 			} );
 
+			it( 'should result in single empty paragraph if both cells are empty', () => {
+				setData( model, modelTable( [
+					[ '[]', '' ],
+					[ '', '' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { rowspan: 2, contents: '[]' }, '' ],
+					[ '' ]
+				] ) );
+			} );
+
+			it( 'should result in single paragraph (other cell is empty)', () => {
+				setData( model, modelTable( [
+					[ 'foo[]', '' ],
+					[ '', '' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { rowspan: 2, contents: '[foo]' }, '' ],
+					[ '' ]
+				] ) );
+			} );
+
+			it( 'should result in single paragraph (selection cell is empty)', () => {
+				setData( model, modelTable( [
+					[ '[]', '' ],
+					[ 'foo', '' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { rowspan: 2, contents: '[foo]' }, '' ],
+					[ '' ]
+				] ) );
+			} );
+
+			it( 'should not merge other empty blocks to single block', () => {
+				model.schema.register( 'block', {
+					allowWhere: '$block',
+					allowContentOf: '$block',
+					isBlock: true
+				} );
+
+				setData( model, modelTable( [
+					[ '<block>[]</block>', '' ],
+					[ '<block></block>', '' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { rowspan: 2, contents: '<block>[</block><block>]</block>' }, '' ],
+					[ '' ]
+				] ) );
+			} );
+
 			it( 'should remove empty row if merging table cells ', () => {
 				setData( model, modelTable( [
 					[ { rowspan: 2, contents: '00' }, '01[]', { rowspan: 3, contents: '02' } ],
@@ -595,6 +765,68 @@ describe( 'MergeCellCommand', () => {
 				] ) );
 			} );
 
+			it( 'should result in single empty paragraph if both cells are empty', () => {
+				setData( model, modelTable( [
+					[ '', '' ],
+					[ '[]', '' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { rowspan: 2, contents: '[]' }, '' ],
+					[ '' ]
+				] ) );
+			} );
+
+			it( 'should result in single paragraph (other cell is empty)', () => {
+				setData( model, modelTable( [
+					[ '', '' ],
+					[ 'foo[]', '' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { rowspan: 2, contents: '[foo]' }, '' ],
+					[ '' ]
+				] ) );
+			} );
+
+			it( 'should result in single paragraph (selection cell is empty)', () => {
+				setData( model, modelTable( [
+					[ 'foo', '' ],
+					[ '[]', '' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { rowspan: 2, contents: '[foo]' }, '' ],
+					[ '' ]
+				] ) );
+			} );
+
+			it( 'should not merge other empty blocks to single block', () => {
+				model.schema.register( 'block', {
+					allowWhere: '$block',
+					allowContentOf: '$block',
+					isBlock: true
+				} );
+
+				setData( model, modelTable( [
+					[ '<block></block>', '' ],
+					[ '<block>[]</block>', '' ]
+				] ) );
+
+				command.execute();
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ { rowspan: 2, contents: '<block>[</block><block>]</block>' }, '' ],
+					[ '' ]
+				] ) );
+			} );
+
 			it( 'should properly merge cells in rows with spaned cells', () => {
 				setData( model, modelTable( [
 					[ { rowspan: 3, contents: '00' }, '11', '12', '13' ],