瀏覽代碼

Added: Simple table layout post-fixer.

Maciej Gołaszewski 7 年之前
父節點
當前提交
0b7fa953df
共有 2 個文件被更改,包括 106 次插入3 次删除
  1. 60 2
      packages/ckeditor5-table/src/tableediting.js
  2. 46 1
      packages/ckeditor5-table/tests/tableediting.js

+ 60 - 2
packages/ckeditor5-table/src/tableediting.js

@@ -10,6 +10,7 @@
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import { upcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';
 import Range from '@ckeditor/ckeditor5-engine/src/model/range';
+import Position from '@ckeditor/ckeditor5-engine/src/model/position';
 import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
 
 import upcastTable from './converters/upcasttable';
@@ -31,7 +32,8 @@ import RemoveColumnCommand from './commands/removecolumncommand';
 import SetHeaderRowCommand from './commands/setheaderrowcommand';
 import SetHeaderColumnCommand from './commands/setheadercolumncommand';
 import { getParentTable } from './commands/utils';
-import TableUtils from './tableutils';
+import TableWalker from './tablewalker';
+import TableUtils from '../src/tableutils';
 
 import '../theme/tableediting.css';
 
@@ -46,7 +48,8 @@ export default class TableEditing extends Plugin {
 	 */
 	init() {
 		const editor = this.editor;
-		const schema = editor.model.schema;
+		const model = editor.model;
+		const schema = model.schema;
 		const conversion = editor.conversion;
 
 		schema.register( 'table', {
@@ -119,6 +122,8 @@ export default class TableEditing extends Plugin {
 		editor.commands.add( 'setTableColumnHeader', new SetHeaderColumnCommand( editor ) );
 		editor.commands.add( 'setTableRowHeader', new SetHeaderRowCommand( editor ) );
 
+		injectTablePostFixer( model, this.editor.plugins.get( TableUtils ) );
+
 		// Handle tab key navigation.
 		this.listenTo( editor.editing.view.document, 'keydown', ( ...args ) => this._handleTabOnSelectedTable( ...args ) );
 		this.listenTo( editor.editing.view.document, 'keydown', ( ...args ) => this._handleTabInsideTable( ...args ) );
@@ -240,3 +245,56 @@ export default class TableEditing extends Plugin {
 		} );
 	}
 }
+
+function injectTablePostFixer( model, tableUtils ) {
+	model.document.registerPostFixer( writer => fixTableLayout( writer, model, tableUtils ) );
+}
+
+function fixTableLayout( writer, model, tableUtils ) {
+	const changes = model.document.differ.getChanges();
+
+	let wasFixed = false;
+
+	for ( const entry of changes ) {
+		if ( entry.type == 'insert' && entry.name == 'table' ) {
+			const table = entry.position.nodeAfter;
+
+			const lengths = {};
+
+			const tableSize = tableUtils.getColumns( table );
+
+			for ( const data of new TableWalker( table ) ) {
+				const row = data.row;
+				const column = data.column;
+				const colspan = data.colspan;
+
+				if ( !lengths[ row ] ) {
+					// Le first row - the first column will be current width including rowspanned cells.
+					lengths[ row ] = column;
+				}
+
+				lengths[ row ] += colspan;
+			}
+
+			const isValid = Object.values( lengths ).every( length => length === tableSize );
+
+			if ( !isValid ) {
+				const maxColumns = Object.values( lengths ).reduce( ( prev, current ) => current > prev ? current : prev, 0 );
+
+				for ( const [ rowIndex, size ] of Object.entries( lengths ) ) {
+					const columnsToInsert = maxColumns - size;
+
+					if ( columnsToInsert ) {
+						for ( let i = 0; i < columnsToInsert; i++ ) {
+							writer.insertElement( 'tableCell', Position.createAt( table.getChild( rowIndex ), 'end' ) );
+						}
+
+						wasFixed = true;
+					}
+				}
+			}
+		}
+	}
+
+	return wasFixed;
+}

+ 46 - 1
packages/ckeditor5-table/tests/tableediting.js

@@ -3,9 +3,10 @@
  * For licensing, see LICENSE.md.
  */
 
+import Range from '@ckeditor/ckeditor5-engine/src/model/range';
 import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
-import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
+import { getData as getModelData, setData as setModelData, parse } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 import { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard';
 
 import TableEditing from '../src/tableediting';
@@ -358,4 +359,48 @@ describe( 'TableEditing', () => {
 			} );
 		} );
 	} );
+
+	describe( 'post-fixer', () => {
+		it( 'should add missing columns to a tableRows that are shorter then longest table row', () => {
+			const parsed = parse( modelTable( [
+				[ '00' ],
+				[ '10', '11', '12' ],
+				[ '20', '21' ]
+			] ), model.schema );
+
+			const root = model.document.getRoot();
+
+			model.change( writer => {
+				writer.remove( Range.createIn( root ) );
+				writer.insert( parsed, root );
+			} );
+
+			expect( formatTable( getModelData( model, { withoutSelection: true } ) ) ).to.equal( formattedModelTable( [
+				[ '00', '', '' ],
+				[ '10', '11', '12' ],
+				[ '20', '21', '' ]
+			] ) );
+		} );
+
+		it( 'should add missing columns to a tableRows that are shorter then longest table row (complex)', () => {
+			const parsed = parse( modelTable( [
+				[ { colspan: 6, contents: '00' } ],
+				[ { rowspan: 2, contents: '10' }, '11', { colspan: 3, contents: '12' } ],
+				[ '21', '22' ]
+			] ), model.schema );
+
+			const root = model.document.getRoot();
+
+			model.change( writer => {
+				writer.remove( Range.createIn( root ) );
+				writer.insert( parsed, root );
+			} );
+
+			expect( formatTable( getModelData( model, { withoutSelection: true } ) ) ).to.equal( formattedModelTable( [
+				[ { colspan: 6, contents: '00' } ],
+				[ { rowspan: 2, contents: '10' }, '11', { colspan: 3, contents: '12' }, '' ],
+				[ '21', '22', '', '', '' ]
+			] ) );
+		} );
+	} );
 } );