From 31041d1d7b05b74196bff4e1313f22c6982ad689 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Fri, 26 Mar 2021 11:55:34 +0100 Subject: [PATCH 01/24] An initial implementation of the default styles for the table/cell. --- .travis.yml | 21 ++++++++++--------- .../src/commands/inserttablecommand.js | 7 +++++++ .../tablecellpropertiesediting.js | 6 ++++++ .../tableproperties/tablepropertiesediting.js | 5 +++++ packages/ckeditor5-table/src/tableutils.js | 9 ++++++-- .../tests/manual/tableproperties.js | 21 ++++++++++++++++++- 6 files changed, 56 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1ff046bb416..b6767069be0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,19 +19,20 @@ before_install: install: - yarn install # The "./manual/all-features-dll.js" test requires building DLL. -- yarn run dll:build +#- yarn run dll:build script: -- node ./scripts/continuous-integration-script.js -- yarn run lint -- yarn run stylelint -- ./scripts/check-manual-tests.sh -r ckeditor5 -f ckeditor5 -- yarn run docs --strict -- 'if [ $TRAVIS_TEST_RESULT -eq 0 ]; then - travis_wait 30 yarn run docs:build-and-publish-nightly; - fi' +- echo "Testing. Do not trigger the full build." +#- node ./scripts/continuous-integration-script.js +#- yarn run lint +#- yarn run stylelint +#- ./scripts/check-manual-tests.sh -r ckeditor5 -f ckeditor5 +#- yarn run docs --strict +#- 'if [ $TRAVIS_TEST_RESULT -eq 0 ]; then +# travis_wait 30 yarn run docs:build-and-publish-nightly; +# fi' after_script: - export END_TIME=$( date +%s ) -- ckeditor5-dev-tests-notify-travis-status +#- ckeditor5-dev-tests-notify-travis-status env: global: - secure: RO140EQDHmEOPJPikk8eCY5IdHpnEKGm41p5U1ewAbeZv1DpCG+rSumR2JdYl75kFAaZvCSm1NuVMM+kmYd+/z+LQbKj7QH5G/UHNho3H89blIU6WlJhT0YR5vclm9rvnEvOtxnfODca1Qrw+CaCoJks2o4VYbJB7mOBVNsh7Bc= diff --git a/packages/ckeditor5-table/src/commands/inserttablecommand.js b/packages/ckeditor5-table/src/commands/inserttablecommand.js index 64b1c533650..f68e73e40fa 100644 --- a/packages/ckeditor5-table/src/commands/inserttablecommand.js +++ b/packages/ckeditor5-table/src/commands/inserttablecommand.js @@ -47,10 +47,17 @@ export default class InsertTableCommand extends Command { * @fires execute */ execute( options = {} ) { + const editor = this.editor; const model = this.editor.model; const selection = model.document.selection; const tableUtils = this.editor.plugins.get( 'TableUtils' ); + // TODO (pomek): Could it be resolved in a nicer way? + const defaultProperties = editor.config.get( 'table.tableProperties.defaultProperties' ); + const defaultCellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); + + options = Object.assign( {}, options, { defaultProperties, defaultCellProperties } ); + const insertPosition = findOptimalInsertionPosition( selection, model ); model.change( writer => { diff --git a/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js b/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js index 9944dacf349..f277f68d7f3 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js +++ b/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js @@ -69,6 +69,12 @@ export default class TableCellPropertiesEditing extends Plugin { const conversion = editor.conversion; const locale = editor.locale; + // TODO (pomek): Add this option to the `table` configuration interface. + editor.config.define( 'table.tableCellProperties.defaultProperties', { + horizontalAlignment: 'center', + verticalAlignment: 'middle' + } ); + editor.data.addStyleProcessorRules( addBorderRules ); enableBorderProperties( schema, conversion ); editor.commands.add( 'tableCellBorderStyle', new TableCellBorderStyleCommand( editor ) ); diff --git a/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js b/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js index c0648cff5bd..dbd315aa1f9 100644 --- a/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js +++ b/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js @@ -69,6 +69,11 @@ export default class TablePropertiesEditing extends Plugin { const schema = editor.model.schema; const conversion = editor.conversion; + // TODO (pomek): Add this option to the `table` configuration interface. + editor.config.define( 'table.tableProperties.defaultProperties', { + alignment: 'center' + } ); + editor.data.addStyleProcessorRules( addBorderRules ); enableBorderProperties( schema, conversion ); editor.commands.add( 'tableBorderColor', new TableBorderColorCommand( editor ) ); diff --git a/packages/ckeditor5-table/src/tableutils.js b/packages/ckeditor5-table/src/tableutils.js index 23b7ea9d8ca..ec7d23e21b0 100644 --- a/packages/ckeditor5-table/src/tableutils.js +++ b/packages/ckeditor5-table/src/tableutils.js @@ -94,15 +94,20 @@ export default class TableUtils extends Plugin { * @param {Number} [options.columns=2] The number of columns to create. * @param {Number} [options.headingRows=0] The number of heading rows. * @param {Number} [options.headingColumns=0] The number of heading columns. + * @param {String} [options.defaultProperties={}] Default properties for the created table. + * @param {String} [options.defaultCellProperties={}] Default properties for the created table. * @returns {module:engine/model/element~Element} The created table element. */ createTable( writer, options ) { - const table = writer.createElement( 'table' ); + const defaultProperties = options.defaultProperties || {}; + const defaultCellProperties = options.defaultCellProperties || {}; + + const table = writer.createElement( 'table', defaultProperties ); const rows = parseInt( options.rows ) || 2; const columns = parseInt( options.columns ) || 2; - createEmptyRows( writer, table, 0, rows, columns ); + createEmptyRows( writer, table, 0, rows, columns, defaultCellProperties ); if ( options.headingRows ) { updateNumericAttribute( 'headingRows', options.headingRows, table, writer, 0 ); diff --git a/packages/ckeditor5-table/tests/manual/tableproperties.js b/packages/ckeditor5-table/tests/manual/tableproperties.js index 79b0d202ab5..065c8da2132 100644 --- a/packages/ckeditor5-table/tests/manual/tableproperties.js +++ b/packages/ckeditor5-table/tests/manual/tableproperties.js @@ -26,8 +26,26 @@ ClassicEditor 'heading', '|', 'insertTable', '|', 'bold', 'italic', 'bulletedList', 'numberedList', 'blockQuote', 'undo', 'redo' ], table: { + // TODO (pomek): Please, rollback these changes or update the manual test. contentToolbar: [ 'tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties' ], - tableToolbar: [ 'bold', 'italic' ] + tableToolbar: [ 'bold', 'italic' ], + tableProperties: { + defaultProperties: { + alignment: 'left', + borderColor: '#ff0000', + borderWidth: '2px', + borderStyle: 'dashed' + } + }, + tableCellProperties: { + defaultProperties: { + horizontalAlignment: 'right', + verticalAlignment: 'bottom', + borderColor: '#0000ff', + borderWidth: '2px', + borderStyle: 'dotted' + } + } } } ) .then( editor => { @@ -36,3 +54,4 @@ ClassicEditor .catch( err => { console.error( err.stack ); } ); + From 445f60b674fa84866d82f1552b71c7ea6da4e8ca Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Mon, 29 Mar 2021 17:20:17 +0200 Subject: [PATCH 02/24] Added tests for default table/cell properties. --- .../src/commands/inserttablecommand.js | 18 ++- packages/ckeditor5-table/src/tableutils.js | 4 +- .../ckeditor5-table/tests/_utils/utils.js | 19 ++- .../tests/commands/inserttablecommand.js | 120 ++++++++++++++++++ .../tablecellpropertiesediting.js | 15 +++ .../tablecellpropertiesui.js | 6 +- .../tableproperties/tablepropertiesediting.js | 24 +++- .../tableproperties/tablepropertiesui.js | 5 +- packages/ckeditor5-table/tests/tableutils.js | 68 ++++++++++ 9 files changed, 258 insertions(+), 21 deletions(-) diff --git a/packages/ckeditor5-table/src/commands/inserttablecommand.js b/packages/ckeditor5-table/src/commands/inserttablecommand.js index f68e73e40fa..f6434be3924 100644 --- a/packages/ckeditor5-table/src/commands/inserttablecommand.js +++ b/packages/ckeditor5-table/src/commands/inserttablecommand.js @@ -48,20 +48,24 @@ export default class InsertTableCommand extends Command { */ execute( options = {} ) { const editor = this.editor; - const model = this.editor.model; + const model = editor.model; const selection = model.document.selection; - const tableUtils = this.editor.plugins.get( 'TableUtils' ); + const tableUtils = editor.plugins.get( 'TableUtils' ); + + const createTableOptions = Object.assign( {}, options ); - // TODO (pomek): Could it be resolved in a nicer way? - const defaultProperties = editor.config.get( 'table.tableProperties.defaultProperties' ); - const defaultCellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); + if ( editor.plugins.has( 'TablePropertiesEditing' ) ) { + createTableOptions.defaultProperties = editor.config.get( 'table.tableProperties.defaultProperties' ); + } - options = Object.assign( {}, options, { defaultProperties, defaultCellProperties } ); + if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { + createTableOptions.defaultCellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); + } const insertPosition = findOptimalInsertionPosition( selection, model ); model.change( writer => { - const table = tableUtils.createTable( writer, options ); + const table = tableUtils.createTable( writer, createTableOptions ); model.insertContent( table, insertPosition ); diff --git a/packages/ckeditor5-table/src/tableutils.js b/packages/ckeditor5-table/src/tableutils.js index ec7d23e21b0..867d1f1d135 100644 --- a/packages/ckeditor5-table/src/tableutils.js +++ b/packages/ckeditor5-table/src/tableutils.js @@ -94,8 +94,8 @@ export default class TableUtils extends Plugin { * @param {Number} [options.columns=2] The number of columns to create. * @param {Number} [options.headingRows=0] The number of heading rows. * @param {Number} [options.headingColumns=0] The number of heading columns. - * @param {String} [options.defaultProperties={}] Default properties for the created table. - * @param {String} [options.defaultCellProperties={}] Default properties for the created table. + * @param {String} [options.defaultProperties={}] The default properties for the created table. + * @param {String} [options.defaultCellProperties={}] The default cell properties in the created table. * @returns {module:engine/model/element~Element} The created table element. */ createTable( writer, options ) { diff --git a/packages/ckeditor5-table/tests/_utils/utils.js b/packages/ckeditor5-table/tests/_utils/utils.js index 36bd57d89db..b5fde3991e3 100644 --- a/packages/ckeditor5-table/tests/_utils/utils.js +++ b/packages/ckeditor5-table/tests/_utils/utils.js @@ -32,19 +32,26 @@ const WIDGET_TABLE_CELL_CLASS = 'ck-editor__editable ck-editor__nested-editable' * }; * * @param {Array.|Object>} tableData - * @param {Object} [attributes] Optional table attributes: `headingRows` and `headingColumns`. + * @param {Object} [attributes={}] Optional table attributes. + * @param {Number} attributes.headingRows Number of heading rows. + * @param {Number} attributes.headingColumns Number of heading columns. + * @param {Object} attributes.defaultProperties Default styles for the table. + * @param {Object} attributes.defaultCellProperties Default styles for all cells. * * @returns {String} */ -export function modelTable( tableData, attributes ) { +export function modelTable( tableData, attributes = {} ) { const tableRows = makeRows( tableData, { cellElement: 'tableCell', rowElement: 'tableRow', headingElement: 'tableCell', wrappingElement: 'paragraph', - enforceWrapping: true + enforceWrapping: true, + defaultCellProperties: attributes.defaultCellProperties } ); + delete attributes.defaultCellProperties; + return `${ tableRows }`; } @@ -343,7 +350,7 @@ function formatAttributes( attributes ) { // Formats passed table data to a set of table rows. function makeRows( tableData, options ) { - const { cellElement, rowElement, headingElement, wrappingElement, enforceWrapping, asWidget } = options; + const { cellElement, rowElement, headingElement, wrappingElement, enforceWrapping, asWidget, defaultCellProperties } = options; return tableData .reduce( ( previousRowsString, tableRow ) => { @@ -367,7 +374,9 @@ function makeRows( tableData, options ) { delete tableCellData.isSelected; } - let attributes = {}; + let attributes = { + ...defaultCellProperties + }; if ( asWidget ) { attributes.class = getClassToSet( attributes ); diff --git a/packages/ckeditor5-table/tests/commands/inserttablecommand.js b/packages/ckeditor5-table/tests/commands/inserttablecommand.js index 3f4bb0841de..7ea58cc68ec 100644 --- a/packages/ckeditor5-table/tests/commands/inserttablecommand.js +++ b/packages/ckeditor5-table/tests/commands/inserttablecommand.js @@ -12,6 +12,8 @@ import TableEditing from '../../src/tableediting'; import { modelTable } from '../_utils/utils'; import InsertTableCommand from '../../src/commands/inserttablecommand'; +import TablePropertiesEditing from '../../src/tableproperties/tablepropertiesediting'; +import TableCellPropertiesEditing from '../../src/tablecellproperties/tablecellpropertiesediting'; describe( 'InsertTableCommand', () => { let editor, model, command; @@ -168,6 +170,124 @@ describe( 'InsertTableCommand', () => { ] ) ); } ); + + describe( 'integration with TablePropertiesEditing', () => { + let editor, model, command, tableUtils; + + beforeEach( () => { + return ModelTestEditor + .create( { + plugins: [ Paragraph, TableEditing, TablePropertiesEditing ] + } ) + .then( newEditor => { + editor = newEditor; + model = editor.model; + setData( model, '[]' ); + + command = editor.commands.get( 'insertTable' ); + tableUtils = editor.plugins.get( 'TableUtils' ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( + 'should pass the default table styles to "TableUtils.createTable()" function if TablePropertiesEditing is enabled', + () => { + const createTableStub = sinon.stub( tableUtils, 'createTable' ).callThrough(); + + command.execute(); + + expect( createTableStub.callCount ).to.equal( 1 ); + expect( createTableStub.firstCall.args[ 1 ] ).to.deep.equal( { + defaultProperties: { alignment: 'center' } + } ); + } + ); + + it( 'should create the table with applied the default properties', () => { + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + alignment: 'right' + }; + + editor.config.set( 'table.tableProperties.defaultProperties', defaultProperties ); + + command.execute(); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '[]', '' ], + [ '', '' ] + ], { ...defaultProperties } ) + ); + } ); + } ); + + describe( 'integration with TableCellPropertiesEditing', () => { + let editor, model, command, tableUtils; + + beforeEach( () => { + return ModelTestEditor + .create( { + plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] + } ) + .then( newEditor => { + editor = newEditor; + model = editor.model; + setData( model, '[]' ); + + command = editor.commands.get( 'insertTable' ); + tableUtils = editor.plugins.get( 'TableUtils' ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( + 'should pass the default cell styles to "TableUtils.createTable()" function if TableCellPropertiesEditing is enabled', + () => { + const createTableStub = sinon.stub( tableUtils, 'createTable' ).callThrough(); + + command.execute(); + + expect( createTableStub.callCount ).to.equal( 1 ); + expect( createTableStub.firstCall.args[ 1 ] ).to.deep.equal( { + defaultCellProperties: { + horizontalAlignment: 'center', + verticalAlignment: 'middle' + } + } ); + } + ); + + it( 'should create the table and all cells should have applied the default cell properties', () => { + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); + + command.execute(); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '[]', '' ], + [ '', '' ] + ], { defaultCellProperties: defaultProperties } ) + ); + } ); + } ); } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js index 24fd7657336..7b974b8a03f 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js @@ -79,6 +79,21 @@ describe( 'table cell properties', () => { expect( editor.commands.get( 'tableCellHeight' ) ).to.be.instanceOf( TableCellHeightCommand ); } ); + describe( 'config', () => { + let tableCellProperties; + + beforeEach( () => { + tableCellProperties = editor.config.get( 'table.tableCellProperties' ); + } ); + + it( 'should define the default properties for a table', () => { + expect( tableCellProperties.defaultProperties ).to.deep.equal( { + horizontalAlignment: 'center', + verticalAlignment: 'middle' + } ); + } ); + } ); + describe( 'border', () => { it( 'should set proper schema rules', () => { expect( model.schema.checkAttribute( [ '$root', 'tableCell' ], 'borderColor' ) ).to.be.true; diff --git a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js index f5538646802..0a5d6a93803 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js @@ -74,7 +74,11 @@ describe( 'table cell properties', () => { it( 'should define table.tableCellProperties config', () => { expect( editor.config.get( 'table.tableCellProperties' ) ).to.deep.equal( { borderColors: defaultColors, - backgroundColors: defaultColors + backgroundColors: defaultColors, + defaultProperties: { + horizontalAlignment: 'center', + verticalAlignment: 'middle' + } } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js b/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js index d81e4ac477c..12c7e090442 100644 --- a/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js +++ b/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js @@ -73,6 +73,20 @@ describe( 'table properties', () => { expect( editor.commands.get( 'tableBackgroundColor' ) ).to.be.instanceOf( TableBackgroundColorCommand ); } ); + describe( 'config', () => { + let tableProperties; + + beforeEach( () => { + tableProperties = editor.config.get( 'table.tableProperties' ); + } ); + + it( 'should define the default properties for a table', () => { + expect( tableProperties.defaultProperties ).to.deep.equal( { + alignment: 'center' + } ); + } ); + } ); + describe( 'border', () => { it( 'should set proper schema rules', () => { expect( model.schema.checkAttribute( [ '$root', 'table' ], 'borderColor' ) ).to.be.true; @@ -1054,11 +1068,11 @@ describe( 'table properties', () => { setModelData( model, '' + - '' + - '' + - 'foo' + - '' + - '' + + '' + + '' + + 'foo' + + '' + + '' + '
' ); diff --git a/packages/ckeditor5-table/tests/tableproperties/tablepropertiesui.js b/packages/ckeditor5-table/tests/tableproperties/tablepropertiesui.js index e0129f80e63..2fb3b5742de 100644 --- a/packages/ckeditor5-table/tests/tableproperties/tablepropertiesui.js +++ b/packages/ckeditor5-table/tests/tableproperties/tablepropertiesui.js @@ -73,7 +73,10 @@ describe( 'table properties', () => { it( 'should define table.tableProperties config', () => { expect( editor.config.get( 'table.tableProperties' ) ).to.deep.equal( { borderColors: defaultColors, - backgroundColors: defaultColors + backgroundColors: defaultColors, + defaultProperties: { + alignment: 'center' + } } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tableutils.js b/packages/ckeditor5-table/tests/tableutils.js index cfc03d379fa..99d83556161 100644 --- a/packages/ckeditor5-table/tests/tableutils.js +++ b/packages/ckeditor5-table/tests/tableutils.js @@ -13,6 +13,8 @@ import TableEditing from '../src/tableediting'; import { modelTable } from './_utils/utils'; import TableUtils from '../src/tableutils'; +import TablePropertiesEditing from '../src/tableproperties/tablepropertiesediting'; +import TableCellPropertiesEditing from '../src/tablecellproperties/tablecellpropertiesediting'; describe( 'TableUtils', () => { let editor, model, root, tableUtils; @@ -1635,5 +1637,71 @@ describe( 'TableUtils', () => { [ '', '' ] ], { headingRows: 2, headingColumns: 1 } ) ); } ); + + describe( 'enabled TablePropertiesEditing + TableCellPropertiesEditing', () => { + let editor, model, tableUtils; + + beforeEach( () => { + return ModelTestEditor.create( { + plugins: [ Paragraph, TableEditing, TableUtils, TablePropertiesEditing, TableCellPropertiesEditing ] + } ).then( newEditor => { + editor = newEditor; + model = editor.model; + tableUtils = editor.plugins.get( TableUtils ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( 'should create table and apply specified styles for the table', () => { + setData( model, '[]' ); + + const defaultProperties = { + borderStyle: 'solid', + borderColor: '#f00', + borderWidth: '2px', + width: '400px', + height: '200px', + alignment: 'left' + }; + + model.change( writer => { + const table = tableUtils.createTable( writer, { defaultProperties } ); + + model.insertContent( table, model.document.selection.focus ); + } ); + + // Styles for the table are included in the `attributes` object. + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '', '' ], + [ '', '' ] + ], { ...defaultProperties } ) ); + } ); + + it( 'should create table and apply specified styles for all cells', () => { + setData( model, '[]' ); + + const defaultCellProperties = { + width: '30px', + height: '30px', + verticalAlignment: 'bottom', + horizontalAlignment: 'right' + }; + + model.change( writer => { + const table = tableUtils.createTable( writer, { defaultCellProperties } ); + + model.insertContent( table, model.document.selection.focus ); + } ); + + // Styles for cells are specified as `attributes.defaultCellProperties` object. + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '', '' ], + [ '', '' ] + ], { defaultCellProperties } ) ); + } ); + } ); } ); } ); From 24b747a345a5f1d10c9b44187ab2955eeb72f2b5 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Mon, 29 Mar 2021 17:21:03 +0200 Subject: [PATCH 03/24] API Docs: Added default table/cell properties to docs. --- .../ckeditor5-table/src/tablecellproperties.js | 14 ++++++++++++++ .../tablecellpropertiesediting.js | 1 - packages/ckeditor5-table/src/tableproperties.js | 13 +++++++++++++ .../src/tableproperties/tablepropertiesediting.js | 1 - 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/packages/ckeditor5-table/src/tablecellproperties.js b/packages/ckeditor5-table/src/tablecellproperties.js index daffcb7d022..ca481e90df9 100644 --- a/packages/ckeditor5-table/src/tablecellproperties.js +++ b/packages/ckeditor5-table/src/tablecellproperties.js @@ -64,6 +64,20 @@ export default class TableCellProperties extends Plugin { * } * }; * + * * The default styles for the cell while creating a new table (`tableCellProperties.defaultProperties`): + * + * const tableConfig = { + * tableCellProperties: { + * defaultProperties: { + * borderStyle: 'dotted', + * borderColor: 'hsl(120, 75%, 60%)', + * borderWidth: '2px', + * horizontalAlignment: 'right', + * verticalAlignment: 'bottom' + * } + * } + * } + * * **Note**: The configurations do not impact the data loaded into the editor, * i.e. they do not limit or filter the colors in the data. They are used only in the user interface * allowing users to pick colors in a more convenient way. diff --git a/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js b/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js index f277f68d7f3..388167ebdf4 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js +++ b/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js @@ -69,7 +69,6 @@ export default class TableCellPropertiesEditing extends Plugin { const conversion = editor.conversion; const locale = editor.locale; - // TODO (pomek): Add this option to the `table` configuration interface. editor.config.define( 'table.tableCellProperties.defaultProperties', { horizontalAlignment: 'center', verticalAlignment: 'middle' diff --git a/packages/ckeditor5-table/src/tableproperties.js b/packages/ckeditor5-table/src/tableproperties.js index 25d23f8ffac..5ce4d0b695d 100644 --- a/packages/ckeditor5-table/src/tableproperties.js +++ b/packages/ckeditor5-table/src/tableproperties.js @@ -65,6 +65,19 @@ export default class TableProperties extends Plugin { * } * }; * + * * The default styles for the new created table (`tableProperties.defaultProperties`): + * + * const tableConfig = { + * tableProperties: { + * defaultProperties: { + * borderStyle: 'dashed', + * borderColor: 'hsl(0, 0%, 90%)', + * borderWidth: '3px', + * alignment: 'left' + * } + * } + * } + * * **Note**: The configurations do not impact the data loaded into the editor, * i.e. they do not limit or filter the colors in the data. They are used only in the user interface * allowing users to pick colors in a more convenient way. diff --git a/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js b/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js index dbd315aa1f9..fe5aa14d7bc 100644 --- a/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js +++ b/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js @@ -69,7 +69,6 @@ export default class TablePropertiesEditing extends Plugin { const schema = editor.model.schema; const conversion = editor.conversion; - // TODO (pomek): Add this option to the `table` configuration interface. editor.config.define( 'table.tableProperties.defaultProperties', { alignment: 'center' } ); From 801dd245c929dad356d8489466590ec08edeb1a7 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Tue, 30 Mar 2021 10:33:17 +0200 Subject: [PATCH 04/24] InsertColumnCommand: Support for TableCellProperties. --- .../src/commands/insertcolumncommand.js | 11 +- .../tests/commands/insertcolumncommand.js | 147 ++++++++++++++++++ 2 files changed, 157 insertions(+), 1 deletion(-) diff --git a/packages/ckeditor5-table/src/commands/insertcolumncommand.js b/packages/ckeditor5-table/src/commands/insertcolumncommand.js index b33cc8106d1..bee55205834 100644 --- a/packages/ckeditor5-table/src/commands/insertcolumncommand.js +++ b/packages/ckeditor5-table/src/commands/insertcolumncommand.js @@ -78,6 +78,15 @@ export default class InsertColumnCommand extends Command { const column = insertBefore ? columnIndexes.first : columnIndexes.last; const table = affectedTableCells[ 0 ].findAncestor( 'table' ); - tableUtils.insertColumns( table, { columns: 1, at: insertBefore ? column : column + 1 } ); + const insertColumnsOptions = { + columns: 1, + at: insertBefore ? column : column + 1 + }; + + if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { + insertColumnsOptions.defaultCellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); + } + + tableUtils.insertColumns( table, insertColumnsOptions ); } } diff --git a/packages/ckeditor5-table/tests/commands/insertcolumncommand.js b/packages/ckeditor5-table/tests/commands/insertcolumncommand.js index 8e25b0cd8ea..bcdc8785204 100644 --- a/packages/ckeditor5-table/tests/commands/insertcolumncommand.js +++ b/packages/ckeditor5-table/tests/commands/insertcolumncommand.js @@ -14,6 +14,7 @@ import TableEditing from '../../src/tableediting'; import { assertSelectedCells, modelTable } from '../_utils/utils'; import InsertColumnCommand from '../../src/commands/insertcolumncommand'; +import TableCellPropertiesEditing from '../../src/tablecellproperties/tablecellpropertiesediting'; describe( 'InsertColumnCommand', () => { let editor, model, command; @@ -213,6 +214,79 @@ describe( 'InsertColumnCommand', () => { [ '31', '', '' ] ] ) ); } ); + + describe( 'integration with TableCellPropertiesEditing', () => { + let editor, model, tableUtils, command; + + beforeEach( () => { + return ModelTestEditor + .create( { + plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] + } ) + .then( newEditor => { + editor = newEditor; + model = editor.model; + + command = editor.commands.get( 'insertTableColumnRight' ); + tableUtils = editor.plugins.get( 'TableUtils' ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( + 'should pass the default cell styles to "TableUtils.insertColumns()" function if TableCellPropertiesEditing is enabled', + () => { + const insertColumnsStub = sinon.stub( tableUtils, 'insertColumns' ).callThrough(); + + setData( model, modelTable( [ + [ '11[]' ], + [ '21' ] + ] ) ); + + command.execute(); + + expect( insertColumnsStub.callCount ).to.equal( 1 ); + expect( insertColumnsStub.firstCall.args[ 1 ] ).to.deep.equal( { + columns: 1, + at: 1, + defaultCellProperties: { + horizontalAlignment: 'center', + verticalAlignment: 'middle' + } + } ); + } + ); + + it( 'should create the table and all cells should have applied the default cell properties', () => { + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); + + // Apply default properties for the created table. + setData( model, modelTable( [ + [ '11[]' ], + [ '21' ] + ], { defaultCellProperties: defaultProperties } ) ); + + command.execute(); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '11[]', '' ], + [ '21', '' ] + ], { defaultCellProperties: defaultProperties } ) + ); + } ); + } ); } ); } ); @@ -380,6 +454,79 @@ describe( 'InsertColumnCommand', () => { [ { contents: '20', colspan: 5 }, { contents: '24', colspan: 2 } ] ], { headingColumns: 5 } ) ); } ); + + describe( 'integration with TableCellPropertiesEditing', () => { + let editor, model, tableUtils, command; + + beforeEach( () => { + return ModelTestEditor + .create( { + plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] + } ) + .then( newEditor => { + editor = newEditor; + model = editor.model; + + command = editor.commands.get( 'insertTableColumnLeft' ); + tableUtils = editor.plugins.get( 'TableUtils' ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( + 'should pass the default cell styles to "TableUtils.insertColumns()" function if TableCellPropertiesEditing is enabled', + () => { + const insertColumnsStub = sinon.stub( tableUtils, 'insertColumns' ).callThrough(); + + setData( model, modelTable( [ + [ '11[]' ], + [ '21' ] + ] ) ); + + command.execute(); + + expect( insertColumnsStub.callCount ).to.equal( 1 ); + expect( insertColumnsStub.firstCall.args[ 1 ] ).to.deep.equal( { + columns: 1, + at: 0, + defaultCellProperties: { + horizontalAlignment: 'center', + verticalAlignment: 'middle' + } + } ); + } + ); + + it( 'should create the table and all cells should have applied the default cell properties', () => { + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); + + // Apply default properties for the created table. + setData( model, modelTable( [ + [ '11[]' ], + [ '21' ] + ], { defaultCellProperties: defaultProperties } ) ); + + command.execute(); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '', '11[]' ], + [ '', '21' ] + ], { defaultCellProperties: defaultProperties } ) + ); + } ); + } ); } ); } ); } ); From 9aa0ad2e4bd87004795056c45b0183a28f15fb80 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Tue, 30 Mar 2021 10:42:36 +0200 Subject: [PATCH 05/24] InsertRowCommand: Support for TableCellProperties. --- .../src/commands/insertrowcommand.js | 11 +- .../tests/commands/insertrowcommand.js | 143 ++++++++++++++++++ 2 files changed, 153 insertions(+), 1 deletion(-) diff --git a/packages/ckeditor5-table/src/commands/insertrowcommand.js b/packages/ckeditor5-table/src/commands/insertrowcommand.js index 14f95699e62..c1d67e732f9 100644 --- a/packages/ckeditor5-table/src/commands/insertrowcommand.js +++ b/packages/ckeditor5-table/src/commands/insertrowcommand.js @@ -77,6 +77,15 @@ export default class InsertRowCommand extends Command { const row = insertAbove ? rowIndexes.first : rowIndexes.last; const table = affectedTableCells[ 0 ].findAncestor( 'table' ); - tableUtils.insertRows( table, { at: insertAbove ? row : row + 1, copyStructureFromAbove: !insertAbove } ); + const insertRowsOptions = { + at: insertAbove ? row : row + 1, + copyStructureFromAbove: !insertAbove + }; + + if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { + insertRowsOptions.defaultCellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); + } + + tableUtils.insertRows( table, insertRowsOptions ); } } diff --git a/packages/ckeditor5-table/tests/commands/insertrowcommand.js b/packages/ckeditor5-table/tests/commands/insertrowcommand.js index c7c8b3c442b..9669b30cb69 100644 --- a/packages/ckeditor5-table/tests/commands/insertrowcommand.js +++ b/packages/ckeditor5-table/tests/commands/insertrowcommand.js @@ -14,6 +14,7 @@ import TableSelection from '../../src/tableselection'; import { assertSelectedCells, modelTable } from '../_utils/utils'; import InsertRowCommand from '../../src/commands/insertrowcommand'; +import TableCellPropertiesEditing from '../../src/tablecellproperties/tablecellpropertiesediting'; describe( 'InsertRowCommand', () => { let editor, model, command; @@ -308,6 +309,77 @@ describe( 'InsertRowCommand', () => { [ '10', '11', '12' ] ] ) ); } ); + + describe( 'integration with TableCellPropertiesEditing', () => { + let editor, model, tableUtils, command; + + beforeEach( () => { + return ModelTestEditor + .create( { + plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] + } ) + .then( newEditor => { + editor = newEditor; + model = editor.model; + + command = editor.commands.get( 'insertTableRowBelow' ); + tableUtils = editor.plugins.get( 'TableUtils' ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( + 'should pass the default cell styles to "TableUtils.insertRows()" function if TableCellPropertiesEditing is enabled', + () => { + const insertRowsStub = sinon.stub( tableUtils, 'insertRows' ).callThrough(); + + setData( model, modelTable( [ + [ '11[]', '12' ] + ] ) ); + + command.execute(); + + expect( insertRowsStub.callCount ).to.equal( 1 ); + expect( insertRowsStub.firstCall.args[ 1 ] ).to.deep.equal( { + at: 1, + copyStructureFromAbove: true, + defaultCellProperties: { + horizontalAlignment: 'center', + verticalAlignment: 'middle' + } + } ); + } + ); + + it( 'should create the table and all cells should have applied the default cell properties', () => { + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); + + // Apply default properties for the created table. + setData( model, modelTable( [ + [ '11[]', '12' ] + ], { defaultCellProperties: defaultProperties } ) ); + + command.execute(); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '11[]', '12' ], + [ '', '' ] + ], { defaultCellProperties: defaultProperties } ) + ); + } ); + } ); } ); } ); @@ -470,6 +542,77 @@ describe( 'InsertRowCommand', () => { [ '10', '11', '12' ] ] ) ); } ); + + describe( 'integration with TableCellPropertiesEditing', () => { + let editor, model, tableUtils, command; + + beforeEach( () => { + return ModelTestEditor + .create( { + plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] + } ) + .then( newEditor => { + editor = newEditor; + model = editor.model; + + command = editor.commands.get( 'insertTableRowAbove' ); + tableUtils = editor.plugins.get( 'TableUtils' ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( + 'should pass the default cell styles to "TableUtils.insertRows()" function if TableCellPropertiesEditing is enabled', + () => { + const insertRowsStub = sinon.stub( tableUtils, 'insertRows' ).callThrough(); + + setData( model, modelTable( [ + [ '11[]', '12' ] + ] ) ); + + command.execute(); + + expect( insertRowsStub.callCount ).to.equal( 1 ); + expect( insertRowsStub.firstCall.args[ 1 ] ).to.deep.equal( { + at: 0, + copyStructureFromAbove: false, + defaultCellProperties: { + horizontalAlignment: 'center', + verticalAlignment: 'middle' + } + } ); + } + ); + + it( 'should create the table and all cells should have applied the default cell properties', () => { + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); + + // Apply default properties for the created table. + setData( model, modelTable( [ + [ '11[]', '12' ] + ], { defaultCellProperties: defaultProperties } ) ); + + command.execute(); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '', '' ], + [ '11[]', '12' ] + ], { defaultCellProperties: defaultProperties } ) + ); + } ); + } ); } ); } ); } ); From 1ddab6bde21d750994633362479e2c313847bf14 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Tue, 30 Mar 2021 10:50:41 +0200 Subject: [PATCH 06/24] SplitCellCommand: Support for TableCellProperties. --- .../src/commands/splitcellcommand.js | 15 +- .../tests/commands/splitcellcommand.js | 140 ++++++++++++++++++ 2 files changed, 151 insertions(+), 4 deletions(-) diff --git a/packages/ckeditor5-table/src/commands/splitcellcommand.js b/packages/ckeditor5-table/src/commands/splitcellcommand.js index b13deb974b0..a607ffc1f53 100644 --- a/packages/ckeditor5-table/src/commands/splitcellcommand.js +++ b/packages/ckeditor5-table/src/commands/splitcellcommand.js @@ -55,14 +55,21 @@ export default class SplitCellCommand extends Command { * @inheritDoc */ execute() { - const tableCell = getSelectionAffectedTableCells( this.editor.model.document.selection )[ 0 ]; + const editor = this.editor; + const tableCell = getSelectionAffectedTableCells( editor.model.document.selection )[ 0 ]; const isHorizontal = this.direction === 'horizontally'; - const tableUtils = this.editor.plugins.get( 'TableUtils' ); + const tableUtils = editor.plugins.get( 'TableUtils' ); + + const splitOptions = {}; + + if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { + splitOptions.defaultCellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); + } if ( isHorizontal ) { - tableUtils.splitCellHorizontally( tableCell, 2 ); + tableUtils.splitCellHorizontally( tableCell, 2, splitOptions ); } else { - tableUtils.splitCellVertically( tableCell, 2 ); + tableUtils.splitCellVertically( tableCell, 2, splitOptions ); } } } diff --git a/packages/ckeditor5-table/tests/commands/splitcellcommand.js b/packages/ckeditor5-table/tests/commands/splitcellcommand.js index b9ef82d29bc..8569fdf84bc 100644 --- a/packages/ckeditor5-table/tests/commands/splitcellcommand.js +++ b/packages/ckeditor5-table/tests/commands/splitcellcommand.js @@ -13,6 +13,7 @@ import TableSelection from '../../src/tableselection'; import { modelTable } from '../_utils/utils'; import SplitCellCommand from '../../src/commands/splitcellcommand'; +import TableCellPropertiesEditing from '../../src/tablecellproperties/tablecellpropertiesediting'; describe( 'SplitCellCommand', () => { let editor, model, command; @@ -164,6 +165,75 @@ describe( 'SplitCellCommand', () => { [ '25' ] ] ) ); } ); + + describe( 'integration with TableCellPropertiesEditing', () => { + let editor, model, tableUtils, command; + + beforeEach( () => { + return ModelTestEditor + .create( { + plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] + } ) + .then( newEditor => { + editor = newEditor; + model = editor.model; + + command = editor.commands.get( 'splitTableCellVertically' ); + tableUtils = editor.plugins.get( 'TableUtils' ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( + 'should pass the default cell styles to "TableUtils.splitCellVertically()" function if TableCellPropertiesEditing ' + + 'is enabled', + () => { + const splitCellVerticallyStub = sinon.stub( tableUtils, 'splitCellVertically' ).callThrough(); + + setData( model, modelTable( [ + [ '11[]' ] + ] ) ); + + command.execute(); + + expect( splitCellVerticallyStub.callCount ).to.equal( 1 ); + expect( splitCellVerticallyStub.firstCall.args[ 2 ] ).to.deep.equal( { + defaultCellProperties: { + horizontalAlignment: 'center', + verticalAlignment: 'middle' + } + } ); + } + ); + + it( 'should create the table and all cells should have applied the default cell properties', () => { + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); + + // Apply default properties for the created table. + setData( model, modelTable( [ + [ '11[]' ] + ], { defaultCellProperties: defaultProperties } ) ); + + command.execute(); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '11[]', '' ] + ], { defaultCellProperties: defaultProperties } ) + ); + } ); + } ); } ); } ); @@ -205,6 +275,76 @@ describe( 'SplitCellCommand', () => { [ '20', '21', '22' ] ] ) ); } ); + + describe( 'integration with TableCellPropertiesEditing', () => { + let editor, model, tableUtils, command; + + beforeEach( () => { + return ModelTestEditor + .create( { + plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] + } ) + .then( newEditor => { + editor = newEditor; + model = editor.model; + + command = editor.commands.get( 'splitTableCellHorizontally' ); + tableUtils = editor.plugins.get( 'TableUtils' ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( + 'should pass the default cell styles to "TableUtils.splitCellHorizontally()" function if TableCellPropertiesEditing ' + + 'is enabled', + () => { + const splitCellHorizontallyStub = sinon.stub( tableUtils, 'splitCellHorizontally' ).callThrough(); + + setData( model, modelTable( [ + [ '11[]' ] + ] ) ); + + command.execute(); + + expect( splitCellHorizontallyStub.callCount ).to.equal( 1 ); + expect( splitCellHorizontallyStub.firstCall.args[ 2 ] ).to.deep.equal( { + defaultCellProperties: { + horizontalAlignment: 'center', + verticalAlignment: 'middle' + } + } ); + } + ); + + it( 'should create the table and all cells should have applied the default cell properties', () => { + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); + + // Apply default properties for the created table. + setData( model, modelTable( [ + [ '11[]' ] + ], { defaultCellProperties: defaultProperties } ) ); + + command.execute(); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '11[]' ], + [ '' ] + ], { defaultCellProperties: defaultProperties } ) + ); + } ); + } ); } ); } ); } ); From efa3e195bbfce6c15a8f5df704564c418e5a7155 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Wed, 31 Mar 2021 09:44:00 +0200 Subject: [PATCH 07/24] Support for default table properties when splitting a cell. --- packages/ckeditor5-table/src/tableutils.js | 74 ++- packages/ckeditor5-table/src/utils/common.js | 2 +- .../ckeditor5-table/tests/_utils/utils.js | 5 +- packages/ckeditor5-table/tests/tableutils.js | 576 +++++++++++++++++- 4 files changed, 624 insertions(+), 33 deletions(-) diff --git a/packages/ckeditor5-table/src/tableutils.js b/packages/ckeditor5-table/src/tableutils.js index 867d1f1d135..dc397d351c2 100644 --- a/packages/ckeditor5-table/src/tableutils.js +++ b/packages/ckeditor5-table/src/tableutils.js @@ -95,7 +95,7 @@ export default class TableUtils extends Plugin { * @param {Number} [options.headingRows=0] The number of heading rows. * @param {Number} [options.headingColumns=0] The number of heading columns. * @param {String} [options.defaultProperties={}] The default properties for the created table. - * @param {String} [options.defaultCellProperties={}] The default cell properties in the created table. + * @param {Object} [options.defaultCellProperties={}] The default cell properties in the created table. * @returns {module:engine/model/element~Element} The created table element. */ createTable( writer, options ) { @@ -107,7 +107,9 @@ export default class TableUtils extends Plugin { const rows = parseInt( options.rows ) || 2; const columns = parseInt( options.columns ) || 2; - createEmptyRows( writer, table, 0, rows, columns, defaultCellProperties ); + createEmptyRows( writer, table, 0, rows, columns, { + cellProperties: defaultCellProperties + } ); if ( options.headingRows ) { updateNumericAttribute( 'headingRows', options.headingRows, table, writer, 0 ); @@ -146,6 +148,7 @@ export default class TableUtils extends Plugin { * @param {Number} [options.rows=1] The number of rows to insert. * @param {Boolean|undefined} [options.copyStructureFromAbove] The flag for copying row structure. Note that * the row structure will not be copied if this option is not provided. + * @param {Object} [options.defaultCellProperties={}] The default cell properties in the created table. */ insertRows( table, options = {} ) { const model = this.editor.model; @@ -154,6 +157,7 @@ export default class TableUtils extends Plugin { const rowsToInsert = options.rows || 1; const isCopyStructure = options.copyStructureFromAbove !== undefined; const copyStructureFrom = options.copyStructureFromAbove ? insertAt - 1 : insertAt; + const cellProperties = options.defaultCellProperties || {}; const rows = this.getRows( table ); const columns = this.getColumns( table ); @@ -168,7 +172,7 @@ export default class TableUtils extends Plugin { // Inserting at the end or at the beginning of a table doesn't require to calculate anything special. if ( !isCopyStructure && ( insertAt === 0 || insertAt === rows ) ) { - createEmptyRows( writer, table, insertAt, rowsToInsert, columns ); + createEmptyRows( writer, table, insertAt, rowsToInsert, columns, { cellProperties } ); return; } @@ -211,7 +215,11 @@ export default class TableUtils extends Plugin { // Insert the empty cell only if this slot is not row-spanned from any other cell. if ( colspan > 0 ) { - createEmptyTableCell( writer, insertPosition, colspan > 1 ? { colspan } : null ); + const newCellProperties = Object.assign( {}, cellProperties, { + colspan: colspan > 1 ? colspan : null + } ); + + createEmptyTableCell( writer, insertPosition, newCellProperties ); } // Skip the col-spanned slots, there won't be any cells. @@ -246,12 +254,14 @@ export default class TableUtils extends Plugin { * @param {Object} options * @param {Number} [options.at=0] The column index at which the columns will be inserted. * @param {Number} [options.columns=1] The number of columns to insert. + * @param {Object} [options.defaultCellProperties={}] The default cell properties in the created table. */ insertColumns( table, options = {} ) { const model = this.editor.model; const insertAt = options.at || 0; const columnsToInsert = options.columns || 1; + const cellProperties = options.defaultCellProperties || {}; model.change( writer => { const headingColumns = table.getAttribute( 'headingColumns' ); @@ -266,7 +276,7 @@ export default class TableUtils extends Plugin { // Inserting at the end and at the beginning of a table doesn't require to calculate anything special. if ( insertAt === 0 || tableColumns === insertAt ) { for ( const tableRow of table.getChildren() ) { - createCells( columnsToInsert, writer, writer.createPositionAt( tableRow, insertAt ? 'end' : 0 ) ); + createCells( columnsToInsert, writer, writer.createPositionAt( tableRow, insertAt ? 'end' : 0 ), cellProperties ); } return; @@ -296,7 +306,7 @@ export default class TableUtils extends Plugin { } else { // It's either cell at this column index or spanned cell by a row-spanned cell from row above. // In table above it's cell "e" and a spanned position from row below (empty cell between cells "g" and "h") - createCells( columnsToInsert, writer, tableSlot.getPositionBefore() ); + createCells( columnsToInsert, writer, tableSlot.getPositionBefore(), cellProperties ); } } } ); @@ -477,14 +487,17 @@ export default class TableUtils extends Plugin { * * @param {module:engine/model/element~Element} tableCell * @param {Number} numberOfCells + * @param {Object} [options={}] options + * @param {Object} [options.defaultCellProperties={}] The default cell properties in the created table. */ - splitCellVertically( tableCell, numberOfCells = 2 ) { + splitCellVertically( tableCell, numberOfCells = 2, options = {} ) { const model = this.editor.model; const tableRow = tableCell.parent; const table = tableRow.parent; const rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 ); const colspan = parseInt( tableCell.getAttribute( 'colspan' ) || 1 ); + const defaultCellProperties = options.defaultCellProperties || {}; model.change( writer => { // First check - the cell spans over multiple rows so before doing anything else just split this cell. @@ -494,21 +507,21 @@ export default class TableUtils extends Plugin { updateNumericAttribute( 'colspan', updatedSpan, tableCell, writer ); - // Each inserted cell will have the same attributes: - const newCellsAttributes = {}; + // Each inserted cell will have the same properties. Copy the default ones to avoid modifying references. + const newCellProperties = Object.assign( {}, defaultCellProperties ); // Do not store default value in the model. if ( newCellsSpan > 1 ) { - newCellsAttributes.colspan = newCellsSpan; + newCellProperties.colspan = newCellsSpan; } // Copy rowspan of split cell. if ( rowspan > 1 ) { - newCellsAttributes.rowspan = rowspan; + newCellProperties.rowspan = rowspan; } const cellsToInsert = colspan > numberOfCells ? numberOfCells - 1 : colspan - 1; - createCells( cellsToInsert, writer, writer.createPositionAfter( tableCell ), newCellsAttributes ); + createCells( cellsToInsert, writer, writer.createPositionAfter( tableCell ), newCellProperties ); } // Second check - the cell has colspan of 1 or we need to create more cells then the currently one spans over. @@ -536,17 +549,17 @@ export default class TableUtils extends Plugin { // Second step: create columns after split cell. - // Each inserted cell will have the same attributes: - const newCellsAttributes = {}; + // Each inserted cell will have the same properties. Copy the default ones to avoid modifying references. + const newCellProperties = Object.assign( {}, defaultCellProperties ); // Do not store default value in the model. // Copy rowspan of split cell. if ( rowspan > 1 ) { - newCellsAttributes.rowspan = rowspan; + newCellProperties.rowspan = rowspan; } - createCells( cellsToInsert, writer, writer.createPositionAfter( tableCell ), newCellsAttributes ); + createCells( cellsToInsert, writer, writer.createPositionAfter( tableCell ), newCellProperties ); const headingColumns = table.getAttribute( 'headingColumns' ) || 0; @@ -613,8 +626,10 @@ export default class TableUtils extends Plugin { * * @param {module:engine/model/element~Element} tableCell * @param {Number} numberOfCells + * @param {Object} [options={}] options + * @param {Object} [options.defaultCellProperties={}] The default cell properties in the created table. */ - splitCellHorizontally( tableCell, numberOfCells = 2 ) { + splitCellHorizontally( tableCell, numberOfCells = 2, options = {} ) { const model = this.editor.model; const tableRow = tableCell.parent; @@ -623,6 +638,7 @@ export default class TableUtils extends Plugin { const rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 ); const colspan = parseInt( tableCell.getAttribute( 'colspan' ) || 1 ); + const defaultCellProperties = options.defaultCellProperties || {}; model.change( writer => { // First check - the cell spans over multiple rows so before doing anything else just split this cell. @@ -641,17 +657,17 @@ export default class TableUtils extends Plugin { const { column: cellColumn } = tableMap.find( ( { cell } ) => cell === tableCell ); - // Each inserted cell will have the same attributes: - const newCellsAttributes = {}; + // Each inserted cell will have the same properties. Copy the default ones to avoid modifying references. + const newCellProperties = Object.assign( {}, defaultCellProperties ); // Do not store default value in the model. if ( newCellsSpan > 1 ) { - newCellsAttributes.rowspan = newCellsSpan; + newCellProperties.rowspan = newCellsSpan; } // Copy colspan of split cell. if ( colspan > 1 ) { - newCellsAttributes.colspan = colspan; + newCellProperties.colspan = colspan; } for ( const tableSlot of tableMap ) { @@ -668,7 +684,7 @@ export default class TableUtils extends Plugin { const isInEvenlySplitRow = ( row + splitCellRow + updatedSpan ) % newCellsSpan === 0; if ( isAfterSplitCell && isOnSameColumn && isInEvenlySplitRow ) { - createCells( 1, writer, tableSlot.getPositionBefore(), newCellsAttributes ); + createCells( 1, writer, tableSlot.getPositionBefore(), newCellProperties ); } } } @@ -693,15 +709,15 @@ export default class TableUtils extends Plugin { } } - // Second step: create rows with single cell below split cell. - const newCellsAttributes = {}; + // Second step: create rows with single cell below split cell. Copy the default ones to avoid modifying references. + const newCellProperties = Object.assign( {}, defaultCellProperties ); // Copy colspan of split cell. if ( colspan > 1 ) { - newCellsAttributes.colspan = colspan; + newCellProperties.colspan = colspan; } - createEmptyRows( writer, table, splitCellRow + 1, cellsToInsert, 1, newCellsAttributes ); + createEmptyRows( writer, table, splitCellRow + 1, cellsToInsert, 1, { cellProperties: newCellProperties } ); // Update heading section if split cell is in heading section. const headingRows = table.getAttribute( 'headingRows' ) || 0; @@ -753,13 +769,15 @@ export default class TableUtils extends Plugin { // @param {Number} insertAt The row index of row insertion. // @param {Number} rows The number of rows to create. // @param {Number} tableCellToInsert The number of cells to insert in each row. -function createEmptyRows( writer, table, insertAt, rows, tableCellToInsert, attributes = {} ) { +// @param {Object} [options={}] +// @param {Object} options.cellProperties The cell attributes. +function createEmptyRows( writer, table, insertAt, rows, tableCellToInsert, options = {} ) { for ( let i = 0; i < rows; i++ ) { const tableRow = writer.createElement( 'tableRow' ); writer.insert( tableRow, table, insertAt ); - createCells( tableCellToInsert, writer, writer.createPositionAt( tableRow, 'end' ), attributes ); + createCells( tableCellToInsert, writer, writer.createPositionAt( tableRow, 'end' ), options.cellProperties ); } } diff --git a/packages/ckeditor5-table/src/utils/common.js b/packages/ckeditor5-table/src/utils/common.js index 26ac1a071f5..c304d9cf1d2 100644 --- a/packages/ckeditor5-table/src/utils/common.js +++ b/packages/ckeditor5-table/src/utils/common.js @@ -29,7 +29,7 @@ export function updateNumericAttribute( key, value, item, writer, defaultValue = * * @param {module:engine/model/writer~Writer} writer The model writer. * @param {module:engine/model/position~Position} insertPosition The position at which the table cell should be inserted. - * @param {Object} attributes The element attributes. + * @param {Object} [attributes={}] The element attributes. * @returns {module:engine/model/element~Element} Created table cell. */ export function createEmptyTableCell( writer, insertPosition, attributes = {} ) { diff --git a/packages/ckeditor5-table/tests/_utils/utils.js b/packages/ckeditor5-table/tests/_utils/utils.js index b5fde3991e3..cca2b319967 100644 --- a/packages/ckeditor5-table/tests/_utils/utils.js +++ b/packages/ckeditor5-table/tests/_utils/utils.js @@ -374,9 +374,8 @@ function makeRows( tableData, options ) { delete tableCellData.isSelected; } - let attributes = { - ...defaultCellProperties - }; + // Copy the default properties to avoid modifying references. + let attributes = Object.assign( {}, defaultCellProperties ); if ( asWidget ) { attributes.class = getClassToSet( attributes ); diff --git a/packages/ckeditor5-table/tests/tableutils.js b/packages/ckeditor5-table/tests/tableutils.js index 99d83556161..8d4c165974b 100644 --- a/packages/ckeditor5-table/tests/tableutils.js +++ b/packages/ckeditor5-table/tests/tableutils.js @@ -290,7 +290,7 @@ describe( 'TableUtils', () => { ] ) ); } ); - it( 'should copy structure from the first row', () => { + it( 'should not copy structure from the first row (copyStructureFromAbove=false)', () => { tableUtils.insertRows( root.getNodeByPath( [ 0 ] ), { at: 0, rows: 1, copyStructureFromAbove: false } ); // +----+----+----+----+----+----+ @@ -358,6 +358,171 @@ describe( 'TableUtils', () => { ] ) ); } ); } ); + + describe( 'integration with TableCellPropertiesEditing', () => { + let editor, model, tableUtils, table; + + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + beforeEach( () => { + return ModelTestEditor.create( { + plugins: [ Paragraph, TableEditing, TableUtils, TableCellPropertiesEditing ] + } ).then( newEditor => { + editor = newEditor; + model = editor.model; + tableUtils = editor.plugins.get( TableUtils ); + + // +----+----+----+----+----+----+ + // | 00 | 01 | 03 | 04 | 05 | + // +----+ + +----+----+ + // | 10 | | | 14 | + // +----+----+----+----+----+----+ + // | 20 | 21 | 22 | 23 | 24 | 25 | + // +----+----+----+----+----+----+ + setData( model, modelTable( [ + [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], + [ '10', { contents: '14', colspan: 2 } ], + [ '20', '21', '22', '23', '24', '25' ] + ], { defaultCellProperties: defaultProperties } ) ); + + const root = model.document.getRoot( 'main' ); + table = root.getNodeByPath( [ 0 ] ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( 'should insert a new row and apply default cell properties to all created cells (insert below, single row)', () => { + tableUtils.insertRows( table, { + at: 3, + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+----+ + // | 00 | 01 | 03 | 04 | 05 | + // +----+ + +----+----+ + // | 10 | | | 14 | + // +----+----+----+----+----+----+ + // | 20 | 21 | 22 | 23 | 24 | 25 | + // +----+----+----+----+----+----+ + // | | | | | | | + // +----+----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], + [ '10', { contents: '14', colspan: 2 } ], + [ '20', '21', '22', '23', '24', '25' ], + [ '', '', '', '', '', '' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should insert a new row and apply default cell properties to all created cells (insert below, double row)', () => { + tableUtils.insertRows( table, { + at: 3, + rows: 2, + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+----+ + // | 00 | 01 | 03 | 04 | 05 | + // +----+ + +----+----+ + // | 10 | | | 14 | + // +----+----+----+----+----+----+ + // | 20 | 21 | 22 | 23 | 24 | 25 | + // +----+----+----+----+----+----+ + // | | | | | | | + // +----+----+----+----+----+----+ + // | | | | | | | + // +----+----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], + [ '10', { contents: '14', colspan: 2 } ], + [ '20', '21', '22', '23', '24', '25' ], + [ '', '', '', '', '', '' ], + [ '', '', '', '', '', '' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should insert a new row and apply default cell properties to all created cells (insert above, single row)', () => { + tableUtils.insertRows( table, { + at: 0, + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+----+ + // | | | | | | | + // +----+----+----+----+----+----+ + // | 00 | 01 | 03 | 04 | 05 | + // +----+ + +----+----+ + // | 10 | | | 14 | + // +----+----+----+----+----+----+ + // | 20 | 21 | 22 | 23 | 24 | 25 | + // +----+----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '', '', '', '', '', '' ], + [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], + [ '10', { contents: '14', colspan: 2 } ], + [ '20', '21', '22', '23', '24', '25' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should insert a new row and apply default cell properties to all created cells (insert above, double row)', () => { + tableUtils.insertRows( table, { + at: 0, + rows: 2, + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+----+ + // | | | | | | | + // +----+----+----+----+----+----+ + // | | | | | | | + // +----+----+----+----+----+----+ + // | 00 | 01 | 03 | 04 | 05 | + // +----+ + +----+----+ + // | 10 | | | 14 | + // +----+----+----+----+----+----+ + // | 20 | 21 | 22 | 23 | 24 | 25 | + // +----+----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '', '', '', '', '', '' ], + [ '', '', '', '', '', '' ], + [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], + [ '10', { contents: '14', colspan: 2 } ], + [ '20', '21', '22', '23', '24', '25' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should insert a new row and apply default cell properties to all created cells (insert in the middle, single row)', () => { + tableUtils.insertRows( table, { + at: 1, + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+----+ + // | 00 | 01 | 03 | 04 | 05 | + // +----+ + +----+----+ + // | | | | | | + // +----+ + +----+----+ + // | 10 | | | 14 | + // +----+----+----+----+----+----+ + // | 20 | 21 | 22 | 23 | 24 | 25 | + // +----+----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '00', { contents: '01', colspan: 2, rowspan: 3 }, { contents: '03', rowspan: 3 }, '04', '05' ], + [ '', '', '' ], + [ '10', { contents: '14', colspan: 2 } ], + [ '20', '21', '22', '23', '24', '25' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + } ); } ); describe( 'insertColumns()', () => { @@ -599,6 +764,132 @@ describe( 'TableUtils', () => { [ '', '32' ] ], { headingColumns: 3 } ) ); } ); + + describe( 'integration with TableCellPropertiesEditing', () => { + let editor, model, tableUtils, table; + + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + beforeEach( () => { + return ModelTestEditor.create( { + plugins: [ Paragraph, TableEditing, TableUtils, TableCellPropertiesEditing ] + } ).then( newEditor => { + editor = newEditor; + model = editor.model; + tableUtils = editor.plugins.get( TableUtils ); + + // +----+----+----+----+----+ + // | 00 | 01 | 03 | 04 | + // +----+ + +----+ + // | 10 | | | 14 | + // +----+----+----+----+----+ + setData( model, modelTable( [ + [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], + [ '10', '14' ] + ], { defaultCellProperties: defaultProperties } ) ); + + const root = model.document.getRoot( 'main' ); + table = root.getNodeByPath( [ 0 ] ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( 'should insert a new column and apply default cell properties to all created cells (insert right, single column)', () => { + tableUtils.insertColumns( table, { + at: 5, + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+----+ + // | 00 | 01 | 03 | 04 | | + // +----+ + +----+----+ + // | 10 | | | 14 | | + // +----+----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '' ], + [ '10', '14', '' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should insert a new column and apply default cell properties to all created cells (insert right, double column)', () => { + tableUtils.insertColumns( table, { + at: 5, + columns: 2, + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+----+----+ + // | 00 | 01 | 03 | 04 | | | + // +----+ + +----+----+----+ + // | 10 | | | 14 | | | + // +----+----+----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '', '' ], + [ '10', '14', '', '' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should insert a new column and apply default cell properties to all created cells (insert left, single column)', () => { + tableUtils.insertColumns( table, { + at: 0, + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+----+ + // | | 00 | 01 | 03 | 04 | + // +----+----+ + +----+ + // | | 10 | | | 14 | + // +----+----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '', '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], + [ '', '10', '14' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should insert a new column and apply default cell properties to all created cells (insert left, double column)', () => { + tableUtils.insertColumns( table, { + at: 0, + columns: 2, + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+----+----+ + // | | | 00 | 01 | 03 | 04 | + // +----+----+----+ + +----+ + // | | | 10 | | | 14 | + // +----+----+----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '', '', '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], + [ '', '', '10', '14' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should insert a new row and apply default cell properties to all created cells (insert in the middle, single row)', () => { + tableUtils.insertColumns( table, { + at: 3, + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+----+ + // | 00 | 01 | | 03 | 04 | + // +----+ +----+ +----+ + // | 10 | | | | 14 | + // +----+----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '00', { contents: '01', colspan: 2, rowspan: 2 }, '', { contents: '03', rowspan: 2 }, '04' ], + [ '10', '', '14' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + } ); } ); describe( 'splitCellVertically()', () => { @@ -743,6 +1034,122 @@ describe( 'TableUtils', () => { [ '10[]', '', '', '11' ] ], { headingColumns: 3 } ) ); } ); + + describe( 'integration with TableCellPropertiesEditing', () => { + let editor, model, tableUtils, root; + + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + beforeEach( () => { + return ModelTestEditor.create( { + plugins: [ Paragraph, TableEditing, TableUtils, TableCellPropertiesEditing ] + } ).then( newEditor => { + editor = newEditor; + model = editor.model; + tableUtils = editor.plugins.get( TableUtils ); + root = model.document.getRoot( 'main' ); + } ); + } ); + + afterEach( () => { + // The `defaultProperties` object should not be modified. + // All values should be copied to a new object while preparing a cell element. + expect( defaultProperties ).to.not.have.property( 'colspan' ); + expect( defaultProperties ).to.not.have.property( 'rowspan' ); + expect( defaultProperties ).to.have.property( 'borderStyle' ); + expect( defaultProperties ).to.have.property( 'borderWidth' ); + expect( defaultProperties ).to.have.property( 'borderColor' ); + expect( defaultProperties ).to.have.property( 'horizontalAlignment' ); + expect( defaultProperties ).to.have.property( 'verticalAlignment' ); + + return editor.destroy(); + } ); + + it( 'should properly split the column and apply default cell properties (colspan=2, cells=2)', () => { + // +----+----+----+----+ + // | 00 | 01 | 03 | + // +----+----+----+----+ + setData( model, modelTable( [ + [ '00', { contents: '[]01', colspan: 2 }, '03' ] + ], { defaultCellProperties: defaultProperties } ) ); + + const tableCell = root.getNodeByPath( [ 0, 0, 1 ] ); + + tableUtils.splitCellVertically( tableCell, 2, { + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+ + // | 00 | 01 | | 03 | + // +----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '00', '01', '', '03' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should properly split the column and apply default cell properties (colspan=4, cells=2)', () => { + // +----+----+----+----+----+----+ + // | 00 | 01 | 05 | + // +----+----+----+----+----+----+ + setData( model, modelTable( [ + [ '00', { contents: '[]01', colspan: 4 }, '05' ] + ], { defaultCellProperties: defaultProperties } ) ); + + const tableCell = root.getNodeByPath( [ 0, 0, 1 ] ); + + tableUtils.splitCellVertically( tableCell, 2, { + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+----+ + // | 00 | 01 | | 05 | + // +----+----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '00', { contents: '01', colspan: 2 }, { contents: '', colspan: 2 }, '05' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should properly split the column and apply default cell properties (colspan=2, rowspan=2, cells=3)', () => { + // +----+----+----+----+----+ + // | 00 | 01 | 03 | 04 | + // +----+ + +----+ + // | 10 | | | 14 | + // +----+----+----+----+----+ + setData( model, modelTable( [ + [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], + [ '10', '14' ] + ], { defaultCellProperties: defaultProperties } ) ); + + const tableCell = root.getNodeByPath( [ 0, 0, 1 ] ); + + tableUtils.splitCellVertically( tableCell, 3, { + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+----+ + // | 00 | 01 | | | 03 | 04 | + // +----+ + + + +----+ + // | 10 | | | | | 14 | + // +----+----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ + '00', + { contents: '01', rowspan: 2 }, + { contents: '', rowspan: 2 }, + { contents: '', rowspan: 2 }, + { contents: '03', rowspan: 2 }, + '04' + ], + [ '10', '14' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + } ); } ); describe( 'splitCellHorizontally()', () => { @@ -918,6 +1325,173 @@ describe( 'TableUtils', () => { [ '20', '21', '22' ] ], { headingRows: 3 } ) ); } ); + + describe( 'integration with TableCellPropertiesEditing', () => { + let editor, model, tableUtils, root; + + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + beforeEach( () => { + return ModelTestEditor.create( { + plugins: [ Paragraph, TableEditing, TableUtils, TableCellPropertiesEditing ] + } ).then( newEditor => { + editor = newEditor; + model = editor.model; + tableUtils = editor.plugins.get( TableUtils ); + root = model.document.getRoot( 'main' ); + } ); + } ); + + afterEach( () => { + // The `defaultProperties` object should not be modified. + // All values should be copied to a new object while preparing a cell element. + expect( defaultProperties ).to.not.have.property( 'colspan' ); + expect( defaultProperties ).to.not.have.property( 'rowspan' ); + expect( defaultProperties ).to.have.property( 'borderStyle' ); + expect( defaultProperties ).to.have.property( 'borderWidth' ); + expect( defaultProperties ).to.have.property( 'borderColor' ); + expect( defaultProperties ).to.have.property( 'horizontalAlignment' ); + expect( defaultProperties ).to.have.property( 'verticalAlignment' ); + + return editor.destroy(); + } ); + + it( 'should properly split the column and apply default cell properties (rowspan=2, cells=2)', () => { + // +----+ + // | 00 | + // +----+ + // | 01 | + // + + + // | | + // +----+ + // | 03 | + // +----+ + setData( model, modelTable( [ + [ '00' ], + [ { contents: '[]01', rowspan: 2 } ], + [], + [ '03' ] + ], { defaultCellProperties: defaultProperties } ) ); + + const tableCell = root.getNodeByPath( [ 0, 1, 0 ] ); + + tableUtils.splitCellHorizontally( tableCell, 2, { + defaultCellProperties: defaultProperties + } ); + + // +----+ + // | 00 | + // +----+ + // | 01 | + // +----+ + // | | + // +----+ + // | 03 | + // +----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '00' ], + [ '01' ], + [ '' ], + [ '03' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should properly split the column and apply default cell properties (rowspan=4, cells=2)', () => { + // +----+ + // | 00 | + // +----+ + // | 01 | + // + + + // | | + // + + + // | | + // + + + // | | + // +----+ + // | 05 | + // +----+ + setData( model, modelTable( [ + [ '00' ], + [ { contents: '[]01', rowspan: 4 } ], + [], + [], + [], + [ '05' ] + ], { defaultCellProperties: defaultProperties } ) ); + + const tableCell = root.getNodeByPath( [ 0, 1, 0 ] ); + + tableUtils.splitCellHorizontally( tableCell, 2, { + defaultCellProperties: defaultProperties + } ); + + // +----+ + // | 00 | + // +----+ + // | 01 | + // + + + // | | + // +----+ + // | | + // + + + // | | + // +----+ + // | 05 | + // +----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ '00' ], + [ { contents: '01', rowspan: 2 } ], + [], + [ { contents: '', rowspan: 2 } ], + [], + [ '05' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should properly split the column and apply default cell properties (colspan=2, rowspan=2, cells=3)', () => { + // +----+----+----+----+----+ + // | 00 | 01 | 03 | 04 | + // +----+ + +----+ + // | 10 | | | 14 | + // +----+----+----+----+----+ + setData( model, modelTable( [ + [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], + [ '10', '14' ] + ], { defaultCellProperties: defaultProperties } ) ); + + const tableCell = root.getNodeByPath( [ 0, 0, 1 ] ); + + tableUtils.splitCellHorizontally( tableCell, 3, { + defaultCellProperties: defaultProperties + } ); + + // +----+----+----+----+----+ + // | 00 | 01 | 03 | 04 | + // + +----+----+ + + + // | | | | | + // +----+----+----+ +----+ + // | 10 | | | 14 | + // +----+----+----+----+----+ + assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ + [ + { contents: '00', rowspan: 2 }, + { contents: '01', colspan: 2 }, + { contents: '03', rowspan: 3 }, + { contents: '04', rowspan: 2 } + ], + [ + { contents: '', colspan: 2 } + ], + [ '10', { contents: '', colspan: 2 }, '14' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + } ); } ); describe( 'getColumns()', () => { From 149858d3f36d8d01e9ef8d00efe006d3d6977afc Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Wed, 31 Mar 2021 10:23:31 +0200 Subject: [PATCH 08/24] The table layout post-fixer uses the default cell properties. --- .../src/converters/table-layout-post-fixer.js | 32 ++++++--- packages/ckeditor5-table/src/tableediting.js | 2 +- .../converters/table-layout-post-fixer.js | 72 +++++++++++++++++++ 3 files changed, 97 insertions(+), 9 deletions(-) diff --git a/packages/ckeditor5-table/src/converters/table-layout-post-fixer.js b/packages/ckeditor5-table/src/converters/table-layout-post-fixer.js index 7eb5fda0f52..19a63ecb543 100644 --- a/packages/ckeditor5-table/src/converters/table-layout-post-fixer.js +++ b/packages/ckeditor5-table/src/converters/table-layout-post-fixer.js @@ -211,18 +211,20 @@ import { createEmptyTableCell, updateNumericAttribute } from '../utils/common'; * * * - * @param {module:engine/model/model~Model} model + * @param {module:core/editor/editor~Editor} editor */ -export default function injectTableLayoutPostFixer( model ) { - model.document.registerPostFixer( writer => tableLayoutPostFixer( writer, model ) ); +export default function injectTableLayoutPostFixer( editor ) { + editor.model.document.registerPostFixer( writer => tableLayoutPostFixer( writer, editor ) ); } // The table layout post-fixer. // // @param {module:engine/model/writer~Writer} writer -// @param {module:engine/model/model~Model} model -function tableLayoutPostFixer( writer, model ) { +// @param {module:core/editor/editor~Editor} editor +function tableLayoutPostFixer( writer, editor ) { + const model = editor.model; const changes = model.document.differ.getChanges(); + const cellProperties = getDefaultCellProperties( editor ); let wasFixed = false; @@ -251,7 +253,7 @@ function tableLayoutPostFixer( writer, model ) { // The wasFixed flag should be true if any of tables in batch was fixed - might be more then one. wasFixed = fixTableCellsRowspan( table, writer ) || wasFixed; // Step 2: fix table rows sizes. - wasFixed = fixTableRowsSizes( table, writer ) || wasFixed; + wasFixed = fixTableRowsSizes( table, writer, cellProperties ) || wasFixed; analyzedTables.add( table ); } @@ -287,8 +289,9 @@ function fixTableCellsRowspan( table, writer ) { // // @param {module:engine/model/element~Element} table // @param {module:engine/model/writer~Writer} writer +// @param {Object} cellProperties Default for created cells. // @returns {Boolean} Returns `true` if the table was fixed. -function fixTableRowsSizes( table, writer ) { +function fixTableRowsSizes( table, writer, cellProperties ) { let wasFixed = false; const rowsLengths = getRowsLengths( table ); @@ -328,7 +331,7 @@ function fixTableRowsSizes( table, writer ) { if ( columnsToInsert ) { for ( let i = 0; i < columnsToInsert; i++ ) { - createEmptyTableCell( writer, writer.createPositionAt( table.getChild( rowIndex ), 'end' ) ); + createEmptyTableCell( writer, writer.createPositionAt( table.getChild( rowIndex ), 'end' ), cellProperties ); } wasFixed = true; @@ -397,3 +400,16 @@ function isTableAttributeEntry( entry ) { return isAttributeType && ( key === 'headingRows' || key === 'colspan' || key === 'rowspan' ); } + +// Returns the default cell properties if the `TableCellPropertiesEditing` plugin is enabled. +// Otherwise, returns an empty object. +// +// @param {module:core/editor/editor~Editor} editor +// @returns {Object} +function getDefaultCellProperties( editor ) { + if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { + return editor.config.get( 'table.tableCellProperties.defaultProperties' ); + } + + return {}; +} diff --git a/packages/ckeditor5-table/src/tableediting.js b/packages/ckeditor5-table/src/tableediting.js index 4770ba9ff33..73fe762311a 100644 --- a/packages/ckeditor5-table/src/tableediting.js +++ b/packages/ckeditor5-table/src/tableediting.js @@ -153,7 +153,7 @@ export default class TableEditing extends Plugin { editor.commands.add( 'selectTableColumn', new SelectColumnCommand( editor ) ); injectTableHeadingRowsRefreshPostFixer( model ); - injectTableLayoutPostFixer( model ); + injectTableLayoutPostFixer( editor ); injectTableCellRefreshPostFixer( model, editor.editing.mapper ); injectTableCellParagraphPostFixer( model ); } diff --git a/packages/ckeditor5-table/tests/converters/table-layout-post-fixer.js b/packages/ckeditor5-table/tests/converters/table-layout-post-fixer.js index 220cb933eb8..7eb0b8db762 100644 --- a/packages/ckeditor5-table/tests/converters/table-layout-post-fixer.js +++ b/packages/ckeditor5-table/tests/converters/table-layout-post-fixer.js @@ -11,6 +11,7 @@ import TableEditing from '../../src/tableediting'; import { modelTable } from './../_utils/utils'; import UndoEditing from '@ckeditor/ckeditor5-undo/src/undoediting'; import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils'; +import TableCellPropertiesEditing from '../../src/tablecellproperties/tablecellpropertiesediting'; describe( 'Table layout post-fixer', () => { let editor, model, root; @@ -198,6 +199,77 @@ describe( 'Table layout post-fixer', () => { expect( getModelData( model, { withoutSelection: true } ) ).to.equal( '' ); } ); + + describe( 'integration with TableCellPropertiesEditing', () => { + let editor, model, root; + + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + beforeEach( () => { + return VirtualTestEditor + .create( { + plugins: [ TableEditing, Paragraph, UndoEditing, TableCellPropertiesEditing ], + table: { + tableCellProperties: { + defaultProperties + } + } + } ) + .then( newEditor => { + editor = newEditor; + model = editor.model; + root = model.document.getRoot(); + } ); + } ); + + afterEach( () => { + editor.destroy(); + } ); + + it( 'should add missing columns to tableRows that are shorter then the longest table row', () => { + const parsed = parse( modelTable( [ + [ '00' ], + [ '10', '11', '12' ], + [ '20', '21' ] + ], { defaultCellProperties: defaultProperties } ), model.schema ); + + model.change( writer => { + writer.remove( writer.createRangeIn( root ) ); + writer.insert( parsed, root ); + } ); + + assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [ + [ '00', '', '' ], + [ '10', '11', '12' ], + [ '20', '21', '' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + + it( 'should add missing columns to tableRows that are shorter then the longest table row (complex 2)', () => { + const parsed = parse( modelTable( [ + [ { colspan: 6, contents: '00' } ], + [ { rowspan: 2, contents: '10' }, '11', { colspan: 3, contents: '12' } ], + [ '21', '22' ] + ], { defaultCellProperties: defaultProperties } ), model.schema ); + + model.change( writer => { + writer.remove( writer.createRangeIn( root ) ); + writer.insert( parsed, root ); + } ); + + assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [ + [ { colspan: 6, contents: '00' } ], + [ { rowspan: 2, contents: '10' }, '11', { colspan: 3, contents: '12' }, '' ], + [ '21', '22', '', '', '' ] + ], { defaultCellProperties: defaultProperties } ) ); + } ); + } ); } ); describe( 'on collaboration', () => { From 3607d42d1d0320b531a3416618dbcf0c6fec4029 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Wed, 31 Mar 2021 10:25:25 +0200 Subject: [PATCH 09/24] Restored .travis.yml --- .travis.yml | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index b6767069be0..1ff046bb416 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,20 +19,19 @@ before_install: install: - yarn install # The "./manual/all-features-dll.js" test requires building DLL. -#- yarn run dll:build +- yarn run dll:build script: -- echo "Testing. Do not trigger the full build." -#- node ./scripts/continuous-integration-script.js -#- yarn run lint -#- yarn run stylelint -#- ./scripts/check-manual-tests.sh -r ckeditor5 -f ckeditor5 -#- yarn run docs --strict -#- 'if [ $TRAVIS_TEST_RESULT -eq 0 ]; then -# travis_wait 30 yarn run docs:build-and-publish-nightly; -# fi' +- node ./scripts/continuous-integration-script.js +- yarn run lint +- yarn run stylelint +- ./scripts/check-manual-tests.sh -r ckeditor5 -f ckeditor5 +- yarn run docs --strict +- 'if [ $TRAVIS_TEST_RESULT -eq 0 ]; then + travis_wait 30 yarn run docs:build-and-publish-nightly; + fi' after_script: - export END_TIME=$( date +%s ) -#- ckeditor5-dev-tests-notify-travis-status +- ckeditor5-dev-tests-notify-travis-status env: global: - secure: RO140EQDHmEOPJPikk8eCY5IdHpnEKGm41p5U1ewAbeZv1DpCG+rSumR2JdYl75kFAaZvCSm1NuVMM+kmYd+/z+LQbKj7QH5G/UHNho3H89blIU6WlJhT0YR5vclm9rvnEvOtxnfODca1Qrw+CaCoJks2o4VYbJB7mOBVNsh7Bc= From 072100de5fd0ff746c8a27ce7ba9977c945178af Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Wed, 31 Mar 2021 10:33:59 +0200 Subject: [PATCH 10/24] Updated the table properties manual tests (included default props). --- .../tests/manual/tableproperties.js | 17 +++++----- .../tests/manual/tableproperties.md | 33 +++++++++++++++++++ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/packages/ckeditor5-table/tests/manual/tableproperties.js b/packages/ckeditor5-table/tests/manual/tableproperties.js index 065c8da2132..fd5464f5eb5 100644 --- a/packages/ckeditor5-table/tests/manual/tableproperties.js +++ b/packages/ckeditor5-table/tests/manual/tableproperties.js @@ -26,24 +26,23 @@ ClassicEditor 'heading', '|', 'insertTable', '|', 'bold', 'italic', 'bulletedList', 'numberedList', 'blockQuote', 'undo', 'redo' ], table: { - // TODO (pomek): Please, rollback these changes or update the manual test. contentToolbar: [ 'tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties' ], tableToolbar: [ 'bold', 'italic' ], tableProperties: { defaultProperties: { - alignment: 'left', - borderColor: '#ff0000', - borderWidth: '2px', - borderStyle: 'dashed' + borderStyle: 'dashed', + borderColor: 'hsl(0, 0%, 60%)', + borderWidth: '3px', + alignment: 'left' } }, tableCellProperties: { defaultProperties: { - horizontalAlignment: 'right', - verticalAlignment: 'bottom', - borderColor: '#0000ff', + borderStyle: 'dotted', + borderColor: 'hsl(120, 75%, 60%)', borderWidth: '2px', - borderStyle: 'dotted' + horizontalAlignment: 'right', + verticalAlignment: 'bottom' } } } diff --git a/packages/ckeditor5-table/tests/manual/tableproperties.md b/packages/ckeditor5-table/tests/manual/tableproperties.md index 7b9976425dd..4a9c94db660 100644 --- a/packages/ckeditor5-table/tests/manual/tableproperties.md +++ b/packages/ckeditor5-table/tests/manual/tableproperties.md @@ -10,3 +10,36 @@ The editor should be loaded with tables: Compare their visual styles with the ones beside the editor. Most of the styles should be preserved. **Note**: Not all styles are preserved (i.e. the column height/width in the second GDocs table). Also note that the original table might have a different cell padding. + +After all, clear the editor before starting checking the default table and cell properties. + +### Default table properties + +After inserting a new table, the default styles (printed below) should be applied to the table automatically: + +```json +{ + "borderStyle": "dashed", + "borderColor": "hsl(0, 0%, 60%)", + "borderWidth": "3px", + "alignment": "left" +} +``` + +Use the `Table properties` icon in the table toolbar and compare values. + +### Default cells properties + +After inserting a new table, the default styles (printed below) should be applied to all cells automatically: + +```json +{ + "borderStyle": "dotted", + "borderColor": "hsl(120, 75%, 60%)", + "borderWidth": "2px", + "horizontalAlignment": "right", + "verticalAlignment": "bottom" +} +``` + +Use the `Cell properties` icon in the table toolbar and compare values. From eddf6af3ad677628f79391ccf22a165a6dbb7663 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Wed, 31 Mar 2021 11:23:24 +0200 Subject: [PATCH 11/24] Docs for the default table/cell properties. --- .../features/table-default-properties.html | 1 + .../features/table-default-properties.js | 55 +++++++++++++++++++ .../ckeditor5-table/docs/features/table.md | 39 +++++++++++++ .../src/tablecellproperties.js | 13 ++++- .../ckeditor5-table/src/tableproperties.js | 10 ++++ 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 packages/ckeditor5-table/docs/_snippets/features/table-default-properties.html create mode 100644 packages/ckeditor5-table/docs/_snippets/features/table-default-properties.js diff --git a/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.html b/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.html new file mode 100644 index 00000000000..8d2f6837ee2 --- /dev/null +++ b/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.html @@ -0,0 +1 @@ +
diff --git a/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.js b/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.js new file mode 100644 index 00000000000..c8805ba8cd0 --- /dev/null +++ b/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.js @@ -0,0 +1,55 @@ +/** + * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +/* globals ClassicEditor, CKEditorPlugins, console, window, document */ + +ClassicEditor + .create( document.querySelector( '#snippet-default-properties' ), { + extraPlugins: [ + CKEditorPlugins.TableProperties, + CKEditorPlugins.TableCellProperties + ], + table: { + contentToolbar: [ 'tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties' ], + tableProperties: { + defaultProperties: { + borderStyle: 'dashed', + borderColor: 'hsl(0, 0%, 60%)', + borderWidth: '3px', + alignment: 'left' + } + }, + tableCellProperties: { + defaultProperties: { + borderStyle: 'dotted', + borderColor: 'hsl(120, 75%, 60%)', + borderWidth: '2px', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + } + } + }, + image: { + toolbar: [ + 'imageStyle:full', + 'imageStyle:side', + '|', + 'imageTextAlternative' + ] + }, + placeholder: 'Insert the new table with applied the default styles.' + } ) + .then( editor => { + window.editorDefaultStyles = editor; + + window.attachTourBalloon( { + target: window.findToolbarItem( editor.ui.view.toolbar, 0 ), + text: 'Click to insert the new table.', + editor + } ); + } ) + .catch( err => { + console.error( err.stack ); + } ); diff --git a/packages/ckeditor5-table/docs/features/table.md b/packages/ckeditor5-table/docs/features/table.md index ae69d287ce5..cdd36d515b7 100644 --- a/packages/ckeditor5-table/docs/features/table.md +++ b/packages/ckeditor5-table/docs/features/table.md @@ -205,6 +205,45 @@ ClassicEditor .catch( ... ); ``` +### Default table and cell styles + +You can specify the default styles for the table and cells that will be applied while creating the new table by passing the `defaultProperties` object to {@link module:table/table~TableConfig#tableProperties} for tables, and {@link module:table/table~TableConfig#tableCellProperties} for cells. + +```js +const tableConfig = { + table: { + tableProperties: { + // The default styles for new tables. + defaultProperties: { + borderStyle: 'dashed', + borderColor: 'hsl(0, 0%, 60%)', + borderWidth: '3px', + alignment: 'left' + } + }, + + tableCellProperties: { + // The default styles for each cell inside the created table. + defaultProperties: { + borderStyle: 'dotted', + borderColor: 'hsl(120, 75%, 60%)', + borderWidth: '2px', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + } + } + } +}; +``` + +Read more about supported values in {@link module:table/table~TableConfig}. + +{@snippet features/table-default-properties} + + + The default table and cell styles **do not** impact the {@link builds/guides/integration/basic-api#setting-the-editor-data data loaded into the editor}. They are used only when creating the new table. + + ## Block vs inline content in table cells The table feature allows creating block content (like paragraphs, lists, headings, etc.) in table cells. However, if a table cell contains just one paragraph and this paragraph has no special attributes (like text alignment), the cell content is considered "inline" and the paragraph is not rendered. diff --git a/packages/ckeditor5-table/src/tablecellproperties.js b/packages/ckeditor5-table/src/tablecellproperties.js index ca481e90df9..a866759103c 100644 --- a/packages/ckeditor5-table/src/tablecellproperties.js +++ b/packages/ckeditor5-table/src/tablecellproperties.js @@ -73,11 +73,22 @@ export default class TableCellProperties extends Plugin { * borderColor: 'hsl(120, 75%, 60%)', * borderWidth: '2px', * horizontalAlignment: 'right', - * verticalAlignment: 'bottom' + * verticalAlignment: 'bottom' * } * } * } * + * The following properties are supported: + * + * * `backgroundColor` – sets the cell background color + * * `borderColor` – sets the border color + * * `borderStyle` – sets the border style + * * `borderWidth` – sets the border width + * * `height` – sets the cell height + * * `horizontalAlignment` – sets the cell horizontal alignment + * * `verticalAlignment` – sets the cell vertical alignment + * * `width` – sets the cell width + * * **Note**: The configurations do not impact the data loaded into the editor, * i.e. they do not limit or filter the colors in the data. They are used only in the user interface * allowing users to pick colors in a more convenient way. diff --git a/packages/ckeditor5-table/src/tableproperties.js b/packages/ckeditor5-table/src/tableproperties.js index 5ce4d0b695d..96d5961cd86 100644 --- a/packages/ckeditor5-table/src/tableproperties.js +++ b/packages/ckeditor5-table/src/tableproperties.js @@ -78,6 +78,16 @@ export default class TableProperties extends Plugin { * } * } * + * The following properties are supported: + * + * * `alignment` – sets the table alignment + * * `backgroundColor` – sets the table background color + * * `borderColor` – sets the border color + * * `borderStyle` – sets the border style + * * `borderWidth` – sets the border width + * * `height` – sets the table height + * * `width` – sets the table width + * * **Note**: The configurations do not impact the data loaded into the editor, * i.e. they do not limit or filter the colors in the data. They are used only in the user interface * allowing users to pick colors in a more convenient way. From fa5f455ddd49961d907f1e94fd65bd9c8c1dcf9a Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Wed, 31 Mar 2021 11:45:51 +0200 Subject: [PATCH 12/24] Removed default values for attributes/options. --- packages/ckeditor5-table/src/tableutils.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/ckeditor5-table/src/tableutils.js b/packages/ckeditor5-table/src/tableutils.js index dc397d351c2..b6ded312c0d 100644 --- a/packages/ckeditor5-table/src/tableutils.js +++ b/packages/ckeditor5-table/src/tableutils.js @@ -769,9 +769,9 @@ export default class TableUtils extends Plugin { // @param {Number} insertAt The row index of row insertion. // @param {Number} rows The number of rows to create. // @param {Number} tableCellToInsert The number of cells to insert in each row. -// @param {Object} [options={}] +// @param {Object} options // @param {Object} options.cellProperties The cell attributes. -function createEmptyRows( writer, table, insertAt, rows, tableCellToInsert, options = {} ) { +function createEmptyRows( writer, table, insertAt, rows, tableCellToInsert, options ) { for ( let i = 0; i < rows; i++ ) { const tableRow = writer.createElement( 'tableRow' ); @@ -786,7 +786,8 @@ function createEmptyRows( writer, table, insertAt, rows, tableCellToInsert, opti // @param {Number} columns The number of columns to create // @param {module:engine/model/writer~Writer} writer // @param {module:engine/model/position~Position} insertPosition -function createCells( cells, writer, insertPosition, attributes = {} ) { +// @param {Object} attributes The cell attributes. +function createCells( cells, writer, insertPosition, attributes ) { for ( let i = 0; i < cells; i++ ) { createEmptyTableCell( writer, insertPosition, attributes ); } From 912cb064cd7aaad47a6d193b6b74de4193414ad5 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Wed, 31 Mar 2021 18:30:53 +0200 Subject: [PATCH 13/24] Fixed tabs in API docs. --- packages/ckeditor5-table/src/tablecellproperties.js | 10 +++++----- packages/ckeditor5-table/src/tableproperties.js | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/ckeditor5-table/src/tablecellproperties.js b/packages/ckeditor5-table/src/tablecellproperties.js index a866759103c..eca37ccc014 100644 --- a/packages/ckeditor5-table/src/tablecellproperties.js +++ b/packages/ckeditor5-table/src/tablecellproperties.js @@ -69,11 +69,11 @@ export default class TableCellProperties extends Plugin { * const tableConfig = { * tableCellProperties: { * defaultProperties: { - * borderStyle: 'dotted', - * borderColor: 'hsl(120, 75%, 60%)', - * borderWidth: '2px', - * horizontalAlignment: 'right', - * verticalAlignment: 'bottom' + * borderStyle: 'dotted', + * borderColor: 'hsl(120, 75%, 60%)', + * borderWidth: '2px', + * horizontalAlignment: 'right', + * verticalAlignment: 'bottom' * } * } * } diff --git a/packages/ckeditor5-table/src/tableproperties.js b/packages/ckeditor5-table/src/tableproperties.js index 96d5961cd86..1ded0939aa7 100644 --- a/packages/ckeditor5-table/src/tableproperties.js +++ b/packages/ckeditor5-table/src/tableproperties.js @@ -70,10 +70,10 @@ export default class TableProperties extends Plugin { * const tableConfig = { * tableProperties: { * defaultProperties: { - * borderStyle: 'dashed', - * borderColor: 'hsl(0, 0%, 90%)', - * borderWidth: '3px', - * alignment: 'left' + * borderStyle: 'dashed', + * borderColor: 'hsl(0, 0%, 90%)', + * borderWidth: '3px', + * alignment: 'left' * } * } * } From 0a1201dd814b82d48daf0c40d043213aa831fffa Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Thu, 8 Apr 2021 09:20:29 +0200 Subject: [PATCH 14/24] Added the default table/cell properties to API docs. --- packages/ckeditor5-table/src/tablecellproperties.js | 8 ++++++++ packages/ckeditor5-table/src/tableproperties.js | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/packages/ckeditor5-table/src/tablecellproperties.js b/packages/ckeditor5-table/src/tablecellproperties.js index eca37ccc014..88e8521cc95 100644 --- a/packages/ckeditor5-table/src/tablecellproperties.js +++ b/packages/ckeditor5-table/src/tablecellproperties.js @@ -89,6 +89,14 @@ export default class TableCellProperties extends Plugin { * * `verticalAlignment` – sets the cell vertical alignment * * `width` – sets the cell width * + * The {@link module:table/tablecellproperties/tablecellpropertiesediting~TableCellPropertiesEditing} plugin defines the default cell + * properties as specified below: + * + * { + * "horizontalAlignment": "center", + * "verticalAlignment": "middle" + * } + * * **Note**: The configurations do not impact the data loaded into the editor, * i.e. they do not limit or filter the colors in the data. They are used only in the user interface * allowing users to pick colors in a more convenient way. diff --git a/packages/ckeditor5-table/src/tableproperties.js b/packages/ckeditor5-table/src/tableproperties.js index 1ded0939aa7..b061f2056b8 100644 --- a/packages/ckeditor5-table/src/tableproperties.js +++ b/packages/ckeditor5-table/src/tableproperties.js @@ -88,6 +88,13 @@ export default class TableProperties extends Plugin { * * `height` – sets the table height * * `width` – sets the table width * + * The {@link module:table/tableproperties/tablepropertiesediting~TablePropertiesEditing} plugin defines the default table + * properties as specified below: + * + * { + * "alignment": "center" + * } + * * **Note**: The configurations do not impact the data loaded into the editor, * i.e. they do not limit or filter the colors in the data. They are used only in the user interface * allowing users to pick colors in a more convenient way. From e245caf22f71165ecc3876a914529261d106fe9c Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Thu, 8 Apr 2021 09:49:12 +0200 Subject: [PATCH 15/24] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jacek Bogdański --- packages/ckeditor5-table/docs/features/table.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ckeditor5-table/docs/features/table.md b/packages/ckeditor5-table/docs/features/table.md index 50642c17d7e..666a679be9f 100644 --- a/packages/ckeditor5-table/docs/features/table.md +++ b/packages/ckeditor5-table/docs/features/table.md @@ -207,7 +207,7 @@ ClassicEditor ### Default table and cell styles -You can specify the default styles for the table and cells that will be applied while creating the new table by passing the `defaultProperties` object to {@link module:table/table~TableConfig#tableProperties} for tables, and {@link module:table/table~TableConfig#tableCellProperties} for cells. +You can specify the default styles for the table and cells that will be applied while creating a new table. To configure default table styles, pass the `defaultProperties` object to {@link module:table/table~TableConfig#tableProperties} configuration option. Similarly, cell styles can be configured by setting `defaultProperties` on {@link module:table/table~TableConfig#tableCellProperties} option. ```js const tableConfig = { From c7b23f2fc23838865fb34a4f228cbf2d737e3a83 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Thu, 8 Apr 2021 10:33:16 +0200 Subject: [PATCH 16/24] Removed the "default" word from tableProperties and cellProperties. From table/cell PoV they are just "properties". --- .../src/commands/insertcolumncommand.js | 2 +- .../src/commands/insertrowcommand.js | 2 +- .../src/commands/inserttablecommand.js | 4 +- .../src/commands/splitcellcommand.js | 2 +- packages/ckeditor5-table/src/tableutils.js | 49 +++++----- .../ckeditor5-table/tests/_utils/utils.js | 12 +-- .../tests/commands/insertcolumncommand.js | 12 +-- .../tests/commands/insertrowcommand.js | 12 +-- .../tests/commands/inserttablecommand.js | 6 +- .../tests/commands/splitcellcommand.js | 12 +-- .../converters/table-layout-post-fixer.js | 8 +- packages/ckeditor5-table/tests/tableutils.js | 90 +++++++++---------- 12 files changed, 104 insertions(+), 107 deletions(-) diff --git a/packages/ckeditor5-table/src/commands/insertcolumncommand.js b/packages/ckeditor5-table/src/commands/insertcolumncommand.js index bee55205834..1aa78ce0236 100644 --- a/packages/ckeditor5-table/src/commands/insertcolumncommand.js +++ b/packages/ckeditor5-table/src/commands/insertcolumncommand.js @@ -84,7 +84,7 @@ export default class InsertColumnCommand extends Command { }; if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { - insertColumnsOptions.defaultCellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); + insertColumnsOptions.cellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); } tableUtils.insertColumns( table, insertColumnsOptions ); diff --git a/packages/ckeditor5-table/src/commands/insertrowcommand.js b/packages/ckeditor5-table/src/commands/insertrowcommand.js index c1d67e732f9..8e3eb216936 100644 --- a/packages/ckeditor5-table/src/commands/insertrowcommand.js +++ b/packages/ckeditor5-table/src/commands/insertrowcommand.js @@ -83,7 +83,7 @@ export default class InsertRowCommand extends Command { }; if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { - insertRowsOptions.defaultCellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); + insertRowsOptions.cellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); } tableUtils.insertRows( table, insertRowsOptions ); diff --git a/packages/ckeditor5-table/src/commands/inserttablecommand.js b/packages/ckeditor5-table/src/commands/inserttablecommand.js index f6434be3924..b4b0dbf215f 100644 --- a/packages/ckeditor5-table/src/commands/inserttablecommand.js +++ b/packages/ckeditor5-table/src/commands/inserttablecommand.js @@ -55,11 +55,11 @@ export default class InsertTableCommand extends Command { const createTableOptions = Object.assign( {}, options ); if ( editor.plugins.has( 'TablePropertiesEditing' ) ) { - createTableOptions.defaultProperties = editor.config.get( 'table.tableProperties.defaultProperties' ); + createTableOptions.tableProperties = editor.config.get( 'table.tableProperties.defaultProperties' ); } if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { - createTableOptions.defaultCellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); + createTableOptions.cellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); } const insertPosition = findOptimalInsertionPosition( selection, model ); diff --git a/packages/ckeditor5-table/src/commands/splitcellcommand.js b/packages/ckeditor5-table/src/commands/splitcellcommand.js index a607ffc1f53..ae431904fd7 100644 --- a/packages/ckeditor5-table/src/commands/splitcellcommand.js +++ b/packages/ckeditor5-table/src/commands/splitcellcommand.js @@ -63,7 +63,7 @@ export default class SplitCellCommand extends Command { const splitOptions = {}; if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { - splitOptions.defaultCellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); + splitOptions.cellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); } if ( isHorizontal ) { diff --git a/packages/ckeditor5-table/src/tableutils.js b/packages/ckeditor5-table/src/tableutils.js index b6ded312c0d..e92b8ce272f 100644 --- a/packages/ckeditor5-table/src/tableutils.js +++ b/packages/ckeditor5-table/src/tableutils.js @@ -94,22 +94,20 @@ export default class TableUtils extends Plugin { * @param {Number} [options.columns=2] The number of columns to create. * @param {Number} [options.headingRows=0] The number of heading rows. * @param {Number} [options.headingColumns=0] The number of heading columns. - * @param {String} [options.defaultProperties={}] The default properties for the created table. - * @param {Object} [options.defaultCellProperties={}] The default cell properties in the created table. + * @param {String} [options.tableProperties={}] The default properties for the created table. + * @param {Object} [options.cellProperties={}] The default cell properties in the created table. * @returns {module:engine/model/element~Element} The created table element. */ createTable( writer, options ) { - const defaultProperties = options.defaultProperties || {}; - const defaultCellProperties = options.defaultCellProperties || {}; + const tableProperties = options.tableProperties || {}; + const cellProperties = options.cellProperties || {}; - const table = writer.createElement( 'table', defaultProperties ); + const table = writer.createElement( 'table', tableProperties ); const rows = parseInt( options.rows ) || 2; const columns = parseInt( options.columns ) || 2; - createEmptyRows( writer, table, 0, rows, columns, { - cellProperties: defaultCellProperties - } ); + createEmptyRows( writer, table, 0, rows, columns, cellProperties ); if ( options.headingRows ) { updateNumericAttribute( 'headingRows', options.headingRows, table, writer, 0 ); @@ -148,7 +146,7 @@ export default class TableUtils extends Plugin { * @param {Number} [options.rows=1] The number of rows to insert. * @param {Boolean|undefined} [options.copyStructureFromAbove] The flag for copying row structure. Note that * the row structure will not be copied if this option is not provided. - * @param {Object} [options.defaultCellProperties={}] The default cell properties in the created table. + * @param {Object} [options.cellProperties={}] Properties that will be applied to all created cells. */ insertRows( table, options = {} ) { const model = this.editor.model; @@ -157,7 +155,7 @@ export default class TableUtils extends Plugin { const rowsToInsert = options.rows || 1; const isCopyStructure = options.copyStructureFromAbove !== undefined; const copyStructureFrom = options.copyStructureFromAbove ? insertAt - 1 : insertAt; - const cellProperties = options.defaultCellProperties || {}; + const cellProperties = options.cellProperties || {}; const rows = this.getRows( table ); const columns = this.getColumns( table ); @@ -172,7 +170,7 @@ export default class TableUtils extends Plugin { // Inserting at the end or at the beginning of a table doesn't require to calculate anything special. if ( !isCopyStructure && ( insertAt === 0 || insertAt === rows ) ) { - createEmptyRows( writer, table, insertAt, rowsToInsert, columns, { cellProperties } ); + createEmptyRows( writer, table, insertAt, rowsToInsert, columns, cellProperties ); return; } @@ -254,14 +252,14 @@ export default class TableUtils extends Plugin { * @param {Object} options * @param {Number} [options.at=0] The column index at which the columns will be inserted. * @param {Number} [options.columns=1] The number of columns to insert. - * @param {Object} [options.defaultCellProperties={}] The default cell properties in the created table. + * @param {Object} [options.cellProperties={}] Properties that will be applied to all created cells. */ insertColumns( table, options = {} ) { const model = this.editor.model; const insertAt = options.at || 0; const columnsToInsert = options.columns || 1; - const cellProperties = options.defaultCellProperties || {}; + const cellProperties = options.cellProperties || {}; model.change( writer => { const headingColumns = table.getAttribute( 'headingColumns' ); @@ -488,7 +486,7 @@ export default class TableUtils extends Plugin { * @param {module:engine/model/element~Element} tableCell * @param {Number} numberOfCells * @param {Object} [options={}] options - * @param {Object} [options.defaultCellProperties={}] The default cell properties in the created table. + * @param {Object} [options.cellProperties={}] Properties that will be applied after splitting the cell. */ splitCellVertically( tableCell, numberOfCells = 2, options = {} ) { const model = this.editor.model; @@ -497,7 +495,7 @@ export default class TableUtils extends Plugin { const rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 ); const colspan = parseInt( tableCell.getAttribute( 'colspan' ) || 1 ); - const defaultCellProperties = options.defaultCellProperties || {}; + const cellProperties = options.cellProperties || {}; model.change( writer => { // First check - the cell spans over multiple rows so before doing anything else just split this cell. @@ -508,7 +506,7 @@ export default class TableUtils extends Plugin { updateNumericAttribute( 'colspan', updatedSpan, tableCell, writer ); // Each inserted cell will have the same properties. Copy the default ones to avoid modifying references. - const newCellProperties = Object.assign( {}, defaultCellProperties ); + const newCellProperties = Object.assign( {}, cellProperties ); // Do not store default value in the model. if ( newCellsSpan > 1 ) { @@ -550,7 +548,7 @@ export default class TableUtils extends Plugin { // Second step: create columns after split cell. // Each inserted cell will have the same properties. Copy the default ones to avoid modifying references. - const newCellProperties = Object.assign( {}, defaultCellProperties ); + const newCellProperties = Object.assign( {}, cellProperties ); // Do not store default value in the model. @@ -627,7 +625,7 @@ export default class TableUtils extends Plugin { * @param {module:engine/model/element~Element} tableCell * @param {Number} numberOfCells * @param {Object} [options={}] options - * @param {Object} [options.defaultCellProperties={}] The default cell properties in the created table. + * @param {Object} [options.cellProperties={}] Properties that will be applied after splitting the cell. */ splitCellHorizontally( tableCell, numberOfCells = 2, options = {} ) { const model = this.editor.model; @@ -638,7 +636,7 @@ export default class TableUtils extends Plugin { const rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 ); const colspan = parseInt( tableCell.getAttribute( 'colspan' ) || 1 ); - const defaultCellProperties = options.defaultCellProperties || {}; + const cellProperties = options.cellProperties || {}; model.change( writer => { // First check - the cell spans over multiple rows so before doing anything else just split this cell. @@ -658,7 +656,7 @@ export default class TableUtils extends Plugin { const { column: cellColumn } = tableMap.find( ( { cell } ) => cell === tableCell ); // Each inserted cell will have the same properties. Copy the default ones to avoid modifying references. - const newCellProperties = Object.assign( {}, defaultCellProperties ); + const newCellProperties = Object.assign( {}, cellProperties ); // Do not store default value in the model. if ( newCellsSpan > 1 ) { @@ -710,14 +708,14 @@ export default class TableUtils extends Plugin { } // Second step: create rows with single cell below split cell. Copy the default ones to avoid modifying references. - const newCellProperties = Object.assign( {}, defaultCellProperties ); + const newCellProperties = Object.assign( {}, cellProperties ); // Copy colspan of split cell. if ( colspan > 1 ) { newCellProperties.colspan = colspan; } - createEmptyRows( writer, table, splitCellRow + 1, cellsToInsert, 1, { cellProperties: newCellProperties } ); + createEmptyRows( writer, table, splitCellRow + 1, cellsToInsert, 1, newCellProperties ); // Update heading section if split cell is in heading section. const headingRows = table.getAttribute( 'headingRows' ) || 0; @@ -769,15 +767,14 @@ export default class TableUtils extends Plugin { // @param {Number} insertAt The row index of row insertion. // @param {Number} rows The number of rows to create. // @param {Number} tableCellToInsert The number of cells to insert in each row. -// @param {Object} options -// @param {Object} options.cellProperties The cell attributes. -function createEmptyRows( writer, table, insertAt, rows, tableCellToInsert, options ) { +// @param {Object} attributes The cell attributes. +function createEmptyRows( writer, table, insertAt, rows, tableCellToInsert, attributes ) { for ( let i = 0; i < rows; i++ ) { const tableRow = writer.createElement( 'tableRow' ); writer.insert( tableRow, table, insertAt ); - createCells( tableCellToInsert, writer, writer.createPositionAt( tableRow, 'end' ), options.cellProperties ); + createCells( tableCellToInsert, writer, writer.createPositionAt( tableRow, 'end' ), attributes ); } } diff --git a/packages/ckeditor5-table/tests/_utils/utils.js b/packages/ckeditor5-table/tests/_utils/utils.js index cca2b319967..b71b883c121 100644 --- a/packages/ckeditor5-table/tests/_utils/utils.js +++ b/packages/ckeditor5-table/tests/_utils/utils.js @@ -35,8 +35,8 @@ const WIDGET_TABLE_CELL_CLASS = 'ck-editor__editable ck-editor__nested-editable' * @param {Object} [attributes={}] Optional table attributes. * @param {Number} attributes.headingRows Number of heading rows. * @param {Number} attributes.headingColumns Number of heading columns. - * @param {Object} attributes.defaultProperties Default styles for the table. - * @param {Object} attributes.defaultCellProperties Default styles for all cells. + * @param {Object} attributes.tableProperties Default styles for the table. + * @param {Object} attributes.cellProperties Default styles for all cells. * * @returns {String} */ @@ -47,10 +47,10 @@ export function modelTable( tableData, attributes = {} ) { headingElement: 'tableCell', wrappingElement: 'paragraph', enforceWrapping: true, - defaultCellProperties: attributes.defaultCellProperties + cellProperties: attributes.cellProperties } ); - delete attributes.defaultCellProperties; + delete attributes.cellProperties; return `${ tableRows }`; } @@ -350,7 +350,7 @@ function formatAttributes( attributes ) { // Formats passed table data to a set of table rows. function makeRows( tableData, options ) { - const { cellElement, rowElement, headingElement, wrappingElement, enforceWrapping, asWidget, defaultCellProperties } = options; + const { cellElement, rowElement, headingElement, wrappingElement, enforceWrapping, asWidget, cellProperties } = options; return tableData .reduce( ( previousRowsString, tableRow ) => { @@ -375,7 +375,7 @@ function makeRows( tableData, options ) { } // Copy the default properties to avoid modifying references. - let attributes = Object.assign( {}, defaultCellProperties ); + let attributes = Object.assign( {}, cellProperties ); if ( asWidget ) { attributes.class = getClassToSet( attributes ); diff --git a/packages/ckeditor5-table/tests/commands/insertcolumncommand.js b/packages/ckeditor5-table/tests/commands/insertcolumncommand.js index bcdc8785204..bc204f3f8f1 100644 --- a/packages/ckeditor5-table/tests/commands/insertcolumncommand.js +++ b/packages/ckeditor5-table/tests/commands/insertcolumncommand.js @@ -252,7 +252,7 @@ describe( 'InsertColumnCommand', () => { expect( insertColumnsStub.firstCall.args[ 1 ] ).to.deep.equal( { columns: 1, at: 1, - defaultCellProperties: { + cellProperties: { horizontalAlignment: 'center', verticalAlignment: 'middle' } @@ -275,7 +275,7 @@ describe( 'InsertColumnCommand', () => { setData( model, modelTable( [ [ '11[]' ], [ '21' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); command.execute(); @@ -283,7 +283,7 @@ describe( 'InsertColumnCommand', () => { modelTable( [ [ '11[]', '' ], [ '21', '' ] - ], { defaultCellProperties: defaultProperties } ) + ], { cellProperties: defaultProperties } ) ); } ); } ); @@ -492,7 +492,7 @@ describe( 'InsertColumnCommand', () => { expect( insertColumnsStub.firstCall.args[ 1 ] ).to.deep.equal( { columns: 1, at: 0, - defaultCellProperties: { + cellProperties: { horizontalAlignment: 'center', verticalAlignment: 'middle' } @@ -515,7 +515,7 @@ describe( 'InsertColumnCommand', () => { setData( model, modelTable( [ [ '11[]' ], [ '21' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); command.execute(); @@ -523,7 +523,7 @@ describe( 'InsertColumnCommand', () => { modelTable( [ [ '', '11[]' ], [ '', '21' ] - ], { defaultCellProperties: defaultProperties } ) + ], { cellProperties: defaultProperties } ) ); } ); } ); diff --git a/packages/ckeditor5-table/tests/commands/insertrowcommand.js b/packages/ckeditor5-table/tests/commands/insertrowcommand.js index 9669b30cb69..7c9708d73a3 100644 --- a/packages/ckeditor5-table/tests/commands/insertrowcommand.js +++ b/packages/ckeditor5-table/tests/commands/insertrowcommand.js @@ -346,7 +346,7 @@ describe( 'InsertRowCommand', () => { expect( insertRowsStub.firstCall.args[ 1 ] ).to.deep.equal( { at: 1, copyStructureFromAbove: true, - defaultCellProperties: { + cellProperties: { horizontalAlignment: 'center', verticalAlignment: 'middle' } @@ -368,7 +368,7 @@ describe( 'InsertRowCommand', () => { // Apply default properties for the created table. setData( model, modelTable( [ [ '11[]', '12' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); command.execute(); @@ -376,7 +376,7 @@ describe( 'InsertRowCommand', () => { modelTable( [ [ '11[]', '12' ], [ '', '' ] - ], { defaultCellProperties: defaultProperties } ) + ], { cellProperties: defaultProperties } ) ); } ); } ); @@ -579,7 +579,7 @@ describe( 'InsertRowCommand', () => { expect( insertRowsStub.firstCall.args[ 1 ] ).to.deep.equal( { at: 0, copyStructureFromAbove: false, - defaultCellProperties: { + cellProperties: { horizontalAlignment: 'center', verticalAlignment: 'middle' } @@ -601,7 +601,7 @@ describe( 'InsertRowCommand', () => { // Apply default properties for the created table. setData( model, modelTable( [ [ '11[]', '12' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); command.execute(); @@ -609,7 +609,7 @@ describe( 'InsertRowCommand', () => { modelTable( [ [ '', '' ], [ '11[]', '12' ] - ], { defaultCellProperties: defaultProperties } ) + ], { cellProperties: defaultProperties } ) ); } ); } ); diff --git a/packages/ckeditor5-table/tests/commands/inserttablecommand.js b/packages/ckeditor5-table/tests/commands/inserttablecommand.js index 84fb3d16620..b128f4df81c 100644 --- a/packages/ckeditor5-table/tests/commands/inserttablecommand.js +++ b/packages/ckeditor5-table/tests/commands/inserttablecommand.js @@ -202,7 +202,7 @@ describe( 'InsertTableCommand', () => { expect( createTableStub.callCount ).to.equal( 1 ); expect( createTableStub.firstCall.args[ 1 ] ).to.deep.equal( { - defaultProperties: { alignment: 'center' } + tableProperties: { alignment: 'center' } } ); } ); @@ -259,7 +259,7 @@ describe( 'InsertTableCommand', () => { expect( createTableStub.callCount ).to.equal( 1 ); expect( createTableStub.firstCall.args[ 1 ] ).to.deep.equal( { - defaultCellProperties: { + cellProperties: { horizontalAlignment: 'center', verticalAlignment: 'middle' } @@ -284,7 +284,7 @@ describe( 'InsertTableCommand', () => { modelTable( [ [ '[]', '' ], [ '', '' ] - ], { defaultCellProperties: defaultProperties } ) + ], { cellProperties: defaultProperties } ) ); } ); } ); diff --git a/packages/ckeditor5-table/tests/commands/splitcellcommand.js b/packages/ckeditor5-table/tests/commands/splitcellcommand.js index 8569fdf84bc..fd3885f2bd0 100644 --- a/packages/ckeditor5-table/tests/commands/splitcellcommand.js +++ b/packages/ckeditor5-table/tests/commands/splitcellcommand.js @@ -201,7 +201,7 @@ describe( 'SplitCellCommand', () => { expect( splitCellVerticallyStub.callCount ).to.equal( 1 ); expect( splitCellVerticallyStub.firstCall.args[ 2 ] ).to.deep.equal( { - defaultCellProperties: { + cellProperties: { horizontalAlignment: 'center', verticalAlignment: 'middle' } @@ -223,14 +223,14 @@ describe( 'SplitCellCommand', () => { // Apply default properties for the created table. setData( model, modelTable( [ [ '11[]' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); command.execute(); assertEqualMarkup( getData( model ), modelTable( [ [ '11[]', '' ] - ], { defaultCellProperties: defaultProperties } ) + ], { cellProperties: defaultProperties } ) ); } ); } ); @@ -311,7 +311,7 @@ describe( 'SplitCellCommand', () => { expect( splitCellHorizontallyStub.callCount ).to.equal( 1 ); expect( splitCellHorizontallyStub.firstCall.args[ 2 ] ).to.deep.equal( { - defaultCellProperties: { + cellProperties: { horizontalAlignment: 'center', verticalAlignment: 'middle' } @@ -333,7 +333,7 @@ describe( 'SplitCellCommand', () => { // Apply default properties for the created table. setData( model, modelTable( [ [ '11[]' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); command.execute(); @@ -341,7 +341,7 @@ describe( 'SplitCellCommand', () => { modelTable( [ [ '11[]' ], [ '' ] - ], { defaultCellProperties: defaultProperties } ) + ], { cellProperties: defaultProperties } ) ); } ); } ); diff --git a/packages/ckeditor5-table/tests/converters/table-layout-post-fixer.js b/packages/ckeditor5-table/tests/converters/table-layout-post-fixer.js index 7eb0b8db762..4f19df7a8f9 100644 --- a/packages/ckeditor5-table/tests/converters/table-layout-post-fixer.js +++ b/packages/ckeditor5-table/tests/converters/table-layout-post-fixer.js @@ -237,7 +237,7 @@ describe( 'Table layout post-fixer', () => { [ '00' ], [ '10', '11', '12' ], [ '20', '21' ] - ], { defaultCellProperties: defaultProperties } ), model.schema ); + ], { cellProperties: defaultProperties } ), model.schema ); model.change( writer => { writer.remove( writer.createRangeIn( root ) ); @@ -248,7 +248,7 @@ describe( 'Table layout post-fixer', () => { [ '00', '', '' ], [ '10', '11', '12' ], [ '20', '21', '' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should add missing columns to tableRows that are shorter then the longest table row (complex 2)', () => { @@ -256,7 +256,7 @@ describe( 'Table layout post-fixer', () => { [ { colspan: 6, contents: '00' } ], [ { rowspan: 2, contents: '10' }, '11', { colspan: 3, contents: '12' } ], [ '21', '22' ] - ], { defaultCellProperties: defaultProperties } ), model.schema ); + ], { cellProperties: defaultProperties } ), model.schema ); model.change( writer => { writer.remove( writer.createRangeIn( root ) ); @@ -267,7 +267,7 @@ describe( 'Table layout post-fixer', () => { [ { colspan: 6, contents: '00' } ], [ { rowspan: 2, contents: '10' }, '11', { colspan: 3, contents: '12' }, '' ], [ '21', '22', '', '', '' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tableutils.js b/packages/ckeditor5-table/tests/tableutils.js index 8d4c165974b..35aa1b62320 100644 --- a/packages/ckeditor5-table/tests/tableutils.js +++ b/packages/ckeditor5-table/tests/tableutils.js @@ -389,7 +389,7 @@ describe( 'TableUtils', () => { [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], [ '10', { contents: '14', colspan: 2 } ], [ '20', '21', '22', '23', '24', '25' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); const root = model.document.getRoot( 'main' ); table = root.getNodeByPath( [ 0 ] ); @@ -403,7 +403,7 @@ describe( 'TableUtils', () => { it( 'should insert a new row and apply default cell properties to all created cells (insert below, single row)', () => { tableUtils.insertRows( table, { at: 3, - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+----+ @@ -420,14 +420,14 @@ describe( 'TableUtils', () => { [ '10', { contents: '14', colspan: 2 } ], [ '20', '21', '22', '23', '24', '25' ], [ '', '', '', '', '', '' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should insert a new row and apply default cell properties to all created cells (insert below, double row)', () => { tableUtils.insertRows( table, { at: 3, rows: 2, - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+----+ @@ -447,13 +447,13 @@ describe( 'TableUtils', () => { [ '20', '21', '22', '23', '24', '25' ], [ '', '', '', '', '', '' ], [ '', '', '', '', '', '' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should insert a new row and apply default cell properties to all created cells (insert above, single row)', () => { tableUtils.insertRows( table, { at: 0, - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+----+ @@ -470,14 +470,14 @@ describe( 'TableUtils', () => { [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], [ '10', { contents: '14', colspan: 2 } ], [ '20', '21', '22', '23', '24', '25' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should insert a new row and apply default cell properties to all created cells (insert above, double row)', () => { tableUtils.insertRows( table, { at: 0, rows: 2, - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+----+ @@ -497,13 +497,13 @@ describe( 'TableUtils', () => { [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], [ '10', { contents: '14', colspan: 2 } ], [ '20', '21', '22', '23', '24', '25' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should insert a new row and apply default cell properties to all created cells (insert in the middle, single row)', () => { tableUtils.insertRows( table, { at: 1, - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+----+ @@ -520,7 +520,7 @@ describe( 'TableUtils', () => { [ '', '', '' ], [ '10', { contents: '14', colspan: 2 } ], [ '20', '21', '22', '23', '24', '25' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); } ); } ); @@ -792,7 +792,7 @@ describe( 'TableUtils', () => { setData( model, modelTable( [ [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], [ '10', '14' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); const root = model.document.getRoot( 'main' ); table = root.getNodeByPath( [ 0 ] ); @@ -806,7 +806,7 @@ describe( 'TableUtils', () => { it( 'should insert a new column and apply default cell properties to all created cells (insert right, single column)', () => { tableUtils.insertColumns( table, { at: 5, - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+----+ @@ -817,14 +817,14 @@ describe( 'TableUtils', () => { assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '' ], [ '10', '14', '' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should insert a new column and apply default cell properties to all created cells (insert right, double column)', () => { tableUtils.insertColumns( table, { at: 5, columns: 2, - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+----+----+ @@ -835,13 +835,13 @@ describe( 'TableUtils', () => { assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '', '' ], [ '10', '14', '', '' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should insert a new column and apply default cell properties to all created cells (insert left, single column)', () => { tableUtils.insertColumns( table, { at: 0, - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+----+ @@ -852,14 +852,14 @@ describe( 'TableUtils', () => { assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ [ '', '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], [ '', '10', '14' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should insert a new column and apply default cell properties to all created cells (insert left, double column)', () => { tableUtils.insertColumns( table, { at: 0, columns: 2, - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+----+----+ @@ -870,13 +870,13 @@ describe( 'TableUtils', () => { assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ [ '', '', '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], [ '', '', '10', '14' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should insert a new row and apply default cell properties to all created cells (insert in the middle, single row)', () => { tableUtils.insertColumns( table, { at: 3, - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+----+ @@ -887,7 +887,7 @@ describe( 'TableUtils', () => { assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ [ '00', { contents: '01', colspan: 2, rowspan: 2 }, '', { contents: '03', rowspan: 2 }, '04' ], [ '10', '', '14' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); } ); } ); @@ -1077,12 +1077,12 @@ describe( 'TableUtils', () => { // +----+----+----+----+ setData( model, modelTable( [ [ '00', { contents: '[]01', colspan: 2 }, '03' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); const tableCell = root.getNodeByPath( [ 0, 0, 1 ] ); tableUtils.splitCellVertically( tableCell, 2, { - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+ @@ -1090,7 +1090,7 @@ describe( 'TableUtils', () => { // +----+----+----+----+ assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ [ '00', '01', '', '03' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should properly split the column and apply default cell properties (colspan=4, cells=2)', () => { @@ -1099,12 +1099,12 @@ describe( 'TableUtils', () => { // +----+----+----+----+----+----+ setData( model, modelTable( [ [ '00', { contents: '[]01', colspan: 4 }, '05' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); const tableCell = root.getNodeByPath( [ 0, 0, 1 ] ); tableUtils.splitCellVertically( tableCell, 2, { - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+----+ @@ -1112,7 +1112,7 @@ describe( 'TableUtils', () => { // +----+----+----+----+----+----+ assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ [ '00', { contents: '01', colspan: 2 }, { contents: '', colspan: 2 }, '05' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should properly split the column and apply default cell properties (colspan=2, rowspan=2, cells=3)', () => { @@ -1124,12 +1124,12 @@ describe( 'TableUtils', () => { setData( model, modelTable( [ [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], [ '10', '14' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); const tableCell = root.getNodeByPath( [ 0, 0, 1 ] ); tableUtils.splitCellVertically( tableCell, 3, { - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+----+ @@ -1147,7 +1147,7 @@ describe( 'TableUtils', () => { '04' ], [ '10', '14' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); } ); } ); @@ -1377,12 +1377,12 @@ describe( 'TableUtils', () => { [ { contents: '[]01', rowspan: 2 } ], [], [ '03' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); const tableCell = root.getNodeByPath( [ 0, 1, 0 ] ); tableUtils.splitCellHorizontally( tableCell, 2, { - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+ @@ -1399,7 +1399,7 @@ describe( 'TableUtils', () => { [ '01' ], [ '' ], [ '03' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should properly split the column and apply default cell properties (rowspan=4, cells=2)', () => { @@ -1423,12 +1423,12 @@ describe( 'TableUtils', () => { [], [], [ '05' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); const tableCell = root.getNodeByPath( [ 0, 1, 0 ] ); tableUtils.splitCellHorizontally( tableCell, 2, { - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+ @@ -1451,7 +1451,7 @@ describe( 'TableUtils', () => { [ { contents: '', rowspan: 2 } ], [], [ '05' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); it( 'should properly split the column and apply default cell properties (colspan=2, rowspan=2, cells=3)', () => { @@ -1463,12 +1463,12 @@ describe( 'TableUtils', () => { setData( model, modelTable( [ [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], [ '10', '14' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); const tableCell = root.getNodeByPath( [ 0, 0, 1 ] ); tableUtils.splitCellHorizontally( tableCell, 3, { - defaultCellProperties: defaultProperties + cellProperties: defaultProperties } ); // +----+----+----+----+----+ @@ -1489,7 +1489,7 @@ describe( 'TableUtils', () => { { contents: '', colspan: 2 } ], [ '10', { contents: '', colspan: 2 }, '14' ] - ], { defaultCellProperties: defaultProperties } ) ); + ], { cellProperties: defaultProperties } ) ); } ); } ); } ); @@ -2242,7 +2242,7 @@ describe( 'TableUtils', () => { }; model.change( writer => { - const table = tableUtils.createTable( writer, { defaultProperties } ); + const table = tableUtils.createTable( writer, { tableProperties: defaultProperties } ); model.insertContent( table, model.document.selection.focus ); } ); @@ -2257,7 +2257,7 @@ describe( 'TableUtils', () => { it( 'should create table and apply specified styles for all cells', () => { setData( model, '[]' ); - const defaultCellProperties = { + const cellProperties = { width: '30px', height: '30px', verticalAlignment: 'bottom', @@ -2265,16 +2265,16 @@ describe( 'TableUtils', () => { }; model.change( writer => { - const table = tableUtils.createTable( writer, { defaultCellProperties } ); + const table = tableUtils.createTable( writer, { cellProperties } ); model.insertContent( table, model.document.selection.focus ); } ); - // Styles for cells are specified as `attributes.defaultCellProperties` object. + // Styles for cells are specified as `attributes.cellProperties` object. assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ [ '', '' ], [ '', '' ] - ], { defaultCellProperties } ) ); + ], { cellProperties } ) ); } ); } ); } ); From 88046d8cf94998dd3bc40c7ffc6317c2676fc369 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Thu, 8 Apr 2021 11:07:17 +0200 Subject: [PATCH 17/24] Extended available options/attributes for the modelTable() util. --- packages/ckeditor5-table/tests/_utils/utils.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/ckeditor5-table/tests/_utils/utils.js b/packages/ckeditor5-table/tests/_utils/utils.js index b71b883c121..500935825c1 100644 --- a/packages/ckeditor5-table/tests/_utils/utils.js +++ b/packages/ckeditor5-table/tests/_utils/utils.js @@ -32,27 +32,26 @@ const WIDGET_TABLE_CELL_CLASS = 'ck-editor__editable ck-editor__nested-editable' * }; * * @param {Array.|Object>} tableData - * @param {Object} [attributes={}] Optional table attributes. - * @param {Number} attributes.headingRows Number of heading rows. - * @param {Number} attributes.headingColumns Number of heading columns. - * @param {Object} attributes.tableProperties Default styles for the table. - * @param {Object} attributes.cellProperties Default styles for all cells. + * @param {Object} [options={}] Optional table attributes. Supports {@link module:table/table~TableConfig#tableProperties}. + * @param {Number} options.headingRows Number of heading rows. + * @param {Number} options.headingColumns Number of heading columns. + * @param {module:table/table~TableConfig#tableCellProperties} options.cellProperties Properties for all created cells. * * @returns {String} */ -export function modelTable( tableData, attributes = {} ) { +export function modelTable( tableData, options = {} ) { const tableRows = makeRows( tableData, { cellElement: 'tableCell', rowElement: 'tableRow', headingElement: 'tableCell', wrappingElement: 'paragraph', enforceWrapping: true, - cellProperties: attributes.cellProperties + cellProperties: options.cellProperties } ); - delete attributes.cellProperties; + delete options.cellProperties; - return `${ tableRows }`; + return `${ tableRows }`; } /** From bab6ca241701b4a9c9ca0837ce66a66cac1ea71e Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Fri, 9 Apr 2021 14:02:57 +0200 Subject: [PATCH 18/24] Table and cells default properties decorate proper commands now instead of passing the attributes to TableUtils. --- .../src/commands/insertcolumncommand.js | 15 +- .../src/commands/insertrowcommand.js | 15 +- .../src/commands/inserttablecommand.js | 9 - .../src/commands/splitcellcommand.js | 4 - .../tablecellpropertiesediting.js | 49 +- .../tableproperties/tablepropertiesediting.js | 23 +- packages/ckeditor5-table/src/tableutils.js | 115 +-- .../tests/commands/insertcolumncommand.js | 177 +---- .../tests/commands/insertrowcommand.js | 168 +--- .../tests/commands/inserttablecommand.js | 120 --- .../tests/commands/splitcellcommand.js | 140 ---- .../tablecellpropertiesediting.js | 104 ++- .../tableproperties/tablepropertiesediting.js | 53 +- packages/ckeditor5-table/tests/tableutils.js | 725 +++--------------- 14 files changed, 451 insertions(+), 1266 deletions(-) diff --git a/packages/ckeditor5-table/src/commands/insertcolumncommand.js b/packages/ckeditor5-table/src/commands/insertcolumncommand.js index 1aa78ce0236..05c06a12be0 100644 --- a/packages/ckeditor5-table/src/commands/insertcolumncommand.js +++ b/packages/ckeditor5-table/src/commands/insertcolumncommand.js @@ -78,15 +78,10 @@ export default class InsertColumnCommand extends Command { const column = insertBefore ? columnIndexes.first : columnIndexes.last; const table = affectedTableCells[ 0 ].findAncestor( 'table' ); - const insertColumnsOptions = { - columns: 1, - at: insertBefore ? column : column + 1 - }; - - if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { - insertColumnsOptions.cellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); - } - - tableUtils.insertColumns( table, insertColumnsOptions ); + // The `TableUtils` plugin fires the `#insertColumns` event. In order to having a single undo step, + // we need to wrap the code in the `editor.model.change()` block. + editor.model.change( () => { + tableUtils.insertColumns( table, { columns: 1, at: insertBefore ? column : column + 1 } ); + } ); } } diff --git a/packages/ckeditor5-table/src/commands/insertrowcommand.js b/packages/ckeditor5-table/src/commands/insertrowcommand.js index 8e3eb216936..4c5be76e54d 100644 --- a/packages/ckeditor5-table/src/commands/insertrowcommand.js +++ b/packages/ckeditor5-table/src/commands/insertrowcommand.js @@ -77,15 +77,10 @@ export default class InsertRowCommand extends Command { const row = insertAbove ? rowIndexes.first : rowIndexes.last; const table = affectedTableCells[ 0 ].findAncestor( 'table' ); - const insertRowsOptions = { - at: insertAbove ? row : row + 1, - copyStructureFromAbove: !insertAbove - }; - - if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { - insertRowsOptions.cellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); - } - - tableUtils.insertRows( table, insertRowsOptions ); + // The `TableUtils` plugin fires the `#insertRows` event. In order to having a single undo step, + // we need to wrap the code in the `editor.model.change()` block. + editor.model.change( () => { + tableUtils.insertRows( table, { at: insertAbove ? row : row + 1, copyStructureFromAbove: !insertAbove } ); + } ); } } diff --git a/packages/ckeditor5-table/src/commands/inserttablecommand.js b/packages/ckeditor5-table/src/commands/inserttablecommand.js index b4b0dbf215f..33a966105c7 100644 --- a/packages/ckeditor5-table/src/commands/inserttablecommand.js +++ b/packages/ckeditor5-table/src/commands/inserttablecommand.js @@ -54,21 +54,12 @@ export default class InsertTableCommand extends Command { const createTableOptions = Object.assign( {}, options ); - if ( editor.plugins.has( 'TablePropertiesEditing' ) ) { - createTableOptions.tableProperties = editor.config.get( 'table.tableProperties.defaultProperties' ); - } - - if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { - createTableOptions.cellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); - } - const insertPosition = findOptimalInsertionPosition( selection, model ); model.change( writer => { const table = tableUtils.createTable( writer, createTableOptions ); model.insertContent( table, insertPosition ); - writer.setSelection( writer.createPositionAt( table.getNodeByPath( [ 0, 0, 0 ] ), 0 ) ); } ); } diff --git a/packages/ckeditor5-table/src/commands/splitcellcommand.js b/packages/ckeditor5-table/src/commands/splitcellcommand.js index ae431904fd7..29d51b6777e 100644 --- a/packages/ckeditor5-table/src/commands/splitcellcommand.js +++ b/packages/ckeditor5-table/src/commands/splitcellcommand.js @@ -62,10 +62,6 @@ export default class SplitCellCommand extends Command { const splitOptions = {}; - if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { - splitOptions.cellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); - } - if ( isHorizontal ) { tableUtils.splitCellHorizontally( tableCell, 2, splitOptions ); } else { diff --git a/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js b/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js index 388167ebdf4..bb140c2f3b4 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js +++ b/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js @@ -21,6 +21,8 @@ import TableCellHorizontalAlignmentCommand from './commands/tablecellhorizontala import TableCellBorderStyleCommand from './commands/tablecellborderstylecommand'; import TableCellBorderColorCommand from './commands/tablecellbordercolorcommand'; import TableCellBorderWidthCommand from './commands/tablecellborderwidthcommand'; +import TableWalker from '../tablewalker'; +import TableUtils from '../tableutils'; const VALIGN_VALUES_REG_EXP = /^(top|bottom)$/; @@ -57,7 +59,7 @@ export default class TableCellPropertiesEditing extends Plugin { * @inheritDoc */ static get requires() { - return [ TableEditing ]; + return [ TableEditing, TableUtils ]; } /** @@ -99,6 +101,34 @@ export default class TableCellPropertiesEditing extends Plugin { enableVerticalAlignmentProperty( schema, conversion ); editor.commands.add( 'tableCellVerticalAlignment', new TableCellVerticalAlignmentCommand( editor ) ); + + this._enableDefaultCellProperties(); + } + + /** + * Enables applying the default cell properties. + * + * @private + */ + _enableDefaultCellProperties() { + const editor = this.editor; + const tableCellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); + const tableUtils = editor.plugins.get( TableUtils ); + + // Apply default cell properties while creating a new table. + this.listenTo( tableUtils, 'createTable', ( evt, [ writer ] ) => { + const tableElement = evt.return; + + for ( const item of new TableWalker( tableElement ) ) { + writer.setAttributes( tableCellProperties, item.cell ); + } + }, { priority: 'low' } ); + + // Apply default cell properties while inserting new rows into the table. + this.listenTo( tableUtils, 'insertRows', applyDefaultCellProperties( editor, tableCellProperties ), { priority: 'low' } ); + + // Apply default cell properties while inserting new rows into the table. + this.listenTo( tableUtils, 'insertColumns', applyDefaultCellProperties( editor, tableCellProperties ), { priority: 'low' } ); } } @@ -207,3 +237,20 @@ function enableProperty( schema, conversion, modelAttribute, styleName ) { upcastStyleToAttribute( conversion, 'tableCell', modelAttribute, styleName ); downcastAttributeToStyle( conversion, 'tableCell', modelAttribute, styleName ); } + +// A factory function that returns a handler which applies default cell properties for created cells. +// +// @param {module:core/editor/editor~Editor} editor +// @param {module:table/table~TableConfig#tableCellProperties} tableCellProperties +// @return {Function} +function applyDefaultCellProperties( editor, tableCellProperties ) { + return evt => { + const createdCells = evt.return; + + editor.model.change( writer => { + for ( const tableCell of createdCells ) { + writer.setAttributes( tableCellProperties, tableCell ); + } + } ); + }; +} diff --git a/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js b/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js index fe5aa14d7bc..27dd224057c 100644 --- a/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js +++ b/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js @@ -24,6 +24,7 @@ import TableBorderWidthCommand from './commands/tableborderwidthcommand'; import TableWidthCommand from './commands/tablewidthcommand'; import TableHeightCommand from './commands/tableheightcommand'; import TableAlignmentCommand from './commands/tablealignmentcommand'; +import TableUtils from '../tableutils'; const ALIGN_VALUES_REG_EXP = /^(left|right)$/; @@ -58,7 +59,7 @@ export default class TablePropertiesEditing extends Plugin { * @inheritDoc */ static get requires() { - return [ TableEditing ]; + return [ TableEditing, TableUtils ]; } /** @@ -91,6 +92,26 @@ export default class TablePropertiesEditing extends Plugin { editor.data.addStyleProcessorRules( addBackgroundRules ); enableProperty( schema, conversion, 'backgroundColor', 'background-color' ); editor.commands.add( 'tableBackgroundColor', new TableBackgroundColorCommand( editor ) ); + + this._enableDefaultTableProperties(); + } + + /** + * Enables applying the default table properties. + * + * @private + */ + _enableDefaultTableProperties() { + const editor = this.editor; + const tableProperties = editor.config.get( 'table.tableProperties.defaultProperties' ); + const tableUtils = editor.plugins.get( TableUtils ); + + // Apply default table properties while creating a new table. + this.listenTo( tableUtils, 'createTable', ( evt, [ writer ] ) => { + const tableElement = evt.return; + + writer.setAttributes( tableProperties, tableElement ); + }, { priority: 'low' } ); } } diff --git a/packages/ckeditor5-table/src/tableutils.js b/packages/ckeditor5-table/src/tableutils.js index e92b8ce272f..c6fcd60b8b0 100644 --- a/packages/ckeditor5-table/src/tableutils.js +++ b/packages/ckeditor5-table/src/tableutils.js @@ -32,6 +32,7 @@ export default class TableUtils extends Plugin { init() { this.decorate( 'insertColumns' ); this.decorate( 'insertRows' ); + this.decorate( 'createTable' ); } /** @@ -94,20 +95,15 @@ export default class TableUtils extends Plugin { * @param {Number} [options.columns=2] The number of columns to create. * @param {Number} [options.headingRows=0] The number of heading rows. * @param {Number} [options.headingColumns=0] The number of heading columns. - * @param {String} [options.tableProperties={}] The default properties for the created table. - * @param {Object} [options.cellProperties={}] The default cell properties in the created table. * @returns {module:engine/model/element~Element} The created table element. */ createTable( writer, options ) { - const tableProperties = options.tableProperties || {}; - const cellProperties = options.cellProperties || {}; - - const table = writer.createElement( 'table', tableProperties ); + const table = writer.createElement( 'table' ); const rows = parseInt( options.rows ) || 2; const columns = parseInt( options.columns ) || 2; - createEmptyRows( writer, table, 0, rows, columns, cellProperties ); + createEmptyRows( writer, table, 0, rows, columns ); if ( options.headingRows ) { updateNumericAttribute( 'headingRows', options.headingRows, table, writer, 0 ); @@ -146,7 +142,7 @@ export default class TableUtils extends Plugin { * @param {Number} [options.rows=1] The number of rows to insert. * @param {Boolean|undefined} [options.copyStructureFromAbove] The flag for copying row structure. Note that * the row structure will not be copied if this option is not provided. - * @param {Object} [options.cellProperties={}] Properties that will be applied to all created cells. + * @returns {Array.} Created table cells. */ insertRows( table, options = {} ) { const model = this.editor.model; @@ -155,12 +151,11 @@ export default class TableUtils extends Plugin { const rowsToInsert = options.rows || 1; const isCopyStructure = options.copyStructureFromAbove !== undefined; const copyStructureFrom = options.copyStructureFromAbove ? insertAt - 1 : insertAt; - const cellProperties = options.cellProperties || {}; const rows = this.getRows( table ); const columns = this.getColumns( table ); - model.change( writer => { + return model.change( writer => { const headingRows = table.getAttribute( 'headingRows' ) || 0; // Inserting rows inside heading section requires to update `headingRows` attribute as the heading section will grow. @@ -170,9 +165,7 @@ export default class TableUtils extends Plugin { // Inserting at the end or at the beginning of a table doesn't require to calculate anything special. if ( !isCopyStructure && ( insertAt === 0 || insertAt === rows ) ) { - createEmptyRows( writer, table, insertAt, rowsToInsert, columns, cellProperties ); - - return; + return createEmptyRows( writer, table, insertAt, rowsToInsert, columns ); } // Iterate over all the rows above the inserted rows in order to check for the row-spanned cells. @@ -202,6 +195,8 @@ export default class TableUtils extends Plugin { } } + const createdCells = []; + for ( let rowIndex = 0; rowIndex < rowsToInsert; rowIndex++ ) { const tableRow = writer.createElement( 'tableRow' ); @@ -213,17 +208,17 @@ export default class TableUtils extends Plugin { // Insert the empty cell only if this slot is not row-spanned from any other cell. if ( colspan > 0 ) { - const newCellProperties = Object.assign( {}, cellProperties, { - colspan: colspan > 1 ? colspan : null - } ); + const tableCell = createEmptyTableCell( writer, insertPosition, colspan > 1 ? { colspan } : null ); - createEmptyTableCell( writer, insertPosition, newCellProperties ); + createdCells.push( tableCell ); } // Skip the col-spanned slots, there won't be any cells. cellIndex += Math.abs( colspan ) - 1; } } + + return createdCells; } ); } @@ -252,17 +247,17 @@ export default class TableUtils extends Plugin { * @param {Object} options * @param {Number} [options.at=0] The column index at which the columns will be inserted. * @param {Number} [options.columns=1] The number of columns to insert. - * @param {Object} [options.cellProperties={}] Properties that will be applied to all created cells. + * @returns {Array.} Created table cells. */ insertColumns( table, options = {} ) { const model = this.editor.model; const insertAt = options.at || 0; const columnsToInsert = options.columns || 1; - const cellProperties = options.cellProperties || {}; - model.change( writer => { + return model.change( writer => { const headingColumns = table.getAttribute( 'headingColumns' ); + const createdCells = []; // Inserting columns inside heading section requires to update `headingColumns` attribute as the heading section will grow. if ( insertAt < headingColumns ) { @@ -274,10 +269,12 @@ export default class TableUtils extends Plugin { // Inserting at the end and at the beginning of a table doesn't require to calculate anything special. if ( insertAt === 0 || tableColumns === insertAt ) { for ( const tableRow of table.getChildren() ) { - createCells( columnsToInsert, writer, writer.createPositionAt( tableRow, insertAt ? 'end' : 0 ), cellProperties ); + createdCells.push( + ...createCells( columnsToInsert, writer, writer.createPositionAt( tableRow, insertAt ? 'end' : 0 ) ) + ); } - return; + return createdCells; } const tableWalker = new TableWalker( table, { column: insertAt, includeAllSlots: true } ); @@ -304,9 +301,13 @@ export default class TableUtils extends Plugin { } else { // It's either cell at this column index or spanned cell by a row-spanned cell from row above. // In table above it's cell "e" and a spanned position from row below (empty cell between cells "g" and "h") - createCells( columnsToInsert, writer, tableSlot.getPositionBefore(), cellProperties ); + createdCells.push( + ...createCells( columnsToInsert, writer, tableSlot.getPositionBefore() ) + ); } } + + return createdCells; } ); } @@ -485,17 +486,14 @@ export default class TableUtils extends Plugin { * * @param {module:engine/model/element~Element} tableCell * @param {Number} numberOfCells - * @param {Object} [options={}] options - * @param {Object} [options.cellProperties={}] Properties that will be applied after splitting the cell. */ - splitCellVertically( tableCell, numberOfCells = 2, options = {} ) { + splitCellVertically( tableCell, numberOfCells = 2 ) { const model = this.editor.model; const tableRow = tableCell.parent; const table = tableRow.parent; const rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 ); const colspan = parseInt( tableCell.getAttribute( 'colspan' ) || 1 ); - const cellProperties = options.cellProperties || {}; model.change( writer => { // First check - the cell spans over multiple rows so before doing anything else just split this cell. @@ -505,21 +503,21 @@ export default class TableUtils extends Plugin { updateNumericAttribute( 'colspan', updatedSpan, tableCell, writer ); - // Each inserted cell will have the same properties. Copy the default ones to avoid modifying references. - const newCellProperties = Object.assign( {}, cellProperties ); + // Each inserted cell will have the same attributes: + const newCellsAttributes = {}; // Do not store default value in the model. if ( newCellsSpan > 1 ) { - newCellProperties.colspan = newCellsSpan; + newCellsAttributes.colspan = newCellsSpan; } // Copy rowspan of split cell. if ( rowspan > 1 ) { - newCellProperties.rowspan = rowspan; + newCellsAttributes.rowspan = rowspan; } const cellsToInsert = colspan > numberOfCells ? numberOfCells - 1 : colspan - 1; - createCells( cellsToInsert, writer, writer.createPositionAfter( tableCell ), newCellProperties ); + createCells( cellsToInsert, writer, writer.createPositionAfter( tableCell ), newCellsAttributes ); } // Second check - the cell has colspan of 1 or we need to create more cells then the currently one spans over. @@ -547,17 +545,17 @@ export default class TableUtils extends Plugin { // Second step: create columns after split cell. - // Each inserted cell will have the same properties. Copy the default ones to avoid modifying references. - const newCellProperties = Object.assign( {}, cellProperties ); + // Each inserted cell will have the same attributes: + const newCellsAttributes = {}; // Do not store default value in the model. // Copy rowspan of split cell. if ( rowspan > 1 ) { - newCellProperties.rowspan = rowspan; + newCellsAttributes.rowspan = rowspan; } - createCells( cellsToInsert, writer, writer.createPositionAfter( tableCell ), newCellProperties ); + createCells( cellsToInsert, writer, writer.createPositionAfter( tableCell ), newCellsAttributes ); const headingColumns = table.getAttribute( 'headingColumns' ) || 0; @@ -624,10 +622,8 @@ export default class TableUtils extends Plugin { * * @param {module:engine/model/element~Element} tableCell * @param {Number} numberOfCells - * @param {Object} [options={}] options - * @param {Object} [options.cellProperties={}] Properties that will be applied after splitting the cell. */ - splitCellHorizontally( tableCell, numberOfCells = 2, options = {} ) { + splitCellHorizontally( tableCell, numberOfCells = 2 ) { const model = this.editor.model; const tableRow = tableCell.parent; @@ -636,7 +632,6 @@ export default class TableUtils extends Plugin { const rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 ); const colspan = parseInt( tableCell.getAttribute( 'colspan' ) || 1 ); - const cellProperties = options.cellProperties || {}; model.change( writer => { // First check - the cell spans over multiple rows so before doing anything else just split this cell. @@ -655,17 +650,17 @@ export default class TableUtils extends Plugin { const { column: cellColumn } = tableMap.find( ( { cell } ) => cell === tableCell ); - // Each inserted cell will have the same properties. Copy the default ones to avoid modifying references. - const newCellProperties = Object.assign( {}, cellProperties ); + // Each inserted cell will have the same attributes: + const newCellsAttributes = {}; // Do not store default value in the model. if ( newCellsSpan > 1 ) { - newCellProperties.rowspan = newCellsSpan; + newCellsAttributes.rowspan = newCellsSpan; } // Copy colspan of split cell. if ( colspan > 1 ) { - newCellProperties.colspan = colspan; + newCellsAttributes.colspan = colspan; } for ( const tableSlot of tableMap ) { @@ -682,7 +677,7 @@ export default class TableUtils extends Plugin { const isInEvenlySplitRow = ( row + splitCellRow + updatedSpan ) % newCellsSpan === 0; if ( isAfterSplitCell && isOnSameColumn && isInEvenlySplitRow ) { - createCells( 1, writer, tableSlot.getPositionBefore(), newCellProperties ); + createCells( 1, writer, tableSlot.getPositionBefore(), newCellsAttributes ); } } } @@ -707,15 +702,15 @@ export default class TableUtils extends Plugin { } } - // Second step: create rows with single cell below split cell. Copy the default ones to avoid modifying references. - const newCellProperties = Object.assign( {}, cellProperties ); + // Second step: create rows with single cell below split cell. + const newCellsAttributes = {}; // Copy colspan of split cell. if ( colspan > 1 ) { - newCellProperties.colspan = colspan; + newCellsAttributes.colspan = colspan; } - createEmptyRows( writer, table, splitCellRow + 1, cellsToInsert, 1, newCellProperties ); + createEmptyRows( writer, table, splitCellRow + 1, cellsToInsert, 1, newCellsAttributes ); // Update heading section if split cell is in heading section. const headingRows = table.getAttribute( 'headingRows' ) || 0; @@ -767,15 +762,21 @@ export default class TableUtils extends Plugin { // @param {Number} insertAt The row index of row insertion. // @param {Number} rows The number of rows to create. // @param {Number} tableCellToInsert The number of cells to insert in each row. -// @param {Object} attributes The cell attributes. -function createEmptyRows( writer, table, insertAt, rows, tableCellToInsert, attributes ) { +// @returns {Array.} Created table cells. +function createEmptyRows( writer, table, insertAt, rows, tableCellToInsert, attributes = {} ) { + const createdCells = []; + for ( let i = 0; i < rows; i++ ) { const tableRow = writer.createElement( 'tableRow' ); writer.insert( tableRow, table, insertAt ); - createCells( tableCellToInsert, writer, writer.createPositionAt( tableRow, 'end' ), attributes ); + createdCells.push( + ...createCells( tableCellToInsert, writer, writer.createPositionAt( tableRow, 'end' ), attributes ) + ); } + + return createdCells; } // Creates cells at a given position. @@ -783,11 +784,15 @@ function createEmptyRows( writer, table, insertAt, rows, tableCellToInsert, attr // @param {Number} columns The number of columns to create // @param {module:engine/model/writer~Writer} writer // @param {module:engine/model/position~Position} insertPosition -// @param {Object} attributes The cell attributes. -function createCells( cells, writer, insertPosition, attributes ) { +// @returns {Array.} Created table cells. +function createCells( cells, writer, insertPosition, attributes = {} ) { + const createdCells = []; + for ( let i = 0; i < cells; i++ ) { - createEmptyTableCell( writer, insertPosition, attributes ); + createdCells.push( createEmptyTableCell( writer, insertPosition, attributes ) ); } + + return createdCells; } // Evenly distributes the span of a cell to a number of provided cells. diff --git a/packages/ckeditor5-table/tests/commands/insertcolumncommand.js b/packages/ckeditor5-table/tests/commands/insertcolumncommand.js index bc204f3f8f1..a043dcc6662 100644 --- a/packages/ckeditor5-table/tests/commands/insertcolumncommand.js +++ b/packages/ckeditor5-table/tests/commands/insertcolumncommand.js @@ -14,7 +14,7 @@ import TableEditing from '../../src/tableediting'; import { assertSelectedCells, modelTable } from '../_utils/utils'; import InsertColumnCommand from '../../src/commands/insertcolumncommand'; -import TableCellPropertiesEditing from '../../src/tablecellproperties/tablecellpropertiesediting'; +import { UndoEditing } from '@ckeditor/ckeditor5-undo'; describe( 'InsertColumnCommand', () => { let editor, model, command; @@ -22,7 +22,7 @@ describe( 'InsertColumnCommand', () => { beforeEach( () => { return ModelTestEditor .create( { - plugins: [ Paragraph, TableEditing, TableSelection, HorizontalLineEditing ] + plugins: [ Paragraph, TableEditing, TableSelection, HorizontalLineEditing, UndoEditing ] } ) .then( newEditor => { editor = newEditor; @@ -215,77 +215,41 @@ describe( 'InsertColumnCommand', () => { ] ) ); } ); - describe( 'integration with TableCellPropertiesEditing', () => { - let editor, model, tableUtils, command; - - beforeEach( () => { - return ModelTestEditor - .create( { - plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] - } ) - .then( newEditor => { - editor = newEditor; - model = editor.model; - - command = editor.commands.get( 'insertTableColumnRight' ); - tableUtils = editor.plugins.get( 'TableUtils' ); - } ); - } ); - - afterEach( () => { - return editor.destroy(); - } ); - - it( - 'should pass the default cell styles to "TableUtils.insertColumns()" function if TableCellPropertiesEditing is enabled', - () => { - const insertColumnsStub = sinon.stub( tableUtils, 'insertColumns' ).callThrough(); - - setData( model, modelTable( [ - [ '11[]' ], - [ '21' ] + it( 'should create a single undo step when inserting a column', () => { + setData( model, modelTable( [ + [ '11[]', '12' ], + [ '21', '22' ] + ] ) ); + + const tableUtils = editor.plugins.get( 'TableUtils' ); + const spy = sinon.spy(); + + tableUtils.on( 'insertColumns', () => { + model.change( writer => { + const table = model.document.getRoot().getNodeByPath( [ 0 ] ); + const paragraph = writer.createElement( 'paragraph' ); + + model.insertContent( paragraph, writer.createPositionBefore( table ) ); + + assertEqualMarkup( getData( model ), '' + modelTable( [ + [ '11[]', '', '12' ], + [ '21', '', '22' ] ] ) ); + } ); - command.execute(); - - expect( insertColumnsStub.callCount ).to.equal( 1 ); - expect( insertColumnsStub.firstCall.args[ 1 ] ).to.deep.equal( { - columns: 1, - at: 1, - cellProperties: { - horizontalAlignment: 'center', - verticalAlignment: 'middle' - } - } ); - } - ); + spy(); + }, { priority: 'low' } ); + + command.execute(); + + expect( spy.calledOnce ).to.equal( true ); - it( 'should create the table and all cells should have applied the default cell properties', () => { - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - horizontalAlignment: 'right', - verticalAlignment: 'bottom' - }; - - editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); - - // Apply default properties for the created table. - setData( model, modelTable( [ - [ '11[]' ], - [ '21' ] - ], { cellProperties: defaultProperties } ) ); - - command.execute(); - - assertEqualMarkup( getData( model ), - modelTable( [ - [ '11[]', '' ], - [ '21', '' ] - ], { cellProperties: defaultProperties } ) - ); - } ); + editor.execute( 'undo' ); + + assertEqualMarkup( getData( model ), modelTable( [ + [ '11[]', '12' ], + [ '21', '22' ] + ] ) ); } ); } ); } ); @@ -454,79 +418,6 @@ describe( 'InsertColumnCommand', () => { [ { contents: '20', colspan: 5 }, { contents: '24', colspan: 2 } ] ], { headingColumns: 5 } ) ); } ); - - describe( 'integration with TableCellPropertiesEditing', () => { - let editor, model, tableUtils, command; - - beforeEach( () => { - return ModelTestEditor - .create( { - plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] - } ) - .then( newEditor => { - editor = newEditor; - model = editor.model; - - command = editor.commands.get( 'insertTableColumnLeft' ); - tableUtils = editor.plugins.get( 'TableUtils' ); - } ); - } ); - - afterEach( () => { - return editor.destroy(); - } ); - - it( - 'should pass the default cell styles to "TableUtils.insertColumns()" function if TableCellPropertiesEditing is enabled', - () => { - const insertColumnsStub = sinon.stub( tableUtils, 'insertColumns' ).callThrough(); - - setData( model, modelTable( [ - [ '11[]' ], - [ '21' ] - ] ) ); - - command.execute(); - - expect( insertColumnsStub.callCount ).to.equal( 1 ); - expect( insertColumnsStub.firstCall.args[ 1 ] ).to.deep.equal( { - columns: 1, - at: 0, - cellProperties: { - horizontalAlignment: 'center', - verticalAlignment: 'middle' - } - } ); - } - ); - - it( 'should create the table and all cells should have applied the default cell properties', () => { - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - horizontalAlignment: 'right', - verticalAlignment: 'bottom' - }; - - editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); - - // Apply default properties for the created table. - setData( model, modelTable( [ - [ '11[]' ], - [ '21' ] - ], { cellProperties: defaultProperties } ) ); - - command.execute(); - - assertEqualMarkup( getData( model ), - modelTable( [ - [ '', '11[]' ], - [ '', '21' ] - ], { cellProperties: defaultProperties } ) - ); - } ); - } ); } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/commands/insertrowcommand.js b/packages/ckeditor5-table/tests/commands/insertrowcommand.js index 7c9708d73a3..ad470858f61 100644 --- a/packages/ckeditor5-table/tests/commands/insertrowcommand.js +++ b/packages/ckeditor5-table/tests/commands/insertrowcommand.js @@ -14,7 +14,7 @@ import TableSelection from '../../src/tableselection'; import { assertSelectedCells, modelTable } from '../_utils/utils'; import InsertRowCommand from '../../src/commands/insertrowcommand'; -import TableCellPropertiesEditing from '../../src/tablecellproperties/tablecellpropertiesediting'; +import { UndoEditing } from '@ckeditor/ckeditor5-undo'; describe( 'InsertRowCommand', () => { let editor, model, command; @@ -22,7 +22,7 @@ describe( 'InsertRowCommand', () => { beforeEach( () => { return ModelTestEditor .create( { - plugins: [ Paragraph, TableEditing, TableSelection, HorizontalLineEditing ] + plugins: [ Paragraph, TableEditing, TableSelection, HorizontalLineEditing, UndoEditing ] } ) .then( newEditor => { editor = newEditor; @@ -310,75 +310,42 @@ describe( 'InsertRowCommand', () => { ] ) ); } ); - describe( 'integration with TableCellPropertiesEditing', () => { - let editor, model, tableUtils, command; - - beforeEach( () => { - return ModelTestEditor - .create( { - plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] - } ) - .then( newEditor => { - editor = newEditor; - model = editor.model; - - command = editor.commands.get( 'insertTableRowBelow' ); - tableUtils = editor.plugins.get( 'TableUtils' ); - } ); - } ); - - afterEach( () => { - return editor.destroy(); - } ); - - it( - 'should pass the default cell styles to "TableUtils.insertRows()" function if TableCellPropertiesEditing is enabled', - () => { - const insertRowsStub = sinon.stub( tableUtils, 'insertRows' ).callThrough(); - - setData( model, modelTable( [ - [ '11[]', '12' ] - ] ) ); + it( 'should create a single undo step when inserting a column', () => { + setData( model, modelTable( [ + [ '11[]', '12' ], + [ '21', '22' ] + ] ) ); - command.execute(); - - expect( insertRowsStub.callCount ).to.equal( 1 ); - expect( insertRowsStub.firstCall.args[ 1 ] ).to.deep.equal( { - at: 1, - copyStructureFromAbove: true, - cellProperties: { - horizontalAlignment: 'center', - verticalAlignment: 'middle' - } - } ); - } - ); + const tableUtils = editor.plugins.get( 'TableUtils' ); + const spy = sinon.spy(); + + tableUtils.on( 'insertRows', () => { + model.change( writer => { + const table = model.document.getRoot().getNodeByPath( [ 0 ] ); + const paragraph = writer.createElement( 'paragraph' ); + + model.insertContent( paragraph, writer.createPositionBefore( table ) ); - it( 'should create the table and all cells should have applied the default cell properties', () => { - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - horizontalAlignment: 'right', - verticalAlignment: 'bottom' - }; + assertEqualMarkup( getData( model ), '' + modelTable( [ + [ '11[]', '12' ], + [ '', '' ], + [ '21', '22' ] + ] ) ); + } ); - editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); + spy(); + }, { priority: 'low' } ); - // Apply default properties for the created table. - setData( model, modelTable( [ - [ '11[]', '12' ] - ], { cellProperties: defaultProperties } ) ); + command.execute(); - command.execute(); + expect( spy.calledOnce ).to.equal( true ); - assertEqualMarkup( getData( model ), - modelTable( [ - [ '11[]', '12' ], - [ '', '' ] - ], { cellProperties: defaultProperties } ) - ); - } ); + editor.execute( 'undo' ); + + assertEqualMarkup( getData( model ), modelTable( [ + [ '11[]', '12' ], + [ '21', '22' ] + ] ) ); } ); } ); } ); @@ -542,77 +509,6 @@ describe( 'InsertRowCommand', () => { [ '10', '11', '12' ] ] ) ); } ); - - describe( 'integration with TableCellPropertiesEditing', () => { - let editor, model, tableUtils, command; - - beforeEach( () => { - return ModelTestEditor - .create( { - plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] - } ) - .then( newEditor => { - editor = newEditor; - model = editor.model; - - command = editor.commands.get( 'insertTableRowAbove' ); - tableUtils = editor.plugins.get( 'TableUtils' ); - } ); - } ); - - afterEach( () => { - return editor.destroy(); - } ); - - it( - 'should pass the default cell styles to "TableUtils.insertRows()" function if TableCellPropertiesEditing is enabled', - () => { - const insertRowsStub = sinon.stub( tableUtils, 'insertRows' ).callThrough(); - - setData( model, modelTable( [ - [ '11[]', '12' ] - ] ) ); - - command.execute(); - - expect( insertRowsStub.callCount ).to.equal( 1 ); - expect( insertRowsStub.firstCall.args[ 1 ] ).to.deep.equal( { - at: 0, - copyStructureFromAbove: false, - cellProperties: { - horizontalAlignment: 'center', - verticalAlignment: 'middle' - } - } ); - } - ); - - it( 'should create the table and all cells should have applied the default cell properties', () => { - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - horizontalAlignment: 'right', - verticalAlignment: 'bottom' - }; - - editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); - - // Apply default properties for the created table. - setData( model, modelTable( [ - [ '11[]', '12' ] - ], { cellProperties: defaultProperties } ) ); - - command.execute(); - - assertEqualMarkup( getData( model ), - modelTable( [ - [ '', '' ], - [ '11[]', '12' ] - ], { cellProperties: defaultProperties } ) - ); - } ); - } ); } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/commands/inserttablecommand.js b/packages/ckeditor5-table/tests/commands/inserttablecommand.js index b128f4df81c..45d61c50adc 100644 --- a/packages/ckeditor5-table/tests/commands/inserttablecommand.js +++ b/packages/ckeditor5-table/tests/commands/inserttablecommand.js @@ -12,8 +12,6 @@ import TableEditing from '../../src/tableediting'; import { modelTable } from '../_utils/utils'; import InsertTableCommand from '../../src/commands/inserttablecommand'; -import TablePropertiesEditing from '../../src/tableproperties/tablepropertiesediting'; -import TableCellPropertiesEditing from '../../src/tablecellproperties/tablecellpropertiesediting'; describe( 'InsertTableCommand', () => { let editor, model, command; @@ -170,124 +168,6 @@ describe( 'InsertTableCommand', () => { ] ) ); } ); - - describe( 'integration with TablePropertiesEditing', () => { - let editor, model, command, tableUtils; - - beforeEach( () => { - return ModelTestEditor - .create( { - plugins: [ Paragraph, TableEditing, TablePropertiesEditing ] - } ) - .then( newEditor => { - editor = newEditor; - model = editor.model; - setData( model, '[]' ); - - command = editor.commands.get( 'insertTable' ); - tableUtils = editor.plugins.get( 'TableUtils' ); - } ); - } ); - - afterEach( () => { - return editor.destroy(); - } ); - - it( - 'should pass the default table styles to "TableUtils.createTable()" function if TablePropertiesEditing is enabled', - () => { - const createTableStub = sinon.stub( tableUtils, 'createTable' ).callThrough(); - - command.execute(); - - expect( createTableStub.callCount ).to.equal( 1 ); - expect( createTableStub.firstCall.args[ 1 ] ).to.deep.equal( { - tableProperties: { alignment: 'center' } - } ); - } - ); - - it( 'should create the table with applied the default properties', () => { - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - alignment: 'right' - }; - - editor.config.set( 'table.tableProperties.defaultProperties', defaultProperties ); - - command.execute(); - - assertEqualMarkup( getData( model ), - modelTable( [ - [ '[]', '' ], - [ '', '' ] - ], { ...defaultProperties } ) - ); - } ); - } ); - - describe( 'integration with TableCellPropertiesEditing', () => { - let editor, model, command, tableUtils; - - beforeEach( () => { - return ModelTestEditor - .create( { - plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] - } ) - .then( newEditor => { - editor = newEditor; - model = editor.model; - setData( model, '[]' ); - - command = editor.commands.get( 'insertTable' ); - tableUtils = editor.plugins.get( 'TableUtils' ); - } ); - } ); - - afterEach( () => { - return editor.destroy(); - } ); - - it( - 'should pass the default cell styles to "TableUtils.createTable()" function if TableCellPropertiesEditing is enabled', - () => { - const createTableStub = sinon.stub( tableUtils, 'createTable' ).callThrough(); - - command.execute(); - - expect( createTableStub.callCount ).to.equal( 1 ); - expect( createTableStub.firstCall.args[ 1 ] ).to.deep.equal( { - cellProperties: { - horizontalAlignment: 'center', - verticalAlignment: 'middle' - } - } ); - } - ); - - it( 'should create the table and all cells should have applied the default cell properties', () => { - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - horizontalAlignment: 'right', - verticalAlignment: 'bottom' - }; - - editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); - - command.execute(); - - assertEqualMarkup( getData( model ), - modelTable( [ - [ '[]', '' ], - [ '', '' ] - ], { cellProperties: defaultProperties } ) - ); - } ); - } ); } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/commands/splitcellcommand.js b/packages/ckeditor5-table/tests/commands/splitcellcommand.js index fd3885f2bd0..b9ef82d29bc 100644 --- a/packages/ckeditor5-table/tests/commands/splitcellcommand.js +++ b/packages/ckeditor5-table/tests/commands/splitcellcommand.js @@ -13,7 +13,6 @@ import TableSelection from '../../src/tableselection'; import { modelTable } from '../_utils/utils'; import SplitCellCommand from '../../src/commands/splitcellcommand'; -import TableCellPropertiesEditing from '../../src/tablecellproperties/tablecellpropertiesediting'; describe( 'SplitCellCommand', () => { let editor, model, command; @@ -165,75 +164,6 @@ describe( 'SplitCellCommand', () => { [ '25' ] ] ) ); } ); - - describe( 'integration with TableCellPropertiesEditing', () => { - let editor, model, tableUtils, command; - - beforeEach( () => { - return ModelTestEditor - .create( { - plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] - } ) - .then( newEditor => { - editor = newEditor; - model = editor.model; - - command = editor.commands.get( 'splitTableCellVertically' ); - tableUtils = editor.plugins.get( 'TableUtils' ); - } ); - } ); - - afterEach( () => { - return editor.destroy(); - } ); - - it( - 'should pass the default cell styles to "TableUtils.splitCellVertically()" function if TableCellPropertiesEditing ' + - 'is enabled', - () => { - const splitCellVerticallyStub = sinon.stub( tableUtils, 'splitCellVertically' ).callThrough(); - - setData( model, modelTable( [ - [ '11[]' ] - ] ) ); - - command.execute(); - - expect( splitCellVerticallyStub.callCount ).to.equal( 1 ); - expect( splitCellVerticallyStub.firstCall.args[ 2 ] ).to.deep.equal( { - cellProperties: { - horizontalAlignment: 'center', - verticalAlignment: 'middle' - } - } ); - } - ); - - it( 'should create the table and all cells should have applied the default cell properties', () => { - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - horizontalAlignment: 'right', - verticalAlignment: 'bottom' - }; - - editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); - - // Apply default properties for the created table. - setData( model, modelTable( [ - [ '11[]' ] - ], { cellProperties: defaultProperties } ) ); - - command.execute(); - - assertEqualMarkup( getData( model ), - modelTable( [ - [ '11[]', '' ] - ], { cellProperties: defaultProperties } ) - ); - } ); - } ); } ); } ); @@ -275,76 +205,6 @@ describe( 'SplitCellCommand', () => { [ '20', '21', '22' ] ] ) ); } ); - - describe( 'integration with TableCellPropertiesEditing', () => { - let editor, model, tableUtils, command; - - beforeEach( () => { - return ModelTestEditor - .create( { - plugins: [ Paragraph, TableEditing, TableCellPropertiesEditing ] - } ) - .then( newEditor => { - editor = newEditor; - model = editor.model; - - command = editor.commands.get( 'splitTableCellHorizontally' ); - tableUtils = editor.plugins.get( 'TableUtils' ); - } ); - } ); - - afterEach( () => { - return editor.destroy(); - } ); - - it( - 'should pass the default cell styles to "TableUtils.splitCellHorizontally()" function if TableCellPropertiesEditing ' + - 'is enabled', - () => { - const splitCellHorizontallyStub = sinon.stub( tableUtils, 'splitCellHorizontally' ).callThrough(); - - setData( model, modelTable( [ - [ '11[]' ] - ] ) ); - - command.execute(); - - expect( splitCellHorizontallyStub.callCount ).to.equal( 1 ); - expect( splitCellHorizontallyStub.firstCall.args[ 2 ] ).to.deep.equal( { - cellProperties: { - horizontalAlignment: 'center', - verticalAlignment: 'middle' - } - } ); - } - ); - - it( 'should create the table and all cells should have applied the default cell properties', () => { - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - horizontalAlignment: 'right', - verticalAlignment: 'bottom' - }; - - editor.config.set( 'table.tableCellProperties.defaultProperties', defaultProperties ); - - // Apply default properties for the created table. - setData( model, modelTable( [ - [ '11[]' ] - ], { cellProperties: defaultProperties } ) ); - - command.execute(); - - assertEqualMarkup( getData( model ), - modelTable( [ - [ '11[]' ], - [ '' ] - ], { cellProperties: defaultProperties } ) - ); - } ); - } ); } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js index 7b974b8a03f..f026f667a72 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js @@ -19,9 +19,11 @@ import TableCellVerticalAlignmentCommand from '../../src/tablecellproperties/com import TableCellPaddingCommand from '../../src/tablecellproperties/commands/tablecellpaddingcommand'; import TableCellBackgroundColorCommand from '../../src/tablecellproperties/commands/tablecellbackgroundcolorcommand'; -import { setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; +import { getData, setData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils'; -import { assertTableCellStyle, assertTRBLAttribute } from '../_utils/utils'; +import { assertTableCellStyle, assertTRBLAttribute, modelTable } from '../_utils/utils'; +import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor'; +import TableUtils from '../../src/tableutils'; describe( 'table cell properties', () => { describe( 'TableCellPropertiesEditing', () => { @@ -43,6 +45,10 @@ describe( 'table cell properties', () => { expect( TableCellPropertiesEditing.pluginName ).to.equal( 'TableCellPropertiesEditing' ); } ); + it( 'should require TableUtils', () => { + expect( TableCellPropertiesEditing.requires ).to.include( TableUtils ); + } ); + it( 'adds tableCellBorderColor command', () => { expect( editor.commands.get( 'tableCellBorderColor' ) ).to.be.instanceOf( TableCellBorderColorCommand ); } ); @@ -1259,5 +1265,99 @@ describe( 'table cell properties', () => { } ); } ); } ); + + describe( 'default cell properties', () => { + let editor, model; + + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + beforeEach( () => { + return ModelTestEditor + .create( { + plugins: [ Paragraph, TableCellPropertiesEditing ], + table: { + tableCellProperties: { + defaultProperties + } + } + } ) + .then( newEditor => { + editor = newEditor; + model = editor.model; + setData( model, '[]' ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( 'should create a table and all cells should have applied the default cell properties', () => { + editor.execute( 'insertTable' ); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '[]', '' ], + [ '', '' ] + ], { cellProperties: defaultProperties } ) + ); + } ); + + it( 'should apply default cell properties when inserting a new column (command=insertTableColumnRight)', () => { + editor.execute( 'insertTable' ); + editor.execute( 'insertTableColumnRight' ); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '[]', '', '' ], + [ '', '', '' ] + ], { cellProperties: defaultProperties } ) + ); + } ); + + it( 'should apply default cell properties when inserting a new column (command=insertTableColumnLeft)', () => { + editor.execute( 'insertTable' ); + editor.execute( 'insertTableColumnLeft' ); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '', '[]', '' ], + [ '', '', '' ] + ], { cellProperties: defaultProperties } ) + ); + } ); + + it( 'should apply default cell properties when inserting a new row (command=insertTableRowAbove)', () => { + editor.execute( 'insertTable' ); + editor.execute( 'insertTableRowAbove' ); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '', '' ], + [ '[]', '' ], + [ '', '' ] + ], { cellProperties: defaultProperties } ) + ); + } ); + + it( 'should apply default cell properties when inserting a new row (command=insertTableRowBelow)', () => { + editor.execute( 'insertTable' ); + editor.execute( 'insertTableRowBelow' ); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '[]', '' ], + [ '', '' ], + [ '', '' ] + ], { cellProperties: defaultProperties } ) + ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js b/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js index 20ce3e017bb..fc44e88e069 100644 --- a/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js +++ b/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js @@ -17,9 +17,11 @@ import TableWidthCommand from '../../src/tableproperties/commands/tablewidthcomm import TableHeightCommand from '../../src/tableproperties/commands/tableheightcommand'; import TableBackgroundColorCommand from '../../src/tableproperties/commands/tablebackgroundcolorcommand'; -import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; +import { setData as setModelData, getData as getModelData, setData, getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils'; -import { assertTableStyle, assertTRBLAttribute } from '../_utils/utils'; +import { assertTableStyle, assertTRBLAttribute, modelTable } from '../_utils/utils'; +import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor'; +import TableUtils from '../../src/tableutils'; describe( 'table properties', () => { describe( 'TablePropertiesEditing', () => { @@ -45,6 +47,10 @@ describe( 'table properties', () => { expect( TablePropertiesEditing.pluginName ).to.equal( 'TablePropertiesEditing' ); } ); + it( 'should require TableUtils', () => { + expect( TablePropertiesEditing.requires ).to.include( TableUtils ); + } ); + it( 'adds tableBorderColor command', () => { expect( editor.commands.get( 'tableBorderColor' ) ).to.be.instanceOf( TableBorderColorCommand ); } ); @@ -1252,6 +1258,49 @@ describe( 'table properties', () => { } ); } ); + describe( 'default table properties', () => { + let editor, model; + + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + alignment: 'right' + }; + + beforeEach( () => { + return ModelTestEditor + .create( { + plugins: [ Paragraph, TablePropertiesEditing ], + table: { + tableProperties: { + defaultProperties + } + } + } ) + .then( newEditor => { + editor = newEditor; + model = editor.model; + setData( model, '[]' ); + } ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + it( 'should create a table with applied the default properties', () => { + editor.execute( 'insertTable' ); + + assertEqualMarkup( getData( model ), + modelTable( [ + [ '[]', '' ], + [ '', '' ] + ], { ...defaultProperties } ) + ); + } ); + } ); + function createEmptyTable() { setModelData( model, diff --git a/packages/ckeditor5-table/tests/tableutils.js b/packages/ckeditor5-table/tests/tableutils.js index 35aa1b62320..693eaa1262f 100644 --- a/packages/ckeditor5-table/tests/tableutils.js +++ b/packages/ckeditor5-table/tests/tableutils.js @@ -13,8 +13,6 @@ import TableEditing from '../src/tableediting'; import { modelTable } from './_utils/utils'; import TableUtils from '../src/tableutils'; -import TablePropertiesEditing from '../src/tableproperties/tablepropertiesediting'; -import TableCellPropertiesEditing from '../src/tablecellproperties/tablecellpropertiesediting'; describe( 'TableUtils', () => { let editor, model, root, tableUtils; @@ -277,6 +275,47 @@ describe( 'TableUtils', () => { ] ) ); } ); + it( 'should return created tableCell elements (insert in the middle)', () => { + setData( model, modelTable( [ + [ '11[]', '12' ], + [ '21', '22' ] + ] ) ); + + const insertedCells = tableUtils.insertRows( root.getNodeByPath( [ 0 ] ), { at: 1 } ); + + expect( insertedCells.length ).to.equal( 2 ); + expect( root.getNodeByPath( [ 0, 1, 0 ] ) ).to.equal( insertedCells[ 0 ] ); + expect( root.getNodeByPath( [ 0, 1, 1 ] ) ).to.equal( insertedCells[ 1 ] ); + } ); + + it( 'should return created tableCell elements (insert in the the beginning)', () => { + setData( model, modelTable( [ + [ '11[]', '12' ], + [ '21', '22' ] + ] ) ); + + const insertedCells = tableUtils.insertRows( root.getNodeByPath( [ 0 ] ), { rows: 2 } ); + + expect( insertedCells.length ).to.equal( 4 ); + expect( root.getNodeByPath( [ 0, 1, 1 ] ) ).to.equal( insertedCells[ 0 ] ); + expect( root.getNodeByPath( [ 0, 1, 0 ] ) ).to.equal( insertedCells[ 1 ] ); + expect( root.getNodeByPath( [ 0, 0, 1 ] ) ).to.equal( insertedCells[ 2 ] ); + expect( root.getNodeByPath( [ 0, 0, 0 ] ) ).to.equal( insertedCells[ 3 ] ); + } ); + + it( 'should return created tableCell elements (insert in the the end)', () => { + setData( model, modelTable( [ + [ '11[]', '12' ], + [ '21', '22' ] + ] ) ); + + const insertedCells = tableUtils.insertRows( root.getNodeByPath( [ 0 ] ), { at: 2 } ); + + expect( insertedCells.length ).to.equal( 2 ); + expect( root.getNodeByPath( [ 0, 2, 1 ] ) ).to.equal( insertedCells[ 0 ] ); + expect( root.getNodeByPath( [ 0, 2, 0 ] ) ).to.equal( insertedCells[ 1 ] ); + } ); + describe( 'with copyStructureFrom enabled', () => { beforeEach( () => { // +----+----+----+----+----+----+ @@ -290,7 +329,7 @@ describe( 'TableUtils', () => { ] ) ); } ); - it( 'should not copy structure from the first row (copyStructureFromAbove=false)', () => { + it( 'should copy structure from the first row', () => { tableUtils.insertRows( root.getNodeByPath( [ 0 ] ), { at: 0, rows: 1, copyStructureFromAbove: false } ); // +----+----+----+----+----+----+ @@ -358,171 +397,6 @@ describe( 'TableUtils', () => { ] ) ); } ); } ); - - describe( 'integration with TableCellPropertiesEditing', () => { - let editor, model, tableUtils, table; - - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - horizontalAlignment: 'right', - verticalAlignment: 'bottom' - }; - - beforeEach( () => { - return ModelTestEditor.create( { - plugins: [ Paragraph, TableEditing, TableUtils, TableCellPropertiesEditing ] - } ).then( newEditor => { - editor = newEditor; - model = editor.model; - tableUtils = editor.plugins.get( TableUtils ); - - // +----+----+----+----+----+----+ - // | 00 | 01 | 03 | 04 | 05 | - // +----+ + +----+----+ - // | 10 | | | 14 | - // +----+----+----+----+----+----+ - // | 20 | 21 | 22 | 23 | 24 | 25 | - // +----+----+----+----+----+----+ - setData( model, modelTable( [ - [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], - [ '10', { contents: '14', colspan: 2 } ], - [ '20', '21', '22', '23', '24', '25' ] - ], { cellProperties: defaultProperties } ) ); - - const root = model.document.getRoot( 'main' ); - table = root.getNodeByPath( [ 0 ] ); - } ); - } ); - - afterEach( () => { - return editor.destroy(); - } ); - - it( 'should insert a new row and apply default cell properties to all created cells (insert below, single row)', () => { - tableUtils.insertRows( table, { - at: 3, - cellProperties: defaultProperties - } ); - - // +----+----+----+----+----+----+ - // | 00 | 01 | 03 | 04 | 05 | - // +----+ + +----+----+ - // | 10 | | | 14 | - // +----+----+----+----+----+----+ - // | 20 | 21 | 22 | 23 | 24 | 25 | - // +----+----+----+----+----+----+ - // | | | | | | | - // +----+----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], - [ '10', { contents: '14', colspan: 2 } ], - [ '20', '21', '22', '23', '24', '25' ], - [ '', '', '', '', '', '' ] - ], { cellProperties: defaultProperties } ) ); - } ); - - it( 'should insert a new row and apply default cell properties to all created cells (insert below, double row)', () => { - tableUtils.insertRows( table, { - at: 3, - rows: 2, - cellProperties: defaultProperties - } ); - - // +----+----+----+----+----+----+ - // | 00 | 01 | 03 | 04 | 05 | - // +----+ + +----+----+ - // | 10 | | | 14 | - // +----+----+----+----+----+----+ - // | 20 | 21 | 22 | 23 | 24 | 25 | - // +----+----+----+----+----+----+ - // | | | | | | | - // +----+----+----+----+----+----+ - // | | | | | | | - // +----+----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], - [ '10', { contents: '14', colspan: 2 } ], - [ '20', '21', '22', '23', '24', '25' ], - [ '', '', '', '', '', '' ], - [ '', '', '', '', '', '' ] - ], { cellProperties: defaultProperties } ) ); - } ); - - it( 'should insert a new row and apply default cell properties to all created cells (insert above, single row)', () => { - tableUtils.insertRows( table, { - at: 0, - cellProperties: defaultProperties - } ); - - // +----+----+----+----+----+----+ - // | | | | | | | - // +----+----+----+----+----+----+ - // | 00 | 01 | 03 | 04 | 05 | - // +----+ + +----+----+ - // | 10 | | | 14 | - // +----+----+----+----+----+----+ - // | 20 | 21 | 22 | 23 | 24 | 25 | - // +----+----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '', '', '', '', '', '' ], - [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], - [ '10', { contents: '14', colspan: 2 } ], - [ '20', '21', '22', '23', '24', '25' ] - ], { cellProperties: defaultProperties } ) ); - } ); - - it( 'should insert a new row and apply default cell properties to all created cells (insert above, double row)', () => { - tableUtils.insertRows( table, { - at: 0, - rows: 2, - cellProperties: defaultProperties - } ); - - // +----+----+----+----+----+----+ - // | | | | | | | - // +----+----+----+----+----+----+ - // | | | | | | | - // +----+----+----+----+----+----+ - // | 00 | 01 | 03 | 04 | 05 | - // +----+ + +----+----+ - // | 10 | | | 14 | - // +----+----+----+----+----+----+ - // | 20 | 21 | 22 | 23 | 24 | 25 | - // +----+----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '', '', '', '', '', '' ], - [ '', '', '', '', '', '' ], - [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '05' ], - [ '10', { contents: '14', colspan: 2 } ], - [ '20', '21', '22', '23', '24', '25' ] - ], { cellProperties: defaultProperties } ) ); - } ); - - it( 'should insert a new row and apply default cell properties to all created cells (insert in the middle, single row)', () => { - tableUtils.insertRows( table, { - at: 1, - cellProperties: defaultProperties - } ); - - // +----+----+----+----+----+----+ - // | 00 | 01 | 03 | 04 | 05 | - // +----+ + +----+----+ - // | | | | | | - // +----+ + +----+----+ - // | 10 | | | 14 | - // +----+----+----+----+----+----+ - // | 20 | 21 | 22 | 23 | 24 | 25 | - // +----+----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '00', { contents: '01', colspan: 2, rowspan: 3 }, { contents: '03', rowspan: 3 }, '04', '05' ], - [ '', '', '' ], - [ '10', { contents: '14', colspan: 2 } ], - [ '20', '21', '22', '23', '24', '25' ] - ], { cellProperties: defaultProperties } ) ); - } ); - } ); } ); describe( 'insertColumns()', () => { @@ -765,130 +639,45 @@ describe( 'TableUtils', () => { ], { headingColumns: 3 } ) ); } ); - describe( 'integration with TableCellPropertiesEditing', () => { - let editor, model, tableUtils, table; - - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - horizontalAlignment: 'right', - verticalAlignment: 'bottom' - }; - - beforeEach( () => { - return ModelTestEditor.create( { - plugins: [ Paragraph, TableEditing, TableUtils, TableCellPropertiesEditing ] - } ).then( newEditor => { - editor = newEditor; - model = editor.model; - tableUtils = editor.plugins.get( TableUtils ); - - // +----+----+----+----+----+ - // | 00 | 01 | 03 | 04 | - // +----+ + +----+ - // | 10 | | | 14 | - // +----+----+----+----+----+ - setData( model, modelTable( [ - [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], - [ '10', '14' ] - ], { cellProperties: defaultProperties } ) ); - - const root = model.document.getRoot( 'main' ); - table = root.getNodeByPath( [ 0 ] ); - } ); - } ); - - afterEach( () => { - return editor.destroy(); - } ); - - it( 'should insert a new column and apply default cell properties to all created cells (insert right, single column)', () => { - tableUtils.insertColumns( table, { - at: 5, - cellProperties: defaultProperties - } ); - - // +----+----+----+----+----+----+ - // | 00 | 01 | 03 | 04 | | - // +----+ + +----+----+ - // | 10 | | | 14 | | - // +----+----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '' ], - [ '10', '14', '' ] - ], { cellProperties: defaultProperties } ) ); - } ); + it( 'should return created tableCell elements (insert in the middle)', () => { + setData( model, modelTable( [ + [ '11[]', '12' ], + [ '21', '22' ] + ] ) ); - it( 'should insert a new column and apply default cell properties to all created cells (insert right, double column)', () => { - tableUtils.insertColumns( table, { - at: 5, - columns: 2, - cellProperties: defaultProperties - } ); + const insertedCells = tableUtils.insertColumns( root.getNodeByPath( [ 0 ] ), { at: 1 } ); - // +----+----+----+----+----+----+----+ - // | 00 | 01 | 03 | 04 | | | - // +----+ + +----+----+----+ - // | 10 | | | 14 | | | - // +----+----+----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04', '', '' ], - [ '10', '14', '', '' ] - ], { cellProperties: defaultProperties } ) ); - } ); + expect( insertedCells.length ).to.equal( 2 ); + expect( root.getNodeByPath( [ 0, 0, 1 ] ) ).to.equal( insertedCells[ 0 ] ); + expect( root.getNodeByPath( [ 0, 1, 1 ] ) ).to.equal( insertedCells[ 1 ] ); + } ); - it( 'should insert a new column and apply default cell properties to all created cells (insert left, single column)', () => { - tableUtils.insertColumns( table, { - at: 0, - cellProperties: defaultProperties - } ); + it( 'should return created tableCell elements (insert in the the beginning)', () => { + setData( model, modelTable( [ + [ '11[]', '12' ], + [ '21', '22' ] + ] ) ); - // +----+----+----+----+----+----+ - // | | 00 | 01 | 03 | 04 | - // +----+----+ + +----+ - // | | 10 | | | 14 | - // +----+----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '', '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], - [ '', '10', '14' ] - ], { cellProperties: defaultProperties } ) ); - } ); + const insertedCells = tableUtils.insertColumns( root.getNodeByPath( [ 0 ] ), { columns: 2 } ); - it( 'should insert a new column and apply default cell properties to all created cells (insert left, double column)', () => { - tableUtils.insertColumns( table, { - at: 0, - columns: 2, - cellProperties: defaultProperties - } ); + expect( insertedCells.length ).to.equal( 4 ); + expect( root.getNodeByPath( [ 0, 0, 1 ] ) ).to.equal( insertedCells[ 0 ] ); + expect( root.getNodeByPath( [ 0, 0, 0 ] ) ).to.equal( insertedCells[ 1 ] ); + expect( root.getNodeByPath( [ 0, 1, 1 ] ) ).to.equal( insertedCells[ 2 ] ); + expect( root.getNodeByPath( [ 0, 1, 0 ] ) ).to.equal( insertedCells[ 3 ] ); + } ); - // +----+----+----+----+----+----+----+ - // | | | 00 | 01 | 03 | 04 | - // +----+----+----+ + +----+ - // | | | 10 | | | 14 | - // +----+----+----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '', '', '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], - [ '', '', '10', '14' ] - ], { cellProperties: defaultProperties } ) ); - } ); + it( 'should return created tableCell elements (insert in the the end)', () => { + setData( model, modelTable( [ + [ '11[]', '12' ], + [ '21', '22' ] + ] ) ); - it( 'should insert a new row and apply default cell properties to all created cells (insert in the middle, single row)', () => { - tableUtils.insertColumns( table, { - at: 3, - cellProperties: defaultProperties - } ); + const insertedCells = tableUtils.insertColumns( root.getNodeByPath( [ 0 ] ), { columns: 1, at: 2 } ); - // +----+----+----+----+----+----+ - // | 00 | 01 | | 03 | 04 | - // +----+ +----+ +----+ - // | 10 | | | | 14 | - // +----+----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '00', { contents: '01', colspan: 2, rowspan: 2 }, '', { contents: '03', rowspan: 2 }, '04' ], - [ '10', '', '14' ] - ], { cellProperties: defaultProperties } ) ); - } ); + expect( insertedCells.length ).to.equal( 2 ); + expect( root.getNodeByPath( [ 0, 0, 2 ] ) ).to.equal( insertedCells[ 0 ] ); + expect( root.getNodeByPath( [ 0, 1, 2 ] ) ).to.equal( insertedCells[ 1 ] ); } ); } ); @@ -1034,122 +823,6 @@ describe( 'TableUtils', () => { [ '10[]', '', '', '11' ] ], { headingColumns: 3 } ) ); } ); - - describe( 'integration with TableCellPropertiesEditing', () => { - let editor, model, tableUtils, root; - - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - horizontalAlignment: 'right', - verticalAlignment: 'bottom' - }; - - beforeEach( () => { - return ModelTestEditor.create( { - plugins: [ Paragraph, TableEditing, TableUtils, TableCellPropertiesEditing ] - } ).then( newEditor => { - editor = newEditor; - model = editor.model; - tableUtils = editor.plugins.get( TableUtils ); - root = model.document.getRoot( 'main' ); - } ); - } ); - - afterEach( () => { - // The `defaultProperties` object should not be modified. - // All values should be copied to a new object while preparing a cell element. - expect( defaultProperties ).to.not.have.property( 'colspan' ); - expect( defaultProperties ).to.not.have.property( 'rowspan' ); - expect( defaultProperties ).to.have.property( 'borderStyle' ); - expect( defaultProperties ).to.have.property( 'borderWidth' ); - expect( defaultProperties ).to.have.property( 'borderColor' ); - expect( defaultProperties ).to.have.property( 'horizontalAlignment' ); - expect( defaultProperties ).to.have.property( 'verticalAlignment' ); - - return editor.destroy(); - } ); - - it( 'should properly split the column and apply default cell properties (colspan=2, cells=2)', () => { - // +----+----+----+----+ - // | 00 | 01 | 03 | - // +----+----+----+----+ - setData( model, modelTable( [ - [ '00', { contents: '[]01', colspan: 2 }, '03' ] - ], { cellProperties: defaultProperties } ) ); - - const tableCell = root.getNodeByPath( [ 0, 0, 1 ] ); - - tableUtils.splitCellVertically( tableCell, 2, { - cellProperties: defaultProperties - } ); - - // +----+----+----+----+ - // | 00 | 01 | | 03 | - // +----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '00', '01', '', '03' ] - ], { cellProperties: defaultProperties } ) ); - } ); - - it( 'should properly split the column and apply default cell properties (colspan=4, cells=2)', () => { - // +----+----+----+----+----+----+ - // | 00 | 01 | 05 | - // +----+----+----+----+----+----+ - setData( model, modelTable( [ - [ '00', { contents: '[]01', colspan: 4 }, '05' ] - ], { cellProperties: defaultProperties } ) ); - - const tableCell = root.getNodeByPath( [ 0, 0, 1 ] ); - - tableUtils.splitCellVertically( tableCell, 2, { - cellProperties: defaultProperties - } ); - - // +----+----+----+----+----+----+ - // | 00 | 01 | | 05 | - // +----+----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '00', { contents: '01', colspan: 2 }, { contents: '', colspan: 2 }, '05' ] - ], { cellProperties: defaultProperties } ) ); - } ); - - it( 'should properly split the column and apply default cell properties (colspan=2, rowspan=2, cells=3)', () => { - // +----+----+----+----+----+ - // | 00 | 01 | 03 | 04 | - // +----+ + +----+ - // | 10 | | | 14 | - // +----+----+----+----+----+ - setData( model, modelTable( [ - [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], - [ '10', '14' ] - ], { cellProperties: defaultProperties } ) ); - - const tableCell = root.getNodeByPath( [ 0, 0, 1 ] ); - - tableUtils.splitCellVertically( tableCell, 3, { - cellProperties: defaultProperties - } ); - - // +----+----+----+----+----+----+ - // | 00 | 01 | | | 03 | 04 | - // +----+ + + + +----+ - // | 10 | | | | | 14 | - // +----+----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ - '00', - { contents: '01', rowspan: 2 }, - { contents: '', rowspan: 2 }, - { contents: '', rowspan: 2 }, - { contents: '03', rowspan: 2 }, - '04' - ], - [ '10', '14' ] - ], { cellProperties: defaultProperties } ) ); - } ); - } ); } ); describe( 'splitCellHorizontally()', () => { @@ -1325,173 +998,6 @@ describe( 'TableUtils', () => { [ '20', '21', '22' ] ], { headingRows: 3 } ) ); } ); - - describe( 'integration with TableCellPropertiesEditing', () => { - let editor, model, tableUtils, root; - - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - horizontalAlignment: 'right', - verticalAlignment: 'bottom' - }; - - beforeEach( () => { - return ModelTestEditor.create( { - plugins: [ Paragraph, TableEditing, TableUtils, TableCellPropertiesEditing ] - } ).then( newEditor => { - editor = newEditor; - model = editor.model; - tableUtils = editor.plugins.get( TableUtils ); - root = model.document.getRoot( 'main' ); - } ); - } ); - - afterEach( () => { - // The `defaultProperties` object should not be modified. - // All values should be copied to a new object while preparing a cell element. - expect( defaultProperties ).to.not.have.property( 'colspan' ); - expect( defaultProperties ).to.not.have.property( 'rowspan' ); - expect( defaultProperties ).to.have.property( 'borderStyle' ); - expect( defaultProperties ).to.have.property( 'borderWidth' ); - expect( defaultProperties ).to.have.property( 'borderColor' ); - expect( defaultProperties ).to.have.property( 'horizontalAlignment' ); - expect( defaultProperties ).to.have.property( 'verticalAlignment' ); - - return editor.destroy(); - } ); - - it( 'should properly split the column and apply default cell properties (rowspan=2, cells=2)', () => { - // +----+ - // | 00 | - // +----+ - // | 01 | - // + + - // | | - // +----+ - // | 03 | - // +----+ - setData( model, modelTable( [ - [ '00' ], - [ { contents: '[]01', rowspan: 2 } ], - [], - [ '03' ] - ], { cellProperties: defaultProperties } ) ); - - const tableCell = root.getNodeByPath( [ 0, 1, 0 ] ); - - tableUtils.splitCellHorizontally( tableCell, 2, { - cellProperties: defaultProperties - } ); - - // +----+ - // | 00 | - // +----+ - // | 01 | - // +----+ - // | | - // +----+ - // | 03 | - // +----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '00' ], - [ '01' ], - [ '' ], - [ '03' ] - ], { cellProperties: defaultProperties } ) ); - } ); - - it( 'should properly split the column and apply default cell properties (rowspan=4, cells=2)', () => { - // +----+ - // | 00 | - // +----+ - // | 01 | - // + + - // | | - // + + - // | | - // + + - // | | - // +----+ - // | 05 | - // +----+ - setData( model, modelTable( [ - [ '00' ], - [ { contents: '[]01', rowspan: 4 } ], - [], - [], - [], - [ '05' ] - ], { cellProperties: defaultProperties } ) ); - - const tableCell = root.getNodeByPath( [ 0, 1, 0 ] ); - - tableUtils.splitCellHorizontally( tableCell, 2, { - cellProperties: defaultProperties - } ); - - // +----+ - // | 00 | - // +----+ - // | 01 | - // + + - // | | - // +----+ - // | | - // + + - // | | - // +----+ - // | 05 | - // +----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '00' ], - [ { contents: '01', rowspan: 2 } ], - [], - [ { contents: '', rowspan: 2 } ], - [], - [ '05' ] - ], { cellProperties: defaultProperties } ) ); - } ); - - it( 'should properly split the column and apply default cell properties (colspan=2, rowspan=2, cells=3)', () => { - // +----+----+----+----+----+ - // | 00 | 01 | 03 | 04 | - // +----+ + +----+ - // | 10 | | | 14 | - // +----+----+----+----+----+ - setData( model, modelTable( [ - [ '00', { contents: '01', colspan: 2, rowspan: 2 }, { contents: '03', rowspan: 2 }, '04' ], - [ '10', '14' ] - ], { cellProperties: defaultProperties } ) ); - - const tableCell = root.getNodeByPath( [ 0, 0, 1 ] ); - - tableUtils.splitCellHorizontally( tableCell, 3, { - cellProperties: defaultProperties - } ); - - // +----+----+----+----+----+ - // | 00 | 01 | 03 | 04 | - // + +----+----+ + + - // | | | | | - // +----+----+----+ +----+ - // | 10 | | | 14 | - // +----+----+----+----+----+ - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ - { contents: '00', rowspan: 2 }, - { contents: '01', colspan: 2 }, - { contents: '03', rowspan: 3 }, - { contents: '04', rowspan: 2 } - ], - [ - { contents: '', colspan: 2 } - ], - [ '10', { contents: '', colspan: 2 }, '14' ] - ], { cellProperties: defaultProperties } ) ); - } ); - } ); } ); describe( 'getColumns()', () => { @@ -2148,6 +1654,25 @@ describe( 'TableUtils', () => { } ); describe( 'createTable()', () => { + it( 'should be decorated', () => { + const spy = sinon.spy(); + + setData( model, '[]' ); + + tableUtils.on( 'createTable', spy ); + + model.change( writer => { + const table = tableUtils.createTable( writer, { + rows: 2, + columns: 2 + } ); + + model.insertContent( table ); + } ); + + expect( spy.calledOnce ).to.be.true; + } ); + it( 'should create table', () => { setData( model, '[]' ); @@ -2211,71 +1736,5 @@ describe( 'TableUtils', () => { [ '', '' ] ], { headingRows: 2, headingColumns: 1 } ) ); } ); - - describe( 'enabled TablePropertiesEditing + TableCellPropertiesEditing', () => { - let editor, model, tableUtils; - - beforeEach( () => { - return ModelTestEditor.create( { - plugins: [ Paragraph, TableEditing, TableUtils, TablePropertiesEditing, TableCellPropertiesEditing ] - } ).then( newEditor => { - editor = newEditor; - model = editor.model; - tableUtils = editor.plugins.get( TableUtils ); - } ); - } ); - - afterEach( () => { - return editor.destroy(); - } ); - - it( 'should create table and apply specified styles for the table', () => { - setData( model, '[]' ); - - const defaultProperties = { - borderStyle: 'solid', - borderColor: '#f00', - borderWidth: '2px', - width: '400px', - height: '200px', - alignment: 'left' - }; - - model.change( writer => { - const table = tableUtils.createTable( writer, { tableProperties: defaultProperties } ); - - model.insertContent( table, model.document.selection.focus ); - } ); - - // Styles for the table are included in the `attributes` object. - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '', '' ], - [ '', '' ] - ], { ...defaultProperties } ) ); - } ); - - it( 'should create table and apply specified styles for all cells', () => { - setData( model, '[]' ); - - const cellProperties = { - width: '30px', - height: '30px', - verticalAlignment: 'bottom', - horizontalAlignment: 'right' - }; - - model.change( writer => { - const table = tableUtils.createTable( writer, { cellProperties } ); - - model.insertContent( table, model.document.selection.focus ); - } ); - - // Styles for cells are specified as `attributes.cellProperties` object. - assertEqualMarkup( getData( model, { withoutSelection: true } ), modelTable( [ - [ '', '' ], - [ '', '' ] - ], { cellProperties } ) ); - } ); - } ); } ); } ); From a1bf4189ef0d1dbe1395f0cc8e846c46b20d9f8d Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Fri, 9 Apr 2021 14:05:22 +0200 Subject: [PATCH 19/24] Reverted InsertTableCommand. --- .../ckeditor5-table/src/commands/inserttablecommand.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/ckeditor5-table/src/commands/inserttablecommand.js b/packages/ckeditor5-table/src/commands/inserttablecommand.js index 33a966105c7..64b1c533650 100644 --- a/packages/ckeditor5-table/src/commands/inserttablecommand.js +++ b/packages/ckeditor5-table/src/commands/inserttablecommand.js @@ -47,19 +47,17 @@ export default class InsertTableCommand extends Command { * @fires execute */ execute( options = {} ) { - const editor = this.editor; - const model = editor.model; + const model = this.editor.model; const selection = model.document.selection; - const tableUtils = editor.plugins.get( 'TableUtils' ); - - const createTableOptions = Object.assign( {}, options ); + const tableUtils = this.editor.plugins.get( 'TableUtils' ); const insertPosition = findOptimalInsertionPosition( selection, model ); model.change( writer => { - const table = tableUtils.createTable( writer, createTableOptions ); + const table = tableUtils.createTable( writer, options ); model.insertContent( table, insertPosition ); + writer.setSelection( writer.createPositionAt( table.getNodeByPath( [ 0, 0, 0 ] ), 0 ) ); } ); } From f3292f0ec3e1c92b19e29fab09a5dba2bd33fe61 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Fri, 9 Apr 2021 14:06:24 +0200 Subject: [PATCH 20/24] Reverted SplitCellCommand. --- .../ckeditor5-table/src/commands/splitcellcommand.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/ckeditor5-table/src/commands/splitcellcommand.js b/packages/ckeditor5-table/src/commands/splitcellcommand.js index 29d51b6777e..b13deb974b0 100644 --- a/packages/ckeditor5-table/src/commands/splitcellcommand.js +++ b/packages/ckeditor5-table/src/commands/splitcellcommand.js @@ -55,17 +55,14 @@ export default class SplitCellCommand extends Command { * @inheritDoc */ execute() { - const editor = this.editor; - const tableCell = getSelectionAffectedTableCells( editor.model.document.selection )[ 0 ]; + const tableCell = getSelectionAffectedTableCells( this.editor.model.document.selection )[ 0 ]; const isHorizontal = this.direction === 'horizontally'; - const tableUtils = editor.plugins.get( 'TableUtils' ); - - const splitOptions = {}; + const tableUtils = this.editor.plugins.get( 'TableUtils' ); if ( isHorizontal ) { - tableUtils.splitCellHorizontally( tableCell, 2, splitOptions ); + tableUtils.splitCellHorizontally( tableCell, 2 ); } else { - tableUtils.splitCellVertically( tableCell, 2, splitOptions ); + tableUtils.splitCellVertically( tableCell, 2 ); } } } From b00eba23880406383e880722399e7dbdcc52d42a Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Fri, 9 Apr 2021 14:19:29 +0200 Subject: [PATCH 21/24] Clean the code. --- .../tablecellpropertiesediting.js | 14 +++++++------- .../tableproperties/tablepropertiesediting.js | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js index f026f667a72..9ae21979328 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js @@ -19,7 +19,7 @@ import TableCellVerticalAlignmentCommand from '../../src/tablecellproperties/com import TableCellPaddingCommand from '../../src/tablecellproperties/commands/tablecellpaddingcommand'; import TableCellBackgroundColorCommand from '../../src/tablecellproperties/commands/tablecellbackgroundcolorcommand'; -import { getData, setData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; +import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils'; import { assertTableCellStyle, assertTRBLAttribute, modelTable } from '../_utils/utils'; import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor'; @@ -1290,7 +1290,7 @@ describe( 'table cell properties', () => { .then( newEditor => { editor = newEditor; model = editor.model; - setData( model, '[]' ); + setModelData( model, '[]' ); } ); } ); @@ -1301,7 +1301,7 @@ describe( 'table cell properties', () => { it( 'should create a table and all cells should have applied the default cell properties', () => { editor.execute( 'insertTable' ); - assertEqualMarkup( getData( model ), + assertEqualMarkup( getModelData( model ), modelTable( [ [ '[]', '' ], [ '', '' ] @@ -1313,7 +1313,7 @@ describe( 'table cell properties', () => { editor.execute( 'insertTable' ); editor.execute( 'insertTableColumnRight' ); - assertEqualMarkup( getData( model ), + assertEqualMarkup( getModelData( model ), modelTable( [ [ '[]', '', '' ], [ '', '', '' ] @@ -1325,7 +1325,7 @@ describe( 'table cell properties', () => { editor.execute( 'insertTable' ); editor.execute( 'insertTableColumnLeft' ); - assertEqualMarkup( getData( model ), + assertEqualMarkup( getModelData( model ), modelTable( [ [ '', '[]', '' ], [ '', '', '' ] @@ -1337,7 +1337,7 @@ describe( 'table cell properties', () => { editor.execute( 'insertTable' ); editor.execute( 'insertTableRowAbove' ); - assertEqualMarkup( getData( model ), + assertEqualMarkup( getModelData( model ), modelTable( [ [ '', '' ], [ '[]', '' ], @@ -1350,7 +1350,7 @@ describe( 'table cell properties', () => { editor.execute( 'insertTable' ); editor.execute( 'insertTableRowBelow' ); - assertEqualMarkup( getData( model ), + assertEqualMarkup( getModelData( model ), modelTable( [ [ '[]', '' ], [ '', '' ], diff --git a/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js b/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js index fc44e88e069..8d4768b5200 100644 --- a/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js +++ b/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js @@ -17,7 +17,7 @@ import TableWidthCommand from '../../src/tableproperties/commands/tablewidthcomm import TableHeightCommand from '../../src/tableproperties/commands/tableheightcommand'; import TableBackgroundColorCommand from '../../src/tableproperties/commands/tablebackgroundcolorcommand'; -import { setData as setModelData, getData as getModelData, setData, getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; +import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils'; import { assertTableStyle, assertTRBLAttribute, modelTable } from '../_utils/utils'; import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor'; @@ -1281,7 +1281,7 @@ describe( 'table properties', () => { .then( newEditor => { editor = newEditor; model = editor.model; - setData( model, '[]' ); + setModelData( model, '[]' ); } ); } ); @@ -1292,7 +1292,7 @@ describe( 'table properties', () => { it( 'should create a table with applied the default properties', () => { editor.execute( 'insertTable' ); - assertEqualMarkup( getData( model ), + assertEqualMarkup( getModelData( model ), modelTable( [ [ '[]', '' ], [ '', '' ] From 7def43256a725ac60c7e5566047e452314cc6a3a Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Fri, 9 Apr 2021 16:58:34 +0200 Subject: [PATCH 22/24] Added the table cell default properties post fixer. --- ...able-cell-default-properties-post-fixer.js | 82 ++++ .../src/converters/table-layout-post-fixer.js | 32 +- .../src/tablecellproperties.js | 8 - .../tablecellpropertiesediting.js | 8 +- packages/ckeditor5-table/src/tableediting.js | 2 +- .../ckeditor5-table/src/tableproperties.js | 7 - .../tableproperties/tablepropertiesediting.js | 4 +- ...able-cell-default-properties-post-fixer.js | 357 ++++++++++++++++++ .../converters/table-layout-post-fixer.js | 72 ---- .../tablecellpropertiesediting.js | 5 +- .../tablecellpropertiesui.js | 5 +- .../tableproperties/tablepropertiesediting.js | 4 +- .../tableproperties/tablepropertiesui.js | 4 +- 13 files changed, 457 insertions(+), 133 deletions(-) create mode 100644 packages/ckeditor5-table/src/converters/table-cell-default-properties-post-fixer.js create mode 100644 packages/ckeditor5-table/tests/converters/table-cell-default-properties-post-fixer.js diff --git a/packages/ckeditor5-table/src/converters/table-cell-default-properties-post-fixer.js b/packages/ckeditor5-table/src/converters/table-cell-default-properties-post-fixer.js new file mode 100644 index 00000000000..c22a5b50372 --- /dev/null +++ b/packages/ckeditor5-table/src/converters/table-cell-default-properties-post-fixer.js @@ -0,0 +1,82 @@ +/** + * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +/** + * @module table/converters/table-layout-post-fixer + */ + +import TableWalker from './../tablewalker'; + +/** + * Injects a table cell default properties post-fixer into the model. + * + * A table cell should have specified the default properties when a new cell was added into the table. + * + * @param {module:core/editor/editor~Editor} editor + */ +export default function injectTableCellDefaultPropertiesPostFixer( editor ) { + editor.model.document.registerPostFixer( writer => tableCellDefaultPropertiesPostFixer( writer, editor ) ); +} + +// The table cell default properties post-fixer. +// +// @param {module:engine/model/writer~Writer} writer +// @param {module:core/editor/editor~Editor} editor +function tableCellDefaultPropertiesPostFixer( writer, editor ) { + const model = editor.model; + const changes = model.document.differ.getChanges(); + const cellProperties = editor.config.get( 'table.tableCellProperties.defaultProperties' ); + + // Do not check anything if the default cell properties are not specified. + if ( Object.keys( cellProperties ).length === 0 ) { + return false; + } + + let wasFixed = false; + + // Do not analyze the same table more then once - may happen for multiple changes in the same table. + const analyzedTables = new Set(); + + for ( const entry of changes ) { + let table; + + if ( entry.name == 'table' && entry.type == 'insert' ) { + table = entry.position.nodeAfter; + } + + // Fix table on adding/removing table cells and rows. + if ( entry.name == 'tableRow' ) { + table = entry.position.findAncestor( 'table' ); + } + + // Fix table on adding/removing table cells and rows. + if ( entry.name == 'tableCell' ) { + table = entry.position.findAncestor( 'table' ); + } + + if ( table && !analyzedTables.has( table ) ) { + // For each cell in the table... + for ( const item of new TableWalker( table ) ) { + // ...check its cell properties... + if ( shouldApplyDefaultCellProperties( item.cell ) ) { + // ...and if cell has no properties, apply the default one. + writer.setAttributes( cellProperties, item.cell ); + + wasFixed = true; + } + } + + analyzedTables.add( table ); + } + } + + return wasFixed; +} + +function shouldApplyDefaultCellProperties( tableCell ) { + return [ ...tableCell.getAttributeKeys() ].filter( attributeName => { + return attributeName !== 'colspan' && attributeName !== 'rowspan'; + } ).length === 0; +} diff --git a/packages/ckeditor5-table/src/converters/table-layout-post-fixer.js b/packages/ckeditor5-table/src/converters/table-layout-post-fixer.js index 19a63ecb543..7eb5fda0f52 100644 --- a/packages/ckeditor5-table/src/converters/table-layout-post-fixer.js +++ b/packages/ckeditor5-table/src/converters/table-layout-post-fixer.js @@ -211,20 +211,18 @@ import { createEmptyTableCell, updateNumericAttribute } from '../utils/common'; * * * - * @param {module:core/editor/editor~Editor} editor + * @param {module:engine/model/model~Model} model */ -export default function injectTableLayoutPostFixer( editor ) { - editor.model.document.registerPostFixer( writer => tableLayoutPostFixer( writer, editor ) ); +export default function injectTableLayoutPostFixer( model ) { + model.document.registerPostFixer( writer => tableLayoutPostFixer( writer, model ) ); } // The table layout post-fixer. // // @param {module:engine/model/writer~Writer} writer -// @param {module:core/editor/editor~Editor} editor -function tableLayoutPostFixer( writer, editor ) { - const model = editor.model; +// @param {module:engine/model/model~Model} model +function tableLayoutPostFixer( writer, model ) { const changes = model.document.differ.getChanges(); - const cellProperties = getDefaultCellProperties( editor ); let wasFixed = false; @@ -253,7 +251,7 @@ function tableLayoutPostFixer( writer, editor ) { // The wasFixed flag should be true if any of tables in batch was fixed - might be more then one. wasFixed = fixTableCellsRowspan( table, writer ) || wasFixed; // Step 2: fix table rows sizes. - wasFixed = fixTableRowsSizes( table, writer, cellProperties ) || wasFixed; + wasFixed = fixTableRowsSizes( table, writer ) || wasFixed; analyzedTables.add( table ); } @@ -289,9 +287,8 @@ function fixTableCellsRowspan( table, writer ) { // // @param {module:engine/model/element~Element} table // @param {module:engine/model/writer~Writer} writer -// @param {Object} cellProperties Default for created cells. // @returns {Boolean} Returns `true` if the table was fixed. -function fixTableRowsSizes( table, writer, cellProperties ) { +function fixTableRowsSizes( table, writer ) { let wasFixed = false; const rowsLengths = getRowsLengths( table ); @@ -331,7 +328,7 @@ function fixTableRowsSizes( table, writer, cellProperties ) { if ( columnsToInsert ) { for ( let i = 0; i < columnsToInsert; i++ ) { - createEmptyTableCell( writer, writer.createPositionAt( table.getChild( rowIndex ), 'end' ), cellProperties ); + createEmptyTableCell( writer, writer.createPositionAt( table.getChild( rowIndex ), 'end' ) ); } wasFixed = true; @@ -400,16 +397,3 @@ function isTableAttributeEntry( entry ) { return isAttributeType && ( key === 'headingRows' || key === 'colspan' || key === 'rowspan' ); } - -// Returns the default cell properties if the `TableCellPropertiesEditing` plugin is enabled. -// Otherwise, returns an empty object. -// -// @param {module:core/editor/editor~Editor} editor -// @returns {Object} -function getDefaultCellProperties( editor ) { - if ( editor.plugins.has( 'TableCellPropertiesEditing' ) ) { - return editor.config.get( 'table.tableCellProperties.defaultProperties' ); - } - - return {}; -} diff --git a/packages/ckeditor5-table/src/tablecellproperties.js b/packages/ckeditor5-table/src/tablecellproperties.js index 88e8521cc95..eca37ccc014 100644 --- a/packages/ckeditor5-table/src/tablecellproperties.js +++ b/packages/ckeditor5-table/src/tablecellproperties.js @@ -89,14 +89,6 @@ export default class TableCellProperties extends Plugin { * * `verticalAlignment` – sets the cell vertical alignment * * `width` – sets the cell width * - * The {@link module:table/tablecellproperties/tablecellpropertiesediting~TableCellPropertiesEditing} plugin defines the default cell - * properties as specified below: - * - * { - * "horizontalAlignment": "center", - * "verticalAlignment": "middle" - * } - * * **Note**: The configurations do not impact the data loaded into the editor, * i.e. they do not limit or filter the colors in the data. They are used only in the user interface * allowing users to pick colors in a more convenient way. diff --git a/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js b/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js index bb140c2f3b4..16674b6224d 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js +++ b/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js @@ -23,6 +23,7 @@ import TableCellBorderColorCommand from './commands/tablecellbordercolorcommand' import TableCellBorderWidthCommand from './commands/tablecellborderwidthcommand'; import TableWalker from '../tablewalker'; import TableUtils from '../tableutils'; +import injectTableCellDefaultPropertiesPostFixer from '../converters/table-cell-default-properties-post-fixer'; const VALIGN_VALUES_REG_EXP = /^(top|bottom)$/; @@ -71,10 +72,7 @@ export default class TableCellPropertiesEditing extends Plugin { const conversion = editor.conversion; const locale = editor.locale; - editor.config.define( 'table.tableCellProperties.defaultProperties', { - horizontalAlignment: 'center', - verticalAlignment: 'middle' - } ); + editor.config.define( 'table.tableCellProperties.defaultProperties', {} ); editor.data.addStyleProcessorRules( addBorderRules ); enableBorderProperties( schema, conversion ); @@ -103,6 +101,8 @@ export default class TableCellPropertiesEditing extends Plugin { editor.commands.add( 'tableCellVerticalAlignment', new TableCellVerticalAlignmentCommand( editor ) ); this._enableDefaultCellProperties(); + + injectTableCellDefaultPropertiesPostFixer( editor ); } /** diff --git a/packages/ckeditor5-table/src/tableediting.js b/packages/ckeditor5-table/src/tableediting.js index a648b0b41b2..e339be6b584 100644 --- a/packages/ckeditor5-table/src/tableediting.js +++ b/packages/ckeditor5-table/src/tableediting.js @@ -146,7 +146,7 @@ export default class TableEditing extends Plugin { editor.commands.add( 'selectTableColumn', new SelectColumnCommand( editor ) ); injectTableHeadingRowsRefreshPostFixer( model ); - injectTableLayoutPostFixer( editor ); + injectTableLayoutPostFixer( model ); injectTableCellRefreshPostFixer( model, editor.editing.mapper ); injectTableCellParagraphPostFixer( model ); } diff --git a/packages/ckeditor5-table/src/tableproperties.js b/packages/ckeditor5-table/src/tableproperties.js index b061f2056b8..1ded0939aa7 100644 --- a/packages/ckeditor5-table/src/tableproperties.js +++ b/packages/ckeditor5-table/src/tableproperties.js @@ -88,13 +88,6 @@ export default class TableProperties extends Plugin { * * `height` – sets the table height * * `width` – sets the table width * - * The {@link module:table/tableproperties/tablepropertiesediting~TablePropertiesEditing} plugin defines the default table - * properties as specified below: - * - * { - * "alignment": "center" - * } - * * **Note**: The configurations do not impact the data loaded into the editor, * i.e. they do not limit or filter the colors in the data. They are used only in the user interface * allowing users to pick colors in a more convenient way. diff --git a/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js b/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js index 27dd224057c..e0576cbf11d 100644 --- a/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js +++ b/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js @@ -70,9 +70,7 @@ export default class TablePropertiesEditing extends Plugin { const schema = editor.model.schema; const conversion = editor.conversion; - editor.config.define( 'table.tableProperties.defaultProperties', { - alignment: 'center' - } ); + editor.config.define( 'table.tableProperties.defaultProperties', {} ); editor.data.addStyleProcessorRules( addBorderRules ); enableBorderProperties( schema, conversion ); diff --git a/packages/ckeditor5-table/tests/converters/table-cell-default-properties-post-fixer.js b/packages/ckeditor5-table/tests/converters/table-cell-default-properties-post-fixer.js new file mode 100644 index 00000000000..ba54ed0e904 --- /dev/null +++ b/packages/ckeditor5-table/tests/converters/table-cell-default-properties-post-fixer.js @@ -0,0 +1,357 @@ +/** + * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; +import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor'; +import { getData as getModelData, parse, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model'; + +import TableEditing from '../../src/tableediting'; +import { modelTable } from './../_utils/utils'; +import UndoEditing from '@ckeditor/ckeditor5-undo/src/undoediting'; +import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils'; +import TableCellPropertiesEditing from '../../src/tablecellproperties/tablecellpropertiesediting'; + +describe( 'Table cell default properties post-fixer', () => { + let editor, model, root; + + const defaultProperties = { + borderStyle: 'solid', + borderWidth: '2px', + borderColor: '#f00', + horizontalAlignment: 'right', + verticalAlignment: 'bottom' + }; + + beforeEach( () => { + return VirtualTestEditor + .create( { + plugins: [ TableEditing, Paragraph, UndoEditing, TableCellPropertiesEditing ], + table: { + tableCellProperties: { + defaultProperties + } + } + } ) + .then( newEditor => { + editor = newEditor; + model = editor.model; + root = model.document.getRoot(); + } ); + } ); + + afterEach( () => { + editor.destroy(); + } ); + + describe( 'on insert table', () => { + it( 'should add missing columns to tableRows that are shorter then the longest table row', () => { + const parsed = parse( modelTable( [ + [ '00' ], + [ '10', '11', '12' ], + [ '20', '21' ] + ], { cellProperties: defaultProperties } ), model.schema ); + + model.change( writer => { + writer.remove( writer.createRangeIn( root ) ); + writer.insert( parsed, root ); + } ); + + assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [ + [ '00', '', '' ], + [ '10', '11', '12' ], + [ '20', '21', '' ] + ], { cellProperties: defaultProperties } ) ); + } ); + + it( 'should add missing columns to tableRows that are shorter then the longest table row (complex 2)', () => { + const parsed = parse( modelTable( [ + [ { colspan: 6, contents: '00' } ], + [ { rowspan: 2, contents: '10' }, '11', { colspan: 3, contents: '12' } ], + [ '21', '22' ] + ], { cellProperties: defaultProperties } ), model.schema ); + + model.change( writer => { + writer.remove( writer.createRangeIn( root ) ); + writer.insert( parsed, root ); + } ); + + assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [ + [ { colspan: 6, contents: '00' } ], + [ { rowspan: 2, contents: '10' }, '11', { colspan: 3, contents: '12' }, '' ], + [ '21', '22', '', '', '' ] + ], { cellProperties: defaultProperties } ) ); + } ); + } ); + + describe( 'on collaboration', () => { + it( 'should add missing cells to columns (remove column vs insert row)', () => { + _testExternal( + modelTable( [ + [ '00[]', '01' ], + [ '10', '11' ] + ], { cellProperties: defaultProperties } ), + writer => _removeColumn( writer, 1, [ 0, 1 ] ), + writer => _insertRow( writer, 1, [ 'a', 'b' ] ), + // Table should have added empty cells. + modelTable( [ + [ '00', '' ], + [ 'a', 'b' ], + [ '10', '' ] + ], { cellProperties: defaultProperties } ), + // Table will have empty column after undo. + modelTable( [ + [ '00', '01', '' ], + [ 'a', 'b', '' ], + [ '10', '11', '' ] + ], { cellProperties: defaultProperties } ) ); + } ); + + it( 'should add missing cells to columns (insert row vs remove column)', () => { + _testExternal( + modelTable( [ + [ '00[]', '01' ], + [ '10', '11' ] + ], { cellProperties: defaultProperties } ), + writer => _insertRow( writer, 1, [ 'a', 'b' ] ), + writer => _removeColumn( writer, 1, [ 0, 2 ] ), + // There should be empty cells added. + modelTable( [ + [ '00', '' ], + [ 'a', 'b' ], + [ '10', '' ] + ], { cellProperties: defaultProperties } ), + // Table will have empty column after undo. + modelTable( [ + [ '00', '' ], + [ '10', '' ] + ], { cellProperties: defaultProperties } ) ); + } ); + + it( 'should add empty cell to an added row (insert row vs insert column)', () => { + _testExternal( + modelTable( [ + [ '00[]', '01' ], + [ '10', '11' ] + ], { cellProperties: defaultProperties } ), + writer => _insertRow( writer, 1, [ 'a', 'b' ] ), + writer => _insertColumn( writer, 1, [ 0, 2 ] ), + // There should be empty cells added. + modelTable( [ + [ '00', '', '01' ], + [ 'a', 'b', '' ], + [ '10', '', '11' ] + ], { cellProperties: defaultProperties } ), + // Table will have empty column after undo. + modelTable( [ + [ '00', '', '01' ], + [ '10', '', '11' ] + ], { cellProperties: defaultProperties } ) ); + } ); + + it( 'should add empty cell to an added row (insert column vs insert row)', () => { + _testExternal( + modelTable( [ + [ '00[]', '01' ], + [ '10', '11' ] + ], { cellProperties: defaultProperties } ), + writer => _insertColumn( writer, 1, [ 0, 1 ] ), + writer => _insertRow( writer, 1, [ 'a', 'b' ] ), + // There should be empty cells added. + modelTable( [ + [ '00', '', '01' ], + [ 'a', 'b', '' ], + [ '10', '', '11' ] + ], { cellProperties: defaultProperties } ), + // Table will have empty column after undo. + modelTable( [ + [ '00', '01', '' ], + [ 'a', 'b', '' ], + [ '10', '11', '' ] + ], { cellProperties: defaultProperties } ) ); + } ); + + it( 'should add empty cell when inserting column over a colspanned cell (insert column vs insert column)', () => { + _testExternal( + modelTable( [ + [ { colspan: 3, contents: '00' } ], + [ '10', '11', '12' ] + ], { cellProperties: defaultProperties } ), + writer => { + _setAttribute( writer, 'colspan', 4, [ 0, 0, 0 ] ); + _insertColumn( writer, 2, [ 1 ] ); + }, + writer => { + _setAttribute( writer, 'colspan', 4, [ 0, 0, 0 ] ); + _insertColumn( writer, 1, [ 1 ] ); + }, + // There should be empty cells added. + modelTable( [ + [ { colspan: 4, contents: '00' }, '' ], + [ '10', '', '11', '', '12' ] + ], { cellProperties: defaultProperties } ), + // Table will have empty column after undo. + modelTable( [ + [ { colspan: 3, contents: '00' }, '' ], + [ '10', '', '11', '12' ] + ], { cellProperties: defaultProperties } ) ); + } ); + + it( 'should add empty cell when inserting column over a colspanned cell (insert column vs insert column) - inverted', () => { + _testExternal( + modelTable( [ + [ { colspan: 3, contents: '00' } ], + [ '10', '11', '12' ] + ], { cellProperties: defaultProperties } ), + writer => { + _setAttribute( writer, 'colspan', 4, [ 0, 0, 0 ] ); + _insertColumn( writer, 1, [ 1 ] ); + }, + writer => { + _setAttribute( writer, 'colspan', 4, [ 0, 0, 0 ] ); + _insertColumn( writer, 3, [ 1 ] ); + }, + // There should be empty cells added. + modelTable( [ + [ { colspan: 4, contents: '00' }, '' ], + [ '10', '', '11', '', '12' ] + ], { cellProperties: defaultProperties } ), + // Table will have empty column after undo. + modelTable( [ + [ { colspan: 3, contents: '00' }, '' ], + [ '10', '11', '', '12' ] + ], { cellProperties: defaultProperties } ) ); + } ); + + it( 'should insert table cell on undo (change table headers on row with rowspanned cell vs remove row)', () => { + _testExternal( + modelTable( [ + [ '11', { rowspan: 2, contents: '12' }, '13' ], + [ '21', '23' ], + [ '31', '32', '33' ] + ], { cellProperties: defaultProperties } ), + writer => { + _setAttribute( writer, 'headingRows', 1, [ 0 ] ); + _removeAttribute( writer, 'rowspan', [ 0, 0, 1 ] ); + _insertCell( writer, 1, 1 ); + }, + writer => { + _removeRow( writer, 1 ); + }, + modelTable( [ + [ '11', '12', '13' ], + [ '31', '32', '33' ] + ], { headingRows: 1, cellProperties: defaultProperties } ), + modelTable( [ + [ '11', { rowspan: 2, contents: '12' }, '13', '' ], + [ '31', '32', '33' ] + ], { cellProperties: defaultProperties } ) ); + } ); + + it( 'should insert empty table cell (remove row vs change table headers on row with rowspanned cell)', () => { + _testExternal( + modelTable( [ + [ '11', { rowspan: 2, contents: '12' }, '13' ], + [ '21', '23' ], + [ '31', '32', '33' ] + ], { cellProperties: defaultProperties } ), + writer => { + _removeRow( writer, 1 ); + }, + writer => { + _setAttribute( writer, 'headingRows', 1, [ 0 ] ); + _removeAttribute( writer, 'rowspan', [ 0, 0, 1 ] ); + }, + modelTable( [ + [ '11', '12', '13', '' ], + [ '31', '32', '33', '' ] + ], { headingRows: 1, cellProperties: defaultProperties } ), + modelTable( [ + [ '11', '12', '13', '' ], + [ '21', '23', '', '' ], + [ '31', '32', '33', '' ] + ], { headingRows: 1, cellProperties: defaultProperties } ) ); + } ); + + function _testExternal( initialData, localCallback, externalCallback, modelAfter, modelAfterUndo ) { + setModelData( model, initialData ); + + model.change( localCallback ); + + model.enqueueChange( 'transparent', externalCallback ); + + assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelAfter ); + + editor.execute( 'undo' ); + + assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelAfterUndo ); + + editor.execute( 'redo' ); + + assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelAfter ); + } + + function _removeColumn( writer, columnIndex, rows ) { + const table = root.getChild( 0 ); + + for ( const index of rows ) { + const tableRow = table.getChild( index ); + const tableCell = tableRow.getChild( columnIndex ); + + writer.remove( tableCell ); + } + } + + function _removeRow( writer, rowIndex ) { + const table = root.getChild( 0 ); + const tableRow = table.getChild( rowIndex ); + + writer.remove( tableRow ); + } + + function _insertRow( writer, rowIndex, rowData ) { + const table = root.getChild( 0 ); + + const parsedTable = parse( + modelTable( [ rowData ] ), + model.schema + ); + + writer.insert( parsedTable.getChild( 0 ), table, rowIndex ); + } + + function _insertCell( writer, rowIndex, index ) { + const table = root.getChild( 0 ); + const tableRow = table.getChild( rowIndex ); + + const tableCell = writer.createElement( 'tableCell' ); + writer.insert( tableCell, tableRow, index ); + writer.insertElement( 'paragraph', tableCell ); + } + + function _setAttribute( writer, attributeKey, attributeValue, path ) { + const node = root.getNodeByPath( path ); + + writer.setAttribute( attributeKey, attributeValue, node ); + } + + function _removeAttribute( writer, attributeKey, path ) { + const node = root.getNodeByPath( path ); + + writer.removeAttribute( attributeKey, node ); + } + + function _insertColumn( writer, columnIndex, rows ) { + const table = root.getChild( 0 ); + + for ( const index of rows ) { + const tableRow = table.getChild( index ); + + const tableCell = writer.createElement( 'tableCell' ); + writer.insert( tableCell, tableRow, columnIndex ); + writer.insertElement( 'paragraph', tableCell ); + } + } + } ); +} ); diff --git a/packages/ckeditor5-table/tests/converters/table-layout-post-fixer.js b/packages/ckeditor5-table/tests/converters/table-layout-post-fixer.js index 4f19df7a8f9..220cb933eb8 100644 --- a/packages/ckeditor5-table/tests/converters/table-layout-post-fixer.js +++ b/packages/ckeditor5-table/tests/converters/table-layout-post-fixer.js @@ -11,7 +11,6 @@ import TableEditing from '../../src/tableediting'; import { modelTable } from './../_utils/utils'; import UndoEditing from '@ckeditor/ckeditor5-undo/src/undoediting'; import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils'; -import TableCellPropertiesEditing from '../../src/tablecellproperties/tablecellpropertiesediting'; describe( 'Table layout post-fixer', () => { let editor, model, root; @@ -199,77 +198,6 @@ describe( 'Table layout post-fixer', () => { expect( getModelData( model, { withoutSelection: true } ) ).to.equal( '' ); } ); - - describe( 'integration with TableCellPropertiesEditing', () => { - let editor, model, root; - - const defaultProperties = { - borderStyle: 'solid', - borderWidth: '2px', - borderColor: '#f00', - horizontalAlignment: 'right', - verticalAlignment: 'bottom' - }; - - beforeEach( () => { - return VirtualTestEditor - .create( { - plugins: [ TableEditing, Paragraph, UndoEditing, TableCellPropertiesEditing ], - table: { - tableCellProperties: { - defaultProperties - } - } - } ) - .then( newEditor => { - editor = newEditor; - model = editor.model; - root = model.document.getRoot(); - } ); - } ); - - afterEach( () => { - editor.destroy(); - } ); - - it( 'should add missing columns to tableRows that are shorter then the longest table row', () => { - const parsed = parse( modelTable( [ - [ '00' ], - [ '10', '11', '12' ], - [ '20', '21' ] - ], { cellProperties: defaultProperties } ), model.schema ); - - model.change( writer => { - writer.remove( writer.createRangeIn( root ) ); - writer.insert( parsed, root ); - } ); - - assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [ - [ '00', '', '' ], - [ '10', '11', '12' ], - [ '20', '21', '' ] - ], { cellProperties: defaultProperties } ) ); - } ); - - it( 'should add missing columns to tableRows that are shorter then the longest table row (complex 2)', () => { - const parsed = parse( modelTable( [ - [ { colspan: 6, contents: '00' } ], - [ { rowspan: 2, contents: '10' }, '11', { colspan: 3, contents: '12' } ], - [ '21', '22' ] - ], { cellProperties: defaultProperties } ), model.schema ); - - model.change( writer => { - writer.remove( writer.createRangeIn( root ) ); - writer.insert( parsed, root ); - } ); - - assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [ - [ { colspan: 6, contents: '00' } ], - [ { rowspan: 2, contents: '10' }, '11', { colspan: 3, contents: '12' }, '' ], - [ '21', '22', '', '', '' ] - ], { cellProperties: defaultProperties } ) ); - } ); - } ); } ); describe( 'on collaboration', () => { diff --git a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js index 9ae21979328..c4a589528c7 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js @@ -93,10 +93,7 @@ describe( 'table cell properties', () => { } ); it( 'should define the default properties for a table', () => { - expect( tableCellProperties.defaultProperties ).to.deep.equal( { - horizontalAlignment: 'center', - verticalAlignment: 'middle' - } ); + expect( tableCellProperties.defaultProperties ).to.deep.equal( {} ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js index 0a5d6a93803..b95be8a5d0d 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js @@ -75,10 +75,7 @@ describe( 'table cell properties', () => { expect( editor.config.get( 'table.tableCellProperties' ) ).to.deep.equal( { borderColors: defaultColors, backgroundColors: defaultColors, - defaultProperties: { - horizontalAlignment: 'center', - verticalAlignment: 'middle' - } + defaultProperties: {} } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js b/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js index 8d4768b5200..445e65c6ffd 100644 --- a/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js +++ b/packages/ckeditor5-table/tests/tableproperties/tablepropertiesediting.js @@ -87,9 +87,7 @@ describe( 'table properties', () => { } ); it( 'should define the default properties for a table', () => { - expect( tableProperties.defaultProperties ).to.deep.equal( { - alignment: 'center' - } ); + expect( tableProperties.defaultProperties ).to.deep.equal( {} ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tableproperties/tablepropertiesui.js b/packages/ckeditor5-table/tests/tableproperties/tablepropertiesui.js index 2fb3b5742de..57e88ac03ed 100644 --- a/packages/ckeditor5-table/tests/tableproperties/tablepropertiesui.js +++ b/packages/ckeditor5-table/tests/tableproperties/tablepropertiesui.js @@ -74,9 +74,7 @@ describe( 'table properties', () => { expect( editor.config.get( 'table.tableProperties' ) ).to.deep.equal( { borderColors: defaultColors, backgroundColors: defaultColors, - defaultProperties: { - alignment: 'center' - } + defaultProperties: {} } ); } ); } ); From 6ae94d8cd84a27a648efdaa87d4c937ec09341e2 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Fri, 9 Apr 2021 17:27:46 +0200 Subject: [PATCH 23/24] Final improvements. --- .../src/converters/downcast.js | 2 +- ...able-cell-default-properties-post-fixer.js | 28 +++++++++++++++---- .../src/converters/table-layout-post-fixer.js | 2 +- .../src/tablecellproperties.js | 1 + 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/packages/ckeditor5-table/src/converters/downcast.js b/packages/ckeditor5-table/src/converters/downcast.js index 540b3ecf6e6..e35e45caa7a 100644 --- a/packages/ckeditor5-table/src/converters/downcast.js +++ b/packages/ckeditor5-table/src/converters/downcast.js @@ -7,7 +7,7 @@ * @module table/converters/downcast */ -import TableWalker from './../tablewalker'; +import TableWalker from '../tablewalker'; import { setHighlightHandling, toWidget, toWidgetEditable } from 'ckeditor5/src/widget'; import { toArray } from 'ckeditor5/src/utils'; diff --git a/packages/ckeditor5-table/src/converters/table-cell-default-properties-post-fixer.js b/packages/ckeditor5-table/src/converters/table-cell-default-properties-post-fixer.js index c22a5b50372..888a22311ed 100644 --- a/packages/ckeditor5-table/src/converters/table-cell-default-properties-post-fixer.js +++ b/packages/ckeditor5-table/src/converters/table-cell-default-properties-post-fixer.js @@ -7,7 +7,19 @@ * @module table/converters/table-layout-post-fixer */ -import TableWalker from './../tablewalker'; +import TableWalker from '../tablewalker'; + +const TABLE_CELL_PROPERTIES = [ + 'borderStyle', + 'borderColor', + 'borderWidth', + 'backgroundColor', + 'padding', + 'horizontalAlignment', + 'verticalAlignment', + 'width', + 'height' +]; /** * Injects a table cell default properties post-fixer into the model. @@ -61,7 +73,7 @@ function tableCellDefaultPropertiesPostFixer( writer, editor ) { for ( const item of new TableWalker( table ) ) { // ...check its cell properties... if ( shouldApplyDefaultCellProperties( item.cell ) ) { - // ...and if cell has no properties, apply the default one. + // ...and if the cell has no properties, apply the default. writer.setAttributes( cellProperties, item.cell ); wasFixed = true; @@ -75,8 +87,14 @@ function tableCellDefaultPropertiesPostFixer( writer, editor ) { return wasFixed; } +// Checks whether the default properties should be applied for the specified cell. +// +// The default properties will be applied only if the cell does not contain any "visual" properties. +// +// @param {module:engine/model/element~Element} tableCell +// @returns {Boolean} function shouldApplyDefaultCellProperties( tableCell ) { - return [ ...tableCell.getAttributeKeys() ].filter( attributeName => { - return attributeName !== 'colspan' && attributeName !== 'rowspan'; - } ).length === 0; + const attrs = [ ...tableCell.getAttributeKeys() ]; + + return attrs.some( attributeName => TABLE_CELL_PROPERTIES.includes( attributeName ) ) === false; } diff --git a/packages/ckeditor5-table/src/converters/table-layout-post-fixer.js b/packages/ckeditor5-table/src/converters/table-layout-post-fixer.js index 7eb5fda0f52..5e62ed7606e 100644 --- a/packages/ckeditor5-table/src/converters/table-layout-post-fixer.js +++ b/packages/ckeditor5-table/src/converters/table-layout-post-fixer.js @@ -7,7 +7,7 @@ * @module table/converters/table-layout-post-fixer */ -import TableWalker from './../tablewalker'; +import TableWalker from '../tablewalker'; import { createEmptyTableCell, updateNumericAttribute } from '../utils/common'; /** diff --git a/packages/ckeditor5-table/src/tablecellproperties.js b/packages/ckeditor5-table/src/tablecellproperties.js index eca37ccc014..9de6f39f0c5 100644 --- a/packages/ckeditor5-table/src/tablecellproperties.js +++ b/packages/ckeditor5-table/src/tablecellproperties.js @@ -86,6 +86,7 @@ export default class TableCellProperties extends Plugin { * * `borderWidth` – sets the border width * * `height` – sets the cell height * * `horizontalAlignment` – sets the cell horizontal alignment + * * `padding` – sets the cell padding * * `verticalAlignment` – sets the cell vertical alignment * * `width` – sets the cell width * From 977b69e279ca0e65a4a064efdbb02b2d2b145e19 Mon Sep 17 00:00:00 2001 From: Kuba Niegowski Date: Mon, 12 Apr 2021 17:38:50 +0200 Subject: [PATCH 24/24] Simplified post-fixer. --- ...able-cell-default-properties-post-fixer.js | 40 +++---- ...able-cell-default-properties-post-fixer.js | 112 ------------------ 2 files changed, 18 insertions(+), 134 deletions(-) diff --git a/packages/ckeditor5-table/src/converters/table-cell-default-properties-post-fixer.js b/packages/ckeditor5-table/src/converters/table-cell-default-properties-post-fixer.js index 888a22311ed..0c52fe06d7d 100644 --- a/packages/ckeditor5-table/src/converters/table-cell-default-properties-post-fixer.js +++ b/packages/ckeditor5-table/src/converters/table-cell-default-properties-post-fixer.js @@ -7,8 +7,6 @@ * @module table/converters/table-layout-post-fixer */ -import TableWalker from '../tablewalker'; - const TABLE_CELL_PROPERTIES = [ 'borderStyle', 'borderColor', @@ -48,39 +46,37 @@ function tableCellDefaultPropertiesPostFixer( writer, editor ) { let wasFixed = false; - // Do not analyze the same table more then once - may happen for multiple changes in the same table. - const analyzedTables = new Set(); - for ( const entry of changes ) { - let table; - - if ( entry.name == 'table' && entry.type == 'insert' ) { - table = entry.position.nodeAfter; + if ( entry.type != 'insert' ) { + continue; } // Fix table on adding/removing table cells and rows. if ( entry.name == 'tableRow' ) { - table = entry.position.findAncestor( 'table' ); - } + const tableRow = entry.position.nodeAfter; - // Fix table on adding/removing table cells and rows. - if ( entry.name == 'tableCell' ) { - table = entry.position.findAncestor( 'table' ); - } - - if ( table && !analyzedTables.has( table ) ) { - // For each cell in the table... - for ( const item of new TableWalker( table ) ) { + // For each cell in the table row... + for ( const tableCell of tableRow.getChildren() ) { // ...check its cell properties... - if ( shouldApplyDefaultCellProperties( item.cell ) ) { + if ( shouldApplyDefaultCellProperties( tableCell ) ) { // ...and if the cell has no properties, apply the default. - writer.setAttributes( cellProperties, item.cell ); + writer.setAttributes( cellProperties, tableCell ); wasFixed = true; } } + } + + // Fix table cell on adding/removing table cells and rows. + if ( entry.name == 'tableCell' ) { + const tableCell = entry.position.nodeAfter; + + if ( shouldApplyDefaultCellProperties( tableCell ) ) { + // ...and if the cell has no properties, apply the default. + writer.setAttributes( cellProperties, tableCell ); - analyzedTables.add( table ); + wasFixed = true; + } } } diff --git a/packages/ckeditor5-table/tests/converters/table-cell-default-properties-post-fixer.js b/packages/ckeditor5-table/tests/converters/table-cell-default-properties-post-fixer.js index ba54ed0e904..e049e1c6e71 100644 --- a/packages/ckeditor5-table/tests/converters/table-cell-default-properties-post-fixer.js +++ b/packages/ckeditor5-table/tests/converters/table-cell-default-properties-post-fixer.js @@ -45,46 +45,6 @@ describe( 'Table cell default properties post-fixer', () => { editor.destroy(); } ); - describe( 'on insert table', () => { - it( 'should add missing columns to tableRows that are shorter then the longest table row', () => { - const parsed = parse( modelTable( [ - [ '00' ], - [ '10', '11', '12' ], - [ '20', '21' ] - ], { cellProperties: defaultProperties } ), model.schema ); - - model.change( writer => { - writer.remove( writer.createRangeIn( root ) ); - writer.insert( parsed, root ); - } ); - - assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [ - [ '00', '', '' ], - [ '10', '11', '12' ], - [ '20', '21', '' ] - ], { cellProperties: defaultProperties } ) ); - } ); - - it( 'should add missing columns to tableRows that are shorter then the longest table row (complex 2)', () => { - const parsed = parse( modelTable( [ - [ { colspan: 6, contents: '00' } ], - [ { rowspan: 2, contents: '10' }, '11', { colspan: 3, contents: '12' } ], - [ '21', '22' ] - ], { cellProperties: defaultProperties } ), model.schema ); - - model.change( writer => { - writer.remove( writer.createRangeIn( root ) ); - writer.insert( parsed, root ); - } ); - - assertEqualMarkup( getModelData( model, { withoutSelection: true } ), modelTable( [ - [ { colspan: 6, contents: '00' } ], - [ { rowspan: 2, contents: '10' }, '11', { colspan: 3, contents: '12' }, '' ], - [ '21', '22', '', '', '' ] - ], { cellProperties: defaultProperties } ) ); - } ); - } ); - describe( 'on collaboration', () => { it( 'should add missing cells to columns (remove column vs insert row)', () => { _testExternal( @@ -224,56 +184,6 @@ describe( 'Table cell default properties post-fixer', () => { ], { cellProperties: defaultProperties } ) ); } ); - it( 'should insert table cell on undo (change table headers on row with rowspanned cell vs remove row)', () => { - _testExternal( - modelTable( [ - [ '11', { rowspan: 2, contents: '12' }, '13' ], - [ '21', '23' ], - [ '31', '32', '33' ] - ], { cellProperties: defaultProperties } ), - writer => { - _setAttribute( writer, 'headingRows', 1, [ 0 ] ); - _removeAttribute( writer, 'rowspan', [ 0, 0, 1 ] ); - _insertCell( writer, 1, 1 ); - }, - writer => { - _removeRow( writer, 1 ); - }, - modelTable( [ - [ '11', '12', '13' ], - [ '31', '32', '33' ] - ], { headingRows: 1, cellProperties: defaultProperties } ), - modelTable( [ - [ '11', { rowspan: 2, contents: '12' }, '13', '' ], - [ '31', '32', '33' ] - ], { cellProperties: defaultProperties } ) ); - } ); - - it( 'should insert empty table cell (remove row vs change table headers on row with rowspanned cell)', () => { - _testExternal( - modelTable( [ - [ '11', { rowspan: 2, contents: '12' }, '13' ], - [ '21', '23' ], - [ '31', '32', '33' ] - ], { cellProperties: defaultProperties } ), - writer => { - _removeRow( writer, 1 ); - }, - writer => { - _setAttribute( writer, 'headingRows', 1, [ 0 ] ); - _removeAttribute( writer, 'rowspan', [ 0, 0, 1 ] ); - }, - modelTable( [ - [ '11', '12', '13', '' ], - [ '31', '32', '33', '' ] - ], { headingRows: 1, cellProperties: defaultProperties } ), - modelTable( [ - [ '11', '12', '13', '' ], - [ '21', '23', '', '' ], - [ '31', '32', '33', '' ] - ], { headingRows: 1, cellProperties: defaultProperties } ) ); - } ); - function _testExternal( initialData, localCallback, externalCallback, modelAfter, modelAfterUndo ) { setModelData( model, initialData ); @@ -303,13 +213,6 @@ describe( 'Table cell default properties post-fixer', () => { } } - function _removeRow( writer, rowIndex ) { - const table = root.getChild( 0 ); - const tableRow = table.getChild( rowIndex ); - - writer.remove( tableRow ); - } - function _insertRow( writer, rowIndex, rowData ) { const table = root.getChild( 0 ); @@ -321,27 +224,12 @@ describe( 'Table cell default properties post-fixer', () => { writer.insert( parsedTable.getChild( 0 ), table, rowIndex ); } - function _insertCell( writer, rowIndex, index ) { - const table = root.getChild( 0 ); - const tableRow = table.getChild( rowIndex ); - - const tableCell = writer.createElement( 'tableCell' ); - writer.insert( tableCell, tableRow, index ); - writer.insertElement( 'paragraph', tableCell ); - } - function _setAttribute( writer, attributeKey, attributeValue, path ) { const node = root.getNodeByPath( path ); writer.setAttribute( attributeKey, attributeValue, node ); } - function _removeAttribute( writer, attributeKey, path ) { - const node = root.getNodeByPath( path ); - - writer.removeAttribute( attributeKey, node ); - } - function _insertColumn( writer, columnIndex, rows ) { const table = root.getChild( 0 );