瀏覽代碼

Handle case of pasted table that has has colspans.

Maciej Gołaszewski 5 年之前
父節點
當前提交
07a5e42df8
共有 2 個文件被更改,包括 229 次插入159 次删除
  1. 14 6
      packages/ckeditor5-table/src/tableclipboard.js
  2. 215 153
      packages/ckeditor5-table/tests/tableclipboard.js

+ 14 - 6
packages/ckeditor5-table/src/tableclipboard.js

@@ -11,7 +11,7 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import TableSelection from './tableselection';
 import { getColumnIndexes, getRowIndexes } from './utils';
 import TableWalker from './tablewalker';
-import { findAncestor } from './commands/utils';
+import { findAncestor, updateNumericAttribute } from './commands/utils';
 
 /**
  * This plugin adds support for copying/cutting/pasting fragments of tables.
@@ -134,19 +134,27 @@ export default class TableClipboard extends Plugin {
 						insertionMap.set( `${ row }x${ column }`, cell );
 					}
 
-					for ( const { column, row, cell } of new TableWalker( contentTable, {
-						startRow: rowIndexes.first,
-						endRow: rowIndexes.last
-					} ) ) {
+					const tableMap = [ ...new TableWalker( contentTable, { startRow: rowIndexes.first, endRow: rowIndexes.last } ) ];
+
+					for ( const { column, row, cell } of tableMap ) {
+						// TODO: crete issue for table walker startColumn, endColumn.
 						if ( column < columnIndexes.first || column > columnIndexes.last ) {
 							continue;
 						}
 
 						const toGet = `${ row - rowIndexes.first }x${ column - columnIndexes.first }`;
-
 						const cellToInsert = insertionMap.get( toGet );
+
+						if ( !cellToInsert ) {
+							writer.remove( writer.createRangeOn( cell ) );
+
+							continue;
+						}
+
 						writer.remove( writer.createRangeIn( cell ) );
 
+						updateNumericAttribute( 'colspan', cellToInsert.getAttribute( 'colspan' ), cell, writer, 1 );
+
 						for ( const child of cellToInsert.getChildren() ) {
 							writer.insert( child, cell, 'end' );
 						}

+ 215 - 153
packages/ckeditor5-table/tests/tableclipboard.js

@@ -453,161 +453,223 @@ describe( 'table clipboard', () => {
 					] ) );
 				} );
 
-				it( 'inserts simple table to a simple table fragment - at the beginning of a table', () => {
-					tableSelection._setCellSelection(
-						modelRoot.getNodeByPath( [ 0, 0, 0 ] ),
-						modelRoot.getNodeByPath( [ 0, 1, 1 ] )
-					);
-
-					pasteTable( [
-						[ 'aa', 'ab' ],
-						[ 'ba', 'bb' ]
-					] );
-
-					assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
-						[ 'aa', 'ab', '02', '03' ],
-						[ 'ba', 'bb', '12', '13' ],
-						[ '20', '21', '22', '23' ],
-						[ '30', '31', '32', '33' ]
-					] ) );
-
-					assertSelectedCells( model, [
-						[ 1, 1, 0, 0 ],
-						[ 1, 1, 0, 0 ],
-						[ 0, 0, 0, 0 ],
-						[ 0, 0, 0, 0 ]
-					] );
-				} );
-
-				it( 'inserts simple table to a simple table fragment - at the end of a table', () => {
-					tableSelection._setCellSelection(
-						modelRoot.getNodeByPath( [ 0, 2, 2 ] ),
-						modelRoot.getNodeByPath( [ 0, 3, 3 ] )
-					);
-
-					pasteTable( [
-						[ 'aa', 'ab' ],
-						[ 'ba', 'bb' ]
-					] );
-
-					assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
-						[ '00', '01', '02', '03' ],
-						[ '10', '11', '12', '13' ],
-						[ '20', '21', 'aa', 'ab' ],
-						[ '30', '31', 'ba', 'bb' ]
-					] ) );
-
-					assertSelectedCells( model, [
-						[ 0, 0, 0, 0 ],
-						[ 0, 0, 0, 0 ],
-						[ 0, 0, 1, 1 ],
-						[ 0, 0, 1, 1 ]
-					] );
-				} );
-
-				it( 'inserts simple table to a simple table fragment - in the middle of a table', () => {
-					tableSelection._setCellSelection(
-						modelRoot.getNodeByPath( [ 0, 1, 1 ] ),
-						modelRoot.getNodeByPath( [ 0, 2, 2 ] )
-					);
-
-					pasteTable( [
-						[ 'aa', 'ab' ],
-						[ 'ba', 'bb' ]
-					] );
-
-					assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
-						[ '00', '01', '02', '03' ],
-						[ '10', 'aa', 'ab', '13' ],
-						[ '20', 'ba', 'bb', '23' ],
-						[ '30', '31', '32', '33' ]
-					] ) );
-
-					assertSelectedCells( model, [
-						[ 0, 0, 0, 0 ],
-						[ 0, 1, 1, 0 ],
-						[ 0, 1, 1, 0 ],
-						[ 0, 0, 0, 0 ]
-					] );
+				describe( 'no spans', () => {
+					it( 'handles simple table paste to a simple table fragment - at the beginning of a table', () => {
+						tableSelection._setCellSelection(
+							modelRoot.getNodeByPath( [ 0, 0, 0 ] ),
+							modelRoot.getNodeByPath( [ 0, 1, 1 ] )
+						);
+
+						pasteTable( [
+							[ 'aa', 'ab' ],
+							[ 'ba', 'bb' ]
+						] );
+
+						assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
+							[ 'aa', 'ab', '02', '03' ],
+							[ 'ba', 'bb', '12', '13' ],
+							[ '20', '21', '22', '23' ],
+							[ '30', '31', '32', '33' ]
+						] ) );
+
+						assertSelectedCells( model, [
+							[ 1, 1, 0, 0 ],
+							[ 1, 1, 0, 0 ],
+							[ 0, 0, 0, 0 ],
+							[ 0, 0, 0, 0 ]
+						] );
+					} );
+
+					it( 'handles simple table paste to a simple table fragment - at the end of a table', () => {
+						tableSelection._setCellSelection(
+							modelRoot.getNodeByPath( [ 0, 2, 2 ] ),
+							modelRoot.getNodeByPath( [ 0, 3, 3 ] )
+						);
+
+						pasteTable( [
+							[ 'aa', 'ab' ],
+							[ 'ba', 'bb' ]
+						] );
+
+						assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
+							[ '00', '01', '02', '03' ],
+							[ '10', '11', '12', '13' ],
+							[ '20', '21', 'aa', 'ab' ],
+							[ '30', '31', 'ba', 'bb' ]
+						] ) );
+
+						assertSelectedCells( model, [
+							[ 0, 0, 0, 0 ],
+							[ 0, 0, 0, 0 ],
+							[ 0, 0, 1, 1 ],
+							[ 0, 0, 1, 1 ]
+						] );
+					} );
+
+					it( 'handles simple table paste to a simple table fragment - in the middle of a table', () => {
+						tableSelection._setCellSelection(
+							modelRoot.getNodeByPath( [ 0, 1, 1 ] ),
+							modelRoot.getNodeByPath( [ 0, 2, 2 ] )
+						);
+
+						pasteTable( [
+							[ 'aa', 'ab' ],
+							[ 'ba', 'bb' ]
+						] );
+
+						assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
+							[ '00', '01', '02', '03' ],
+							[ '10', 'aa', 'ab', '13' ],
+							[ '20', 'ba', 'bb', '23' ],
+							[ '30', '31', '32', '33' ]
+						] ) );
+
+						assertSelectedCells( model, [
+							[ 0, 0, 0, 0 ],
+							[ 0, 1, 1, 0 ],
+							[ 0, 1, 1, 0 ],
+							[ 0, 0, 0, 0 ]
+						] );
+					} );
+
+					it( 'handles simple row paste to a simple row fragment - in the middle of a table', () => {
+						tableSelection._setCellSelection(
+							modelRoot.getNodeByPath( [ 0, 1, 1 ] ),
+							modelRoot.getNodeByPath( [ 0, 1, 2 ] )
+						);
+
+						pasteTable( [
+							[ 'aa', 'ab' ]
+						] );
+
+						assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
+							[ '00', '01', '02', '03' ],
+							[ '10', 'aa', 'ab', '13' ],
+							[ '20', '21', '22', '23' ],
+							[ '30', '31', '32', '33' ]
+						] ) );
+
+						assertSelectedCells( model, [
+							[ 0, 0, 0, 0 ],
+							[ 0, 1, 1, 0 ],
+							[ 0, 0, 0, 0 ],
+							[ 0, 0, 0, 0 ]
+						] );
+					} );
+
+					it( 'handles simple column paste to a simple column fragment - in the middle of a table', () => {
+						tableSelection._setCellSelection(
+							modelRoot.getNodeByPath( [ 0, 1, 1 ] ),
+							modelRoot.getNodeByPath( [ 0, 2, 1 ] )
+						);
+
+						pasteTable( [
+							[ 'aa' ],
+							[ 'ba' ]
+						] );
+
+						assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
+							[ '00', '01', '02', '03' ],
+							[ '10', 'aa', '12', '13' ],
+							[ '20', 'ba', '22', '23' ],
+							[ '30', '31', '32', '33' ]
+						] ) );
+
+						assertSelectedCells( model, [
+							[ 0, 0, 0, 0 ],
+							[ 0, 1, 0, 0 ],
+							[ 0, 1, 0, 0 ],
+							[ 0, 0, 0, 0 ]
+						] );
+					} );
+
+					it( 'handles simple table paste to a simple table fragment - whole table selected', () => {
+						tableSelection._setCellSelection(
+							modelRoot.getNodeByPath( [ 0, 0, 0 ] ),
+							modelRoot.getNodeByPath( [ 0, 3, 3 ] )
+						);
+
+						pasteTable( [
+							[ 'aa', 'ab', 'ac', 'ad' ],
+							[ 'ba', 'bb', 'bc', 'bd' ],
+							[ 'ca', 'cb', 'cc', 'cd' ],
+							[ 'da', 'db', 'dc', 'dd' ]
+						] );
+
+						assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
+							[ 'aa', 'ab', 'ac', 'ad' ],
+							[ 'ba', 'bb', 'bc', 'bd' ],
+							[ 'ca', 'cb', 'cc', 'cd' ],
+							[ 'da', 'db', 'dc', 'dd' ]
+						] ) );
+
+						assertSelectedCells( model, [
+							[ 1, 1, 1, 1 ],
+							[ 1, 1, 1, 1 ],
+							[ 1, 1, 1, 1 ],
+							[ 1, 1, 1, 1 ]
+						] );
+					} );
 				} );
 
-				it( 'inserts simple row to a simple row fragment - in the middle of a table', () => {
-					tableSelection._setCellSelection(
-						modelRoot.getNodeByPath( [ 0, 1, 1 ] ),
-						modelRoot.getNodeByPath( [ 0, 1, 2 ] )
-					);
-
-					pasteTable( [
-						[ 'aa', 'ab' ]
-					] );
-
-					assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
-						[ '00', '01', '02', '03' ],
-						[ '10', 'aa', 'ab', '13' ],
-						[ '20', '21', '22', '23' ],
-						[ '30', '31', '32', '33' ]
-					] ) );
-
-					assertSelectedCells( model, [
-						[ 0, 0, 0, 0 ],
-						[ 0, 1, 1, 0 ],
-						[ 0, 0, 0, 0 ],
-						[ 0, 0, 0, 0 ]
-					] );
-				} );
-
-				it( 'inserts simple column to a simple column fragment - in the middle of a table', () => {
-					tableSelection._setCellSelection(
-						modelRoot.getNodeByPath( [ 0, 1, 1 ] ),
-						modelRoot.getNodeByPath( [ 0, 2, 1 ] )
-					);
-
-					pasteTable( [
-						[ 'aa' ],
-						[ 'ba' ]
-					] );
-
-					assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
-						[ '00', '01', '02', '03' ],
-						[ '10', 'aa', '12', '13' ],
-						[ '20', 'ba', '22', '23' ],
-						[ '30', '31', '32', '33' ]
-					] ) );
-
-					assertSelectedCells( model, [
-						[ 0, 0, 0, 0 ],
-						[ 0, 1, 0, 0 ],
-						[ 0, 1, 0, 0 ],
-						[ 0, 0, 0, 0 ]
-					] );
-				} );
-
-				it( 'inserts simple table to a simple table fragment - whole table selected', () => {
-					tableSelection._setCellSelection(
-						modelRoot.getNodeByPath( [ 0, 0, 0 ] ),
-						modelRoot.getNodeByPath( [ 0, 3, 3 ] )
-					);
-
-					pasteTable( [
-						[ 'aa', 'ab', 'ac', 'ad' ],
-						[ 'ba', 'bb', 'bc', 'bd' ],
-						[ 'ca', 'cb', 'cc', 'cd' ],
-						[ 'da', 'db', 'dc', 'dd' ]
-					] );
-
-					assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
-						[ 'aa', 'ab', 'ac', 'ad' ],
-						[ 'ba', 'bb', 'bc', 'bd' ],
-						[ 'ca', 'cb', 'cc', 'cd' ],
-						[ 'da', 'db', 'dc', 'dd' ]
-					] ) );
-
-					assertSelectedCells( model, [
-						[ 1, 1, 1, 1 ],
-						[ 1, 1, 1, 1 ],
-						[ 1, 1, 1, 1 ],
-						[ 1, 1, 1, 1 ]
-					] );
+				describe( 'pasted table has spans', () => {
+					it( 'handles pasting table that has cell with colspan', () => {
+						tableSelection._setCellSelection(
+							modelRoot.getNodeByPath( [ 0, 1, 1 ] ),
+							modelRoot.getNodeByPath( [ 0, 2, 2 ] )
+						);
+
+						pasteTable( [
+							[ { colspan: 2, contents: 'aa' } ],
+							[ 'ba', 'bb' ]
+						] );
+
+						assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
+							[ '00', '01', '02', '03' ],
+							[ '10', { colspan: 2, contents: 'aa' }, '13' ],
+							[ '20', 'ba', 'bb', '23' ],
+							[ '30', '31', '32', '33' ]
+						] ) );
+
+						/* eslint-disable no-multi-spaces */
+						assertSelectedCells( model, [
+							[ 0, 0, 0, 0 ],
+							[ 0, 1,    0 ],
+							[ 0, 1, 1, 0 ],
+							[ 0, 0, 0, 0 ]
+						] );
+						/* eslint-enable no-multi-spaces */
+					} );
+
+					it( 'handles pasting table that has many cells with various colspan', () => {
+						tableSelection._setCellSelection(
+							modelRoot.getNodeByPath( [ 0, 0, 0 ] ),
+							modelRoot.getNodeByPath( [ 0, 3, 2 ] )
+						);
+
+						pasteTable( [
+							[ 'aa', { colspan: 2, contents: 'ab' } ],
+							[ { colspan: 3, contents: 'ba' } ],
+							[ 'ca', 'cb', 'cc' ],
+							[ { colspan: 2, contents: 'da' }, 'dc' ]
+						] );
+
+						assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [
+							[ 'aa', { colspan: 2, contents: 'ab' }, '03' ],
+							[ { colspan: 3, contents: 'ba' }, '13' ],
+							[ 'ca', 'cb', 'cc', '23' ],
+							[ { colspan: 2, contents: 'da' }, 'dc', '33' ]
+						] ) );
+
+						/* eslint-disable no-multi-spaces */
+						assertSelectedCells( model, [
+							[ 1, 1,    0 ],
+							[ 1,       0 ],
+							[ 1, 1, 1, 0 ],
+							[ 1,    1, 0 ]
+						] );
+						/* eslint-enable no-multi-spaces */
+					} );
 				} );
 			} );
 		} );