Browse Source

Merge pull request #7362 from ckeditor/i/6609

Fix (table): Removing empty rows will no longer produce an invalid table model in certain scenarios. Closes #6609.
Maciej 5 years ago
parent
commit
11d69fc808

+ 5 - 6
packages/ckeditor5-table/src/commands/mergecellcommand.js

@@ -11,6 +11,7 @@ import Command from '@ckeditor/ckeditor5-core/src/command';
 import TableWalker from '../tablewalker';
 import { getTableCellsContainingSelection } from '../utils/selection';
 import { findAncestor, isHeadingColumnCell } from '../utils/common';
+import { removeEmptyRowsColumns } from '../utils/structure';
 
 /**
  * The merge cell command.
@@ -104,13 +105,11 @@ export default class MergeCellCommand extends Command {
 			writer.setAttribute( spanAttribute, cellSpan + cellToMergeSpan, cellToExpand );
 			writer.setSelection( writer.createRangeIn( cellToExpand ) );
 
-			// Remove empty row after merging.
-			if ( !removedTableCellRow.childCount ) {
-				const tableUtils = this.editor.plugins.get( 'TableUtils' );
-				const table = findAncestor( 'table', removedTableCellRow );
+			const tableUtils = this.editor.plugins.get( 'TableUtils' );
+			const table = findAncestor( 'table', removedTableCellRow );
 
-				tableUtils.removeRows( table, { at: removedTableCellRow.index, batch: writer.batch } );
-			}
+			// Remove empty rows and columns after merging.
+			removeEmptyRowsColumns( table, tableUtils, writer.batch );
 		} );
 	}
 

+ 4 - 12
packages/ckeditor5-table/src/commands/mergecellscommand.js

@@ -11,6 +11,7 @@ import Command from '@ckeditor/ckeditor5-core/src/command';
 import TableUtils from '../tableutils';
 import { getSelectedTableCells, isSelectionRectangular } from '../utils/selection';
 import { findAncestor, updateNumericAttribute } from '../utils/common';
+import { removeEmptyRowsColumns } from '../utils/structure';
 
 /**
  * The merge cells command.
@@ -57,23 +58,14 @@ export default class MergeCellsCommand extends Command {
 			updateNumericAttribute( 'colspan', mergeWidth, firstTableCell, writer );
 			updateNumericAttribute( 'rowspan', mergeHeight, firstTableCell, writer );
 
-			const emptyRowsIndexes = [];
-
 			for ( const tableCell of selectedTableCells ) {
-				const tableRow = tableCell.parent;
-
 				mergeTableCells( tableCell, firstTableCell, writer );
-
-				if ( !tableRow.childCount ) {
-					emptyRowsIndexes.push( tableRow.index );
-				}
 			}
 
-			if ( emptyRowsIndexes.length ) {
-				const table = findAncestor( 'table', firstTableCell );
+			const table = findAncestor( 'table', firstTableCell );
 
-				emptyRowsIndexes.reverse().forEach( row => tableUtils.removeRows( table, { at: row, batch: writer.batch } ) );
-			}
+			// Remove rows and columns that become empty (have no anchored cells).
+			removeEmptyRowsColumns( table, tableUtils, writer.batch );
 
 			writer.setSelection( firstTableCell, 'in' );
 		} );

+ 7 - 12
packages/ckeditor5-table/src/tableutils.js

@@ -11,6 +11,7 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 
 import TableWalker from './tablewalker';
 import { createEmptyTableCell, updateNumericAttribute } from './utils/common';
+import { removeEmptyColumns, removeEmptyRows } from './utils/structure';
 
 /**
  * The table utilities plugin.
@@ -336,7 +337,10 @@ export default class TableUtils extends Plugin {
 				updateNumericAttribute( 'rowspan', rowspan, cell, writer );
 			}
 
-			// 2d. Adjust heading rows if removed rows were in a heading section.
+			// 2d. Remove empty columns (without anchored cells) if there are any.
+			removeEmptyColumns( table, this );
+
+			// 2e. Adjust heading rows if removed rows were in a heading section.
 			updateHeadingRows( table, first, last, model, batch );
 		} );
 	}
@@ -379,29 +383,20 @@ export default class TableUtils extends Plugin {
 		model.change( writer => {
 			adjustHeadingColumns( table, { first, last }, writer );
 
-			const emptyRowsIndexes = [];
-
 			for ( let removedColumnIndex = last; removedColumnIndex >= first; removedColumnIndex-- ) {
 				for ( const { cell, column, cellWidth } of [ ...new TableWalker( table ) ] ) {
 					// If colspaned cell overlaps removed column decrease its span.
 					if ( column <= removedColumnIndex && cellWidth > 1 && column + cellWidth > removedColumnIndex ) {
 						updateNumericAttribute( 'colspan', cellWidth - 1, cell, writer );
 					} else if ( column === removedColumnIndex ) {
-						const cellRow = cell.parent;
-
 						// The cell in removed column has colspan of 1.
 						writer.remove( cell );
-
-						// If the cell was the last one in the row, get rid of the entire row.
-						// https://github.com/ckeditor/ckeditor5/issues/6429
-						if ( !cellRow.childCount ) {
-							emptyRowsIndexes.push( cellRow.index );
-						}
 					}
 				}
 			}
 
-			emptyRowsIndexes.reverse().forEach( row => this.removeRows( table, { at: row, batch: writer.batch } ) );
+			// Remove empty rows that could appear after removing columns.
+			removeEmptyRows( table, this, writer.batch );
 		} );
 	}
 

+ 133 - 0
packages/ckeditor5-table/src/utils/structure.js

@@ -305,3 +305,136 @@ function addHeadingsToCroppedTable( croppedTable, sourceTable, startRow, startCo
 		updateNumericAttribute( 'headingColumns', headingColumnsInCrop, croppedTable, writer, 0 );
 	}
 }
+
+/**
+ * Removes columns that have no cells anchored.
+ *
+ * In table below:
+ *
+ *     +----+----+----+----+----+----+----+
+ *     | 00 | 01      | 03 | 04      | 06 |
+ *     +----+----+----+----+         +----+
+ *     | 10 | 11      | 13 |         | 16 |
+ *     +----+----+----+----+----+----+----+
+ *     | 20 | 21      | 23 | 24      | 26 |
+ *     +----+----+----+----+----+----+----+
+ *                  ^--- empty ---^
+ *
+ * Will remove columns 2 and 5.
+ *
+ * **Note:** This is a low-level helper method for clearing invalid model state when doing table modifications.
+ * To remove a column from a table use {@link module:table/tableutils~TableUtils#removeColumns `TableUtils.removeColumns()`}.
+ *
+ * @protected
+ * @param {module:engine/model/element~Element} table
+ * @param {module:table/tableutils~TableUtils} tableUtils
+ * @return {Boolean} True if removed some columns.
+ */
+export function removeEmptyColumns( table, tableUtils ) {
+	const width = tableUtils.getColumns( table );
+	const columnsMap = new Array( width ).fill( 0 );
+
+	for ( const { column } of new TableWalker( table ) ) {
+		columnsMap[ column ]++;
+	}
+
+	const emptyColumns = columnsMap.reduce( ( result, cellsCount, column ) => {
+		return cellsCount ? result : [ ...result, column ];
+	}, [] );
+
+	// @if CK_DEBUG_TABLE // emptyColumns.length > 0 && console.log( `Removing empty columns: ${ emptyColumns.join( ', ' ) }.` );
+
+	emptyColumns.reverse().forEach( column => {
+		tableUtils.removeColumns( table, { at: column } );
+	} );
+
+	return emptyColumns.length > 0;
+}
+
+/**
+ * Removes rows that have no cells anchored.
+ *
+ * In table below:
+ *
+ *     +----+----+----+
+ *     | 00 | 01 | 02 |
+ *     +----+----+----+
+ *     | 10 | 11 | 12 |
+ *     +    +    +    +
+ *     |    |    |    | <-- empty
+ *     +----+----+----+
+ *     | 30 | 31 | 32 |
+ *     +----+----+----+
+ *     | 40      | 42 |
+ *     +         +    +
+ *     |         |    | <-- empty
+ *     +----+----+----+
+ *     | 60 | 61 | 62 |
+ *     +----+----+----+
+ *
+ * Will remove rows 2 and 5.
+ *
+ * **Note:** This is a low-level helper method for clearing invalid model state when doing table modifications.
+ * To remove a row from a table use {@link module:table/tableutils~TableUtils#removeRows `TableUtils.removeRows()`}.
+ *
+ * @protected
+ * @param {module:engine/model/element~Element} table
+ * @param {module:table/tableutils~TableUtils} tableUtils
+ * @param {module:engine/model/batch~Batch|null} [batch] Batch that should be used for removing empty rows.
+ * @return {Boolean} True if removed some rows.
+ */
+export function removeEmptyRows( table, tableUtils, batch ) {
+	const emptyRows = [];
+
+	for ( let rowIndex = 0; rowIndex < table.childCount; rowIndex++ ) {
+		const tableRow = table.getChild( rowIndex );
+
+		if ( tableRow.isEmpty ) {
+			emptyRows.push( rowIndex );
+		}
+	}
+
+	// @if CK_DEBUG_TABLE // emptyRows.length > 0 && console.log( `Removing empty rows: ${ emptyRows.join( ', ' ) }.` );
+
+	emptyRows.reverse().forEach( row => {
+		tableUtils.removeRows( table, { at: row, batch } );
+	} );
+
+	return emptyRows.length > 0;
+}
+
+/**
+ * Removes rows and columns that have no cells anchored.
+ *
+ * In table below:
+ *
+ *     +----+----+----+----+
+ *     | 00      | 02      |
+ *     +----+----+         +
+ *     | 10      |         |
+ *     +----+----+----+----+
+ *     | 20      | 22 | 23 |
+ *     +         +    +    +
+ *     |         |    |    | <-- empty row
+ *     +----+----+----+----+
+ *             ^--- empty column
+ *
+ * Will remove row 3 and column 1.
+ *
+ * **Note:** This is a low-level helper method for clearing invalid model state when doing table modifications.
+ * To remove a rows from a table use {@link module:table/tableutils~TableUtils#removeRows `TableUtils.removeRows()`} and
+ * {@link module:table/tableutils~TableUtils#removeColumns `TableUtils.removeColumns()`} to remove a column.
+ *
+ * @protected
+ * @param {module:engine/model/element~Element} table
+ * @param {module:table/tableutils~TableUtils} tableUtils
+ * @param {module:engine/model/batch~Batch|null} [batch] Batch that should be used for removing empty rows.
+ */
+export function removeEmptyRowsColumns( table, tableUtils, batch ) {
+	const removedColumns = removeEmptyColumns( table, tableUtils );
+
+	// If there was some columns removed then cleaning empty rows was already triggered.
+	if ( !removedColumns ) {
+		removeEmptyRows( table, tableUtils, batch );
+	}
+}

+ 62 - 18
packages/ckeditor5-table/tests/commands/mergecellcommand.js

@@ -189,49 +189,69 @@ describe( 'MergeCellCommand', () => {
 		describe( 'execute()', () => {
 			it( 'should merge table cells', () => {
 				setData( model, modelTable( [
+					[ '[]00', '01' ],
+					[ '10', '11' ]
+				] ) );
+
+				command.execute();
+
+				assertEqualMarkup( getData( model ), modelTable( [
+					[ { colspan: 2, contents: '<paragraph>[00</paragraph><paragraph>01]</paragraph>' } ],
+					[ '10', '11' ]
+				] ) );
+			} );
+
+			it( 'should merge table cells and remove empty columns', () => {
+				setData( model, modelTable( [
 					[ '[]00', '01' ]
 				] ) );
 
 				command.execute();
 
 				assertEqualMarkup( getData( model ), modelTable( [
-					[ { colspan: 2, contents: '<paragraph>[00</paragraph><paragraph>01]</paragraph>' } ]
+					[ '<paragraph>[00</paragraph><paragraph>01]</paragraph>' ]
 				] ) );
 			} );
 
 			it( 'should result in single empty paragraph if both cells are empty', () => {
 				setData( model, modelTable( [
-					[ '[]', '' ]
+					[ '[]', '' ],
+					[ '10', '11' ]
 				] ) );
 
 				command.execute();
 
 				assertEqualMarkup( getData( model ), modelTable( [
-					[ { colspan: 2, contents: '<paragraph>[]</paragraph>' } ]
+					[ { colspan: 2, contents: '<paragraph>[]</paragraph>' } ],
+					[ '10', '11' ]
 				] ) );
 			} );
 
 			it( 'should result in single paragraph (other cell is empty)', () => {
 				setData( model, modelTable( [
-					[ 'foo[]', '' ]
+					[ 'foo[]', '' ],
+					[ '10', '11' ]
 				] ) );
 
 				command.execute();
 
 				assertEqualMarkup( getData( model ), modelTable( [
-					[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ]
+					[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ],
+					[ '10', '11' ]
 				] ) );
 			} );
 
 			it( 'should result in single paragraph (selection cell is empty)', () => {
 				setData( model, modelTable( [
-					[ '[]', 'foo' ]
+					[ '[]', 'foo' ],
+					[ '10', '11' ]
 				] ) );
 
 				command.execute();
 
 				assertEqualMarkup( getData( model ), modelTable( [
-					[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ]
+					[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ],
+					[ '10', '11' ]
 				] ) );
 			} );
 
@@ -243,13 +263,15 @@ describe( 'MergeCellCommand', () => {
 				} );
 
 				setData( model, modelTable( [
-					[ '<block>[]</block>', '<block></block>' ]
+					[ '<block>[]</block>', '<block></block>' ],
+					[ '10', '11' ]
 				] ) );
 
 				command.execute();
 
 				assertEqualMarkup( getData( model ), modelTable( [
-					[ { colspan: 2, contents: '<block>[</block><block>]</block>' } ]
+					[ { colspan: 2, contents: '<block>[</block><block>]</block>' } ],
+					[ '10', '11' ]
 				] ) );
 			} );
 		} );
@@ -403,49 +425,69 @@ describe( 'MergeCellCommand', () => {
 		describe( 'execute()', () => {
 			it( 'should merge table cells', () => {
 				setData( model, modelTable( [
+					[ '00', '[]01' ],
+					[ '10', '11' ]
+				] ) );
+
+				command.execute();
+
+				assertEqualMarkup( getData( model ), modelTable( [
+					[ { colspan: 2, contents: '<paragraph>[00</paragraph><paragraph>01]</paragraph>' } ],
+					[ '10', '11' ]
+				] ) );
+			} );
+
+			it( 'should merge table cells and remove empty columns', () => {
+				setData( model, modelTable( [
 					[ '00', '[]01' ]
 				] ) );
 
 				command.execute();
 
 				assertEqualMarkup( getData( model ), modelTable( [
-					[ { colspan: 2, contents: '<paragraph>[00</paragraph><paragraph>01]</paragraph>' } ]
+					[ '<paragraph>[00</paragraph><paragraph>01]</paragraph>' ]
 				] ) );
 			} );
 
 			it( 'should result in single empty paragraph if both cells are empty', () => {
 				setData( model, modelTable( [
-					[ '', '[]' ]
+					[ '', '[]' ],
+					[ '10', '11' ]
 				] ) );
 
 				command.execute();
 
 				assertEqualMarkup( getData( model ), modelTable( [
-					[ { colspan: 2, contents: '<paragraph>[]</paragraph>' } ]
+					[ { colspan: 2, contents: '<paragraph>[]</paragraph>' } ],
+					[ '10', '11' ]
 				] ) );
 			} );
 
 			it( 'should result in single paragraph (other cell is empty)', () => {
 				setData( model, modelTable( [
-					[ '', 'foo[]' ]
+					[ '', 'foo[]' ],
+					[ '10', '11' ]
 				] ) );
 
 				command.execute();
 
 				assertEqualMarkup( getData( model ), modelTable( [
-					[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ]
+					[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ],
+					[ '10', '11' ]
 				] ) );
 			} );
 
 			it( 'should result in single paragraph (selection cell is empty)', () => {
 				setData( model, modelTable( [
-					[ 'foo', '[]' ]
+					[ 'foo', '[]' ],
+					[ '10', '11' ]
 				] ) );
 
 				command.execute();
 
 				assertEqualMarkup( getData( model ), modelTable( [
-					[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ]
+					[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ],
+					[ '10', '11' ]
 				] ) );
 			} );
 
@@ -457,13 +499,15 @@ describe( 'MergeCellCommand', () => {
 				} );
 
 				setData( model, modelTable( [
-					[ '<block></block>', '<block>[]</block>' ]
+					[ '<block></block>', '<block>[]</block>' ],
+					[ '10', '11' ]
 				] ) );
 
 				command.execute();
 
 				assertEqualMarkup( getData( model ), modelTable( [
-					[ { colspan: 2, contents: '<block>[</block><block>]</block>' } ]
+					[ { colspan: 2, contents: '<block>[</block><block>]</block>' } ],
+					[ '10', '11' ]
 				] ) );
 			} );
 		} );

+ 54 - 11
packages/ckeditor5-table/tests/commands/mergecellscommand.js

@@ -312,6 +312,25 @@ describe( 'MergeCellsCommand', () => {
 	describe( 'execute()', () => {
 		it( 'should merge simple table cell selection', () => {
 			setData( model, modelTable( [
+				[ '[]00', '01' ],
+				[ '10', '11' ]
+			] ) );
+
+			tableSelection.setCellSelection(
+				root.getNodeByPath( [ 0, 0, 0 ] ),
+				root.getNodeByPath( [ 0, 0, 1 ] )
+			);
+
+			command.execute();
+
+			assertEqualMarkup( getData( model ), modelTable( [
+				[ { colspan: 2, contents: '<paragraph>[00</paragraph><paragraph>01]</paragraph>' } ],
+				[ '10', '11' ]
+			] ) );
+		} );
+
+		it( 'should merge simple table cell selection and remove empty columns', () => {
+			setData( model, modelTable( [
 				[ '[]00', '01' ]
 			] ) );
 
@@ -323,7 +342,7 @@ describe( 'MergeCellsCommand', () => {
 			command.execute();
 
 			assertEqualMarkup( getData( model ), modelTable( [
-				[ { colspan: 2, contents: '<paragraph>[00</paragraph><paragraph>01]</paragraph>' } ]
+				[ '<paragraph>[00</paragraph><paragraph>01]</paragraph>' ]
 			] ) );
 		} );
 
@@ -403,9 +422,17 @@ describe( 'MergeCellsCommand', () => {
 		} );
 
 		it( 'should merge table cells - extend colspan attribute', () => {
+			// +----+----+----+----+
+			// | 00      | 02 | 03 |
+			// +----+----+----+----+
+			// | 10 | 11 | 12 | 13 |
+			// +----+----+----+----+
+			// | 20 | 21 | 22 | 23 |
+			// +----+----+----+----+
 			setData( model, modelTable( [
 				[ { colspan: 2, contents: '00' }, '02', '03' ],
-				[ '10', '11', '12', '13' ]
+				[ '10', '11', '12', '13' ],
+				[ '20', '21', '22', '23' ]
 			] ) );
 
 			selectNodes( [
@@ -415,6 +442,13 @@ describe( 'MergeCellsCommand', () => {
 
 			command.execute();
 
+			// +----+----+----+----+
+			// |              | 03 |
+			// +   (merged)   +----+
+			// |              | 13 |
+			// +----+----+----+----+
+			// | 20 | 21 | 22 | 23 |
+			// +----+----+----+----+
 			assertEqualMarkup( getData( model ), modelTable( [
 				[ {
 					colspan: 3,
@@ -425,13 +459,15 @@ describe( 'MergeCellsCommand', () => {
 						'<paragraph>11</paragraph>' +
 						'<paragraph>12]</paragraph>'
 				}, '03' ],
-				[ '13' ]
+				[ '13' ],
+				[ '20', '21', '22', '23' ]
 			] ) );
 		} );
 
 		it( 'should merge to a single paragraph - every cell is empty', () => {
 			setData( model, modelTable( [
-				[ '[]', '' ]
+				[ '[]', '' ],
+				[ '10', '11' ]
 			] ) );
 
 			selectNodes( [ [ 0, 0, 0 ], [ 0, 0, 1 ] ] );
@@ -439,13 +475,15 @@ describe( 'MergeCellsCommand', () => {
 			command.execute();
 
 			assertEqualMarkup( getData( model ), modelTable( [
-				[ { colspan: 2, contents: '<paragraph>[]</paragraph>' } ]
+				[ { colspan: 2, contents: '<paragraph>[]</paragraph>' } ],
+				[ '10', '11' ]
 			] ) );
 		} );
 
 		it( 'should merge to a single paragraph - merged cell is empty', () => {
 			setData( model, modelTable( [
-				[ 'foo', '' ]
+				[ 'foo', '' ],
+				[ '10', '11' ]
 			] ) );
 
 			selectNodes( [ [ 0, 0, 0 ], [ 0, 0, 1 ] ] );
@@ -453,13 +491,15 @@ describe( 'MergeCellsCommand', () => {
 			command.execute();
 
 			assertEqualMarkup( getData( model ), modelTable( [
-				[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ]
+				[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ],
+				[ '10', '11' ]
 			] ) );
 		} );
 
 		it( 'should merge to a single paragraph - cell to which others are merged is empty', () => {
 			setData( model, modelTable( [
-				[ '', 'foo' ]
+				[ '', 'foo' ],
+				[ '10', '11' ]
 			] ) );
 
 			selectNodes( [ [ 0, 0, 0 ], [ 0, 0, 1 ] ] );
@@ -467,7 +507,8 @@ describe( 'MergeCellsCommand', () => {
 			command.execute();
 
 			assertEqualMarkup( getData( model ), modelTable( [
-				[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ]
+				[ { colspan: 2, contents: '<paragraph>[foo]</paragraph>' } ],
+				[ '10', '11' ]
 			] ) );
 		} );
 
@@ -479,7 +520,8 @@ describe( 'MergeCellsCommand', () => {
 			} );
 
 			setData( model, modelTable( [
-				[ '<block>[]</block>', '<block></block>' ]
+				[ '<block>[]</block>', '<block></block>' ],
+				[ '10', '11' ]
 			] ) );
 
 			selectNodes( [ [ 0, 0, 0 ], [ 0, 0, 1 ] ] );
@@ -487,7 +529,8 @@ describe( 'MergeCellsCommand', () => {
 			command.execute();
 
 			assertEqualMarkup( getData( model ), modelTable( [
-				[ { colspan: 2, contents: '<block>[</block><block>]</block>' } ]
+				[ { colspan: 2, contents: '<block>[</block><block>]</block>' } ],
+				[ '10', '11' ]
 			] ) );
 		} );
 

+ 13 - 0
packages/ckeditor5-table/tests/commands/removerowcommand.js

@@ -535,5 +535,18 @@ describe( 'RemoveRowCommand', () => {
 				[ '30', '31', '32' ]
 			] ) );
 		} );
+
+		it( 'should remove empty columns after removing row', () => {
+			setData( model, modelTable( [
+				[ '00', { contents: '01', colspan: 2 } ],
+				[ '[]10', '11', '12' ]
+			] ) );
+
+			command.execute();
+
+			assertEqualMarkup( getData( model ), modelTable( [
+				[ '[]00', '01' ]
+			] ) );
+		} );
 	} );
 } );

+ 12 - 2
packages/ckeditor5-table/tests/manual/tablemocking.html

@@ -25,9 +25,19 @@
 	#input-status {
 		color: hsl( 0, 90%, 50% );
 	}
+	#tools {
+		margin-bottom: 10px;
+	}
+	#tools input[type="checkbox"] {
+		vertical-align: middle;
+	}
+	#tools label > span {
+		vertical-align: middle;
+		display: inline-block;
+	}
 </style>
 
-<div style="margin-bottom: 10px;">
+<div id="tools">
 	<label for="model-data">Table data as expected by <a href="https://github.com/ckeditor/ckeditor5-table/blob/1004f9106110be9de125825afd491a1618b71271/tests/_utils/utils.js#L48">modelTable</a> helper function:</label>
 	<textarea id="model-data">
 [
@@ -43,7 +53,7 @@
 	<button type="button" id="set-model-data">↓ Set model data ↓</button>
 	<button type="button" id="get-model-data">↑ Get model data ↑</button>
 	<button type="button" id="renumber-cells">Renumber cells</button>
-	<label><input type="checkbox" id="use-letters" checked="false">Use letters</label>
+	<label><input type="checkbox" id="use-letters" checked="false"><span>Use letters</span></label>
 
 	<span id="input-status"></span>
 </div>

+ 8 - 3
packages/ckeditor5-table/tests/tableselection-integration.js

@@ -229,7 +229,10 @@ describe( 'TableSelection - integration', () => {
 
 		// See https://github.com/ckeditor/ckeditor5/issues/6634.
 		it( 'works with merge cells command', () => {
-			setModelData( editor.model, modelTable( [ [ '00', '01' ] ] ) );
+			setModelData( editor.model, modelTable( [
+				[ '00', '01' ],
+				[ '10', '11' ]
+			] ) );
 
 			tableSelection.setCellSelection(
 				modelRoot.getNodeByPath( [ 0, 0, 0 ] ),
@@ -239,13 +242,15 @@ describe( 'TableSelection - integration', () => {
 			editor.execute( 'mergeTableCells' );
 
 			assertEqualMarkup( getModelData( model ), modelTable( [
-				[ { colspan: 2, contents: '<paragraph>[00</paragraph><paragraph>01]</paragraph>' } ]
+				[ { colspan: 2, contents: '<paragraph>[00</paragraph><paragraph>01]</paragraph>' } ],
+				[ '10', '11' ]
 			] ) );
 
 			editor.execute( 'undo' );
 
 			assertEqualMarkup( getModelData( model ), modelTable( [
-				[ '[]00', '01' ]
+				[ '[]00', '01' ],
+				[ '10', '11' ]
 			] ) );
 		} );
 	} );