diff --git a/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.html b/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.html index 9e1d301d537..daf3d9bf4ce 100644 --- a/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.html +++ b/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.html @@ -1,15 +1,21 @@
diff --git a/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.js b/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.js index 3e6a4799131..d5626194576 100644 --- a/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.js +++ b/packages/ckeditor5-table/docs/_snippets/features/table-default-properties.js @@ -22,6 +22,13 @@ ClassicEditor width: '500px', height: '250px' } + }, + tableCellProperties: { + defaultProperties: { + horizontalAlignment: 'center', + verticalAlignment: 'bottom', + padding: '10px' + } } }, image: { diff --git a/packages/ckeditor5-table/docs/features/table.md b/packages/ckeditor5-table/docs/features/table.md index 9dbff9cb198..ee217926f99 100644 --- a/packages/ckeditor5-table/docs/features/table.md +++ b/packages/ckeditor5-table/docs/features/table.md @@ -221,11 +221,11 @@ ClassicEditor .catch( ... ); ``` -### Default table styles +### Default table and table cell styles The table styles feature allows for configuring the default look of the tables in the editor. The configuration object should be synchronized with the {@link builds/guides/integration/content-styles editor content styles}. -The **“Table properties”** button in the toolbar will show the table properties applied to the table. +The **“Table properties”**, and **“Table cell properties”** buttons in the toolbar will show the table and table cell properties applied to the table or table cells. The stylesheet for the editor displayed below looks as follows: @@ -241,9 +241,18 @@ The stylesheet for the editor displayed below looks as follows: border-color: 'hsl(90, 75%, 60%)'; border-width: 3px; } + +.ck-content .table table td { + text-align: center; + vertical-align: bottom; + padding: 10px +} ``` -The same values must be passed to the editor configuration as the {@link module:table/tableproperties~TablePropertiesOptions `table.tableProperties.defaultProperties`} object: +The same values must be passed to the editor configuration as: + +* the {@link module:table/tableproperties~TablePropertiesOptions `table.tableProperties.defaultProperties`} object for the table properties, +* the {@link module:table/tablecellproperties~TableCellPropertiesOptions `table.tableCellProperties.defaultProperties`} object for the table cell properties. ```js const tableConfig = { @@ -257,20 +266,32 @@ const tableConfig = { alignment: 'right', width: '500px', height: '250px' - } + }, + // The default styles for table cells in the editor. They should be synchronized with the content styles. + tableCellProperties: { + defaultProperties: { + horizontalAlignment: 'center', + verticalAlignment: 'bottom', + padding: '10px' + } + } } } }; ``` -The table element should be aligned to the `right` side by default. Its size should be `500x250px`. Border style should be `dashed`, `3px` of its width, and the color specified as `“Light green”`. The same will be applied for new tables if they will be inserted into the editor +The table element should be aligned to the `right` side by default. Its size should be `500x250px`. Border style should be `dashed`, `3px` of its width, and the color specified as `“Light green”`. + +The content should be away about `10px` from the cell's edges (`padding`), vertically aligned to `bottom` and horizontally to `center`. + +The same will be applied for new tables and cells if they will be inserted into the editor. {@snippet features/table-default-properties} -Read more about {@link module:table/tableproperties~TablePropertiesOptions all supported styles} for the table default properties feature. +Read more about all supported properties for the {@link module:table/tableproperties~TablePropertiesOptions table}, and {@link module:table/tablecellproperties~TableCellPropertiesOptions table cells} features. - The default table styles **do** impact the {@link builds/guides/integration/basic-api#setting-the-editor-data data loaded into the editor}. Default properties will not be kept in the editor model. + The default table, and table cell styles **do** impact the {@link builds/guides/integration/basic-api#setting-the-editor-data data loaded into the editor}. Default properties will not be kept in the editor model. ## Block vs inline content in table cells diff --git a/packages/ckeditor5-table/src/converters/tableproperties.js b/packages/ckeditor5-table/src/converters/tableproperties.js index 4c72cc2b801..57f6c3215db 100644 --- a/packages/ckeditor5-table/src/converters/tableproperties.js +++ b/packages/ckeditor5-table/src/converters/tableproperties.js @@ -47,12 +47,12 @@ export function upcastStyleToAttribute( conversion, options ) { * * @param {module:engine/conversion/conversion~Conversion} conversion * @param {String} viewElementName - * @param {Object} [defaultBorder={}] The default border values. + * @param {Object} defaultBorder The default border values. * @param {String} defaultBorder.color The default `borderColor` value. * @param {String} defaultBorder.style The default `borderStyle` value. * @param {String} defaultBorder.width The default `borderWidth` value. */ -export function upcastBorderStyles( conversion, viewElementName, defaultBorder = {} ) { +export function upcastBorderStyles( conversion, viewElementName, defaultBorder ) { conversion.for( 'upcast' ).add( dispatcher => dispatcher.on( 'element:' + viewElementName, ( evt, data, conversionApi ) => { // If the element was not converted by element-to-element converter, // we should not try to convert the style. See #8393. diff --git a/packages/ckeditor5-table/src/tablecellproperties.js b/packages/ckeditor5-table/src/tablecellproperties.js index daffcb7d022..053e09a23a8 100644 --- a/packages/ckeditor5-table/src/tablecellproperties.js +++ b/packages/ckeditor5-table/src/tablecellproperties.js @@ -64,9 +64,24 @@ export default class TableCellProperties extends Plugin { * } * }; * - * **Note**: The configurations do not impact the data loaded into the editor, + * * The default styles for table cells (`tableCellProperties.defaultProperties`): + * + * const tableConfig = { + * tableCellProperties: { + * defaultProperties: { + * horizontalAlignment: 'right', + * verticalAlignment: 'bottom', + * padding: '5px' + * } + * } + * } + * + * {@link module:table/tableproperties~TablePropertiesOptions Read more about the supported properties.} + * + * **Note**: The `borderColors` and `backgroundColors` options 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. + * allowing users to pick colors in a more convenient way. The `defaultProperties` option does impact the data. + * Default values will not be kept in the editor model. * * The default color palettes for the cell background and the cell border are the same * ({@link module:table/utils/ui/table-properties~defaultColors check out their content}). @@ -78,3 +93,28 @@ export default class TableCellProperties extends Plugin { * * @member {Object} module:table/table~TableConfig#tableCellProperties */ + +/** + * The configuration of the table cell default properties feature. + * + * @typedef {Object} module:table/tablecellproperties~TableCellPropertiesOptions + * + * @property {String} width The default `width` of the table cell. + * + * @property {String} height The default `height` of the table cell. + * + * @property {String} padding The default `padding` of the table cell. + * + * @property {String} backgroundColor The default `background-color` of the table cell. + * + * @property {String} borderColor The default `border-color` of the table cell. + * + * @property {String} borderWidth The default `border-width` of the table cell. + * + * @property {String} [borderStyle='none'] The default `border-style` of the table cell. + * + * @property {String} [horizontalAlignment='center'] The default `horizontalAlignment` of the table cell. + * + * @property {String} [verticalAlignment='middle'] The default `verticalAlignment` of the table cell. + */ + diff --git a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.js b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.js index b06b08d0c13..bdf0e258281 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.js +++ b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.js @@ -28,8 +28,9 @@ export default class TableCellBackgroundColorCommand extends TableCellPropertyCo * Creates a new `TableCellBackgroundColorCommand` instance. * * @param {module:core/editor/editor~Editor} editor An editor in which this command will be used. + * @param {String} defaultValue The default value of the attribute. */ - constructor( editor ) { - super( editor, 'backgroundColor' ); + constructor( editor, defaultValue ) { + super( editor, 'backgroundColor', defaultValue ); } } diff --git a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellbordercolorcommand.js b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellbordercolorcommand.js index 6e4af95a0bd..a40e00bc58b 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellbordercolorcommand.js +++ b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellbordercolorcommand.js @@ -29,9 +29,10 @@ export default class TableCellBorderColorCommand extends TableCellPropertyComman * Creates a new `TableCellBorderColorCommand` instance. * * @param {module:core/editor/editor~Editor} editor An editor in which this command will be used. + * @param {String} defaultValue The default value of the attribute. */ - constructor( editor ) { - super( editor, 'borderColor' ); + constructor( editor, defaultValue ) { + super( editor, 'borderColor', defaultValue ); } /** @@ -42,6 +43,12 @@ export default class TableCellBorderColorCommand extends TableCellPropertyComman return; } - return getSingleValue( tableCell.getAttribute( this.attributeName ) ); + const value = getSingleValue( tableCell.getAttribute( this.attributeName ) ); + + if ( value === this._defaultValue ) { + return; + } + + return value; } } diff --git a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellborderstylecommand.js b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellborderstylecommand.js index 3960441da07..9093a2dd761 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellborderstylecommand.js +++ b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellborderstylecommand.js @@ -29,9 +29,10 @@ export default class TableCellBorderStyleCommand extends TableCellPropertyComman * Creates a new `TableCellBorderStyleCommand` instance. * * @param {module:core/editor/editor~Editor} editor An editor in which this command will be used. + * @param {String} defaultValue The default value of the attribute. */ - constructor( editor ) { - super( editor, 'borderStyle' ); + constructor( editor, defaultValue ) { + super( editor, 'borderStyle', defaultValue ); } /** @@ -42,6 +43,12 @@ export default class TableCellBorderStyleCommand extends TableCellPropertyComman return; } - return getSingleValue( tableCell.getAttribute( this.attributeName ) ); + const value = getSingleValue( tableCell.getAttribute( this.attributeName ) ); + + if ( value === this._defaultValue ) { + return; + } + + return value; } } diff --git a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellborderwidthcommand.js b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellborderwidthcommand.js index 0d505d57846..a4053fc3a59 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellborderwidthcommand.js +++ b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellborderwidthcommand.js @@ -37,9 +37,10 @@ export default class TableCellBorderWidthCommand extends TableCellPropertyComman * Creates a new `TableCellBorderWidthCommand` instance. * * @param {module:core/editor/editor~Editor} editor An editor in which this command will be used. + * @param {String} defaultValue The default value of the attribute. */ - constructor( editor ) { - super( editor, 'borderWidth' ); + constructor( editor, defaultValue ) { + super( editor, 'borderWidth', defaultValue ); } /** @@ -50,13 +51,25 @@ export default class TableCellBorderWidthCommand extends TableCellPropertyComman return; } - return getSingleValue( tableCell.getAttribute( this.attributeName ) ); + const value = getSingleValue( tableCell.getAttribute( this.attributeName ) ); + + if ( value === this._defaultValue ) { + return; + } + + return value; } /** * @inheritDoc */ _getValueToSet( value ) { - return addDefaultUnitToNumericValue( value, 'px' ); + value = addDefaultUnitToNumericValue( value, 'px' ); + + if ( value === this._defaultValue ) { + return; + } + + return value; } } diff --git a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellheightcommand.js b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellheightcommand.js index e00ac93bf36..ef1d4d52a12 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellheightcommand.js +++ b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellheightcommand.js @@ -37,15 +37,22 @@ export default class TableCellHeightCommand extends TableCellPropertyCommand { * Creates a new `TableCellHeightCommand` instance. * * @param {module:core/editor/editor~Editor} editor An editor in which this command will be used. + * @param {String} defaultValue The default value of the attribute. */ - constructor( editor ) { - super( editor, 'height' ); + constructor( editor, defaultValue ) { + super( editor, 'height', defaultValue ); } /** * @inheritDoc */ _getValueToSet( value ) { - return addDefaultUnitToNumericValue( value, 'px' ); + value = addDefaultUnitToNumericValue( value, 'px' ); + + if ( value === this._defaultValue ) { + return null; + } + + return value; } } diff --git a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js index b238afc81cd..715c914a546 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js +++ b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js @@ -28,8 +28,9 @@ export default class TableCellHorizontalAlignmentCommand extends TableCellProper * Creates a new `TableCellHorizontalAlignmentCommand` instance. * * @param {module:core/editor/editor~Editor} editor An editor in which this command will be used. + * @param {String} defaultValue The default value for the "alignment" attribute. */ - constructor( editor ) { - super( editor, 'horizontalAlignment' ); + constructor( editor, defaultValue ) { + super( editor, 'horizontalAlignment', defaultValue ); } } diff --git a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellpaddingcommand.js b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellpaddingcommand.js index 3d9b3d12ecf..9b06dae7b26 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellpaddingcommand.js +++ b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellpaddingcommand.js @@ -37,9 +37,10 @@ export default class TableCellPaddingCommand extends TableCellPropertyCommand { * Creates a new `TableCellPaddingCommand` instance. * * @param {module:core/editor/editor~Editor} editor An editor in which this command will be used. + * @param {String} defaultValue The default value of the attribute. */ - constructor( editor ) { - super( editor, 'padding' ); + constructor( editor, defaultValue ) { + super( editor, 'padding', defaultValue ); } /** @@ -50,13 +51,25 @@ export default class TableCellPaddingCommand extends TableCellPropertyCommand { return; } - return getSingleValue( tableCell.getAttribute( this.attributeName ) ); + const value = getSingleValue( tableCell.getAttribute( this.attributeName ) ); + + if ( value === this._defaultValue ) { + return; + } + + return value; } /** * @inheritDoc */ _getValueToSet( value ) { - return addDefaultUnitToNumericValue( value, 'px' ); + value = addDefaultUnitToNumericValue( value, 'px' ); + + if ( value === this._defaultValue ) { + return; + } + + return value; } } diff --git a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellpropertycommand.js b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellpropertycommand.js index c2eacfef415..3f72baffe9f 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellpropertycommand.js +++ b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellpropertycommand.js @@ -23,11 +23,27 @@ export default class TableCellPropertyCommand extends Command { * * @param {module:core/editor/editor~Editor} editor An editor in which this command will be used. * @param {String} attributeName Table cell attribute name. + * @param {String} defaultValue The default value of the attribute. */ - constructor( editor, attributeName ) { + constructor( editor, attributeName, defaultValue ) { super( editor ); + /** + * The attribute that will be set by the command. + * + * @readonly + * @member {String} + */ this.attributeName = attributeName; + + /** + * The default value for the attribute. + * + * @readonly + * @protected + * @member {String} + */ + this._defaultValue = defaultValue; } /** @@ -78,7 +94,13 @@ export default class TableCellPropertyCommand extends Command { return; } - return tableCell.getAttribute( this.attributeName ); + const value = tableCell.getAttribute( this.attributeName ); + + if ( value === this._defaultValue ) { + return; + } + + return value; } /** @@ -89,6 +111,10 @@ export default class TableCellPropertyCommand extends Command { * @returns {*} */ _getValueToSet( value ) { + if ( value === this._defaultValue ) { + return; + } + return value; } diff --git a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellverticalalignmentcommand.js b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellverticalalignmentcommand.js index 6cb51425df2..9bce02a0179 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellverticalalignmentcommand.js +++ b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellverticalalignmentcommand.js @@ -36,8 +36,9 @@ export default class TableCellVerticalAlignmentCommand extends TableCellProperty * Creates a new `TableCellVerticalAlignmentCommand` instance. * * @param {module:core/editor/editor~Editor} editor An editor in which this command will be used. + * @param {String} defaultValue The default value for the "alignment" attribute. */ - constructor( editor ) { - super( editor, 'verticalAlignment' ); + constructor( editor, defaultValue ) { + super( editor, 'verticalAlignment', defaultValue ); } } diff --git a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellwidthcommand.js b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellwidthcommand.js index 82535875e5e..11cf8d847cd 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellwidthcommand.js +++ b/packages/ckeditor5-table/src/tablecellproperties/commands/tablecellwidthcommand.js @@ -37,15 +37,22 @@ export default class TableCellWidthCommand extends TableCellPropertyCommand { * Creates a new `TableCellWidthCommand` instance. * * @param {module:core/editor/editor~Editor} editor An editor in which this command will be used. + * @param {String} defaultValue The default value of the attribute. */ - constructor( editor ) { - super( editor, 'width' ); + constructor( editor, defaultValue ) { + super( editor, 'width', defaultValue ); } /** * @inheritDoc */ _getValueToSet( value ) { - return addDefaultUnitToNumericValue( value, 'px' ); + value = addDefaultUnitToNumericValue( value, 'px' ); + + if ( value === this._defaultValue ) { + return; + } + + return value; } } diff --git a/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js b/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js index 3196c009ba2..25d5e94b4eb 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js +++ b/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesediting.js @@ -21,8 +21,10 @@ import TableCellHorizontalAlignmentCommand from './commands/tablecellhorizontala import TableCellBorderStyleCommand from './commands/tablecellborderstylecommand'; import TableCellBorderColorCommand from './commands/tablecellbordercolorcommand'; import TableCellBorderWidthCommand from './commands/tablecellborderwidthcommand'; +import { getNormalizedDefaultProperties } from '../utils/table-properties'; -const VALIGN_VALUES_REG_EXP = /^(top|bottom)$/; +const VALIGN_VALUES_REG_EXP = /^(top|middle|bottom)$/; +const ALIGN_VALUES_REG_EXP = /^(left|center|right|justify)$/; /** * The table cell properties editing feature. @@ -67,33 +69,74 @@ export default class TableCellPropertiesEditing extends Plugin { const editor = this.editor; const schema = editor.model.schema; const conversion = editor.conversion; - const locale = editor.locale; + + editor.config.define( 'table.tableCellProperties.defaultProperties', {} ); + + const defaultTableCellProperties = getNormalizedDefaultProperties( + editor.config.get( 'table.tableCellProperties.defaultProperties' ), + { + includeVerticalAlignmentProperty: true, + includeHorizontalAlignmentProperty: true, + includePaddingProperty: true, + isRightToLeftContent: editor.locale.contentLanguageDirection === 'rtl' + } + ); editor.data.addStyleProcessorRules( addBorderRules ); - enableBorderProperties( schema, conversion ); - editor.commands.add( 'tableCellBorderStyle', new TableCellBorderStyleCommand( editor ) ); - editor.commands.add( 'tableCellBorderColor', new TableCellBorderColorCommand( editor ) ); - editor.commands.add( 'tableCellBorderWidth', new TableCellBorderWidthCommand( editor ) ); + enableBorderProperties( schema, conversion, { + color: defaultTableCellProperties.borderColor, + style: defaultTableCellProperties.borderStyle, + width: defaultTableCellProperties.borderWidth + } ); + editor.commands.add( 'tableCellBorderStyle', new TableCellBorderStyleCommand( editor, defaultTableCellProperties.borderStyle ) ); + editor.commands.add( 'tableCellBorderColor', new TableCellBorderColorCommand( editor, defaultTableCellProperties.borderColor ) ); + editor.commands.add( 'tableCellBorderWidth', new TableCellBorderWidthCommand( editor, defaultTableCellProperties.borderWidth ) ); - enableHorizontalAlignmentProperty( schema, conversion, locale ); - editor.commands.add( 'tableCellHorizontalAlignment', new TableCellHorizontalAlignmentCommand( editor ) ); + enableHorizontalAlignmentProperty( schema, conversion, defaultTableCellProperties.horizontalAlignment ); + editor.commands.add( + 'tableCellHorizontalAlignment', + new TableCellHorizontalAlignmentCommand( editor, defaultTableCellProperties.horizontalAlignment ) + ); - enableProperty( schema, conversion, { modelAttribute: 'width', styleName: 'width' } ); - editor.commands.add( 'tableCellWidth', new TableCellWidthCommand( editor ) ); + enableProperty( schema, conversion, { + modelAttribute: 'width', + styleName: 'width', + defaultValue: defaultTableCellProperties.width + } ); + editor.commands.add( 'tableCellWidth', new TableCellWidthCommand( editor, defaultTableCellProperties.width ) ); - enableProperty( schema, conversion, { modelAttribute: 'height', styleName: 'height' } ); - editor.commands.add( 'tableCellHeight', new TableCellHeightCommand( editor ) ); + enableProperty( schema, conversion, { + modelAttribute: 'height', + styleName: 'height', + defaultValue: defaultTableCellProperties.height + } ); + editor.commands.add( 'tableCellHeight', new TableCellHeightCommand( editor, defaultTableCellProperties.height ) ); editor.data.addStyleProcessorRules( addPaddingRules ); - enableProperty( schema, conversion, { modelAttribute: 'padding', styleName: 'padding', reduceBoxSides: true } ); - editor.commands.add( 'tableCellPadding', new TableCellPaddingCommand( editor ) ); + enableProperty( schema, conversion, { + modelAttribute: 'padding', + styleName: 'padding', + reduceBoxSides: true, + defaultValue: defaultTableCellProperties.padding + } ); + editor.commands.add( 'tableCellPadding', new TableCellPaddingCommand( editor, defaultTableCellProperties.padding ) ); editor.data.addStyleProcessorRules( addBackgroundRules ); - enableProperty( schema, conversion, { modelAttribute: 'backgroundColor', styleName: 'background-color' } ); - editor.commands.add( 'tableCellBackgroundColor', new TableCellBackgroundColorCommand( editor ) ); + enableProperty( schema, conversion, { + modelAttribute: 'backgroundColor', + styleName: 'background-color', + defaultValue: defaultTableCellProperties.backgroundColor + } ); + editor.commands.add( + 'tableCellBackgroundColor', + new TableCellBackgroundColorCommand( editor, defaultTableCellProperties.backgroundColor ) + ); - enableVerticalAlignmentProperty( schema, conversion ); - editor.commands.add( 'tableCellVerticalAlignment', new TableCellVerticalAlignmentCommand( editor ) ); + enableVerticalAlignmentProperty( schema, conversion, defaultTableCellProperties.verticalAlignment ); + editor.commands.add( + 'tableCellVerticalAlignment', + new TableCellVerticalAlignmentCommand( editor, defaultTableCellProperties.verticalAlignment ) + ); } } @@ -101,12 +144,16 @@ export default class TableCellPropertiesEditing extends Plugin { // // @param {module:engine/model/schema~Schema} schema // @param {module:engine/conversion/conversion~Conversion} conversion -function enableBorderProperties( schema, conversion ) { +// @param {Object} defaultBorder The default border values. +// @param {String} defaultBorder.color The default `borderColor` value. +// @param {String} defaultBorder.style The default `borderStyle` value. +// @param {String} defaultBorder.width The default `borderWidth` value. +function enableBorderProperties( schema, conversion, defaultBorder ) { schema.extend( 'tableCell', { allowAttributes: [ 'borderWidth', 'borderColor', 'borderStyle' ] } ); - upcastBorderStyles( conversion, 'td' ); - upcastBorderStyles( conversion, 'th' ); + upcastBorderStyles( conversion, 'td', defaultBorder ); + upcastBorderStyles( conversion, 'th', defaultBorder ); downcastAttributeToStyle( conversion, { modelElement: 'tableCell', modelAttribute: 'borderStyle', styleName: 'border-style' } ); downcastAttributeToStyle( conversion, { modelElement: 'tableCell', modelAttribute: 'borderColor', styleName: 'border-color' } ); downcastAttributeToStyle( conversion, { modelElement: 'tableCell', modelAttribute: 'borderWidth', styleName: 'border-width' } ); @@ -117,74 +164,120 @@ function enableBorderProperties( schema, conversion ) { // @param {module:engine/model/schema~Schema} schema // @param {module:engine/conversion/conversion~Conversion} conversion // @param {module:utils/locale~Locale} locale The {@link module:core/editor/editor~Editor#locale} instance. -function enableHorizontalAlignmentProperty( schema, conversion, locale ) { +// @param {String} defaultValue The default horizontal alignment value. +function enableHorizontalAlignmentProperty( schema, conversion, defaultValue ) { schema.extend( 'tableCell', { allowAttributes: [ 'horizontalAlignment' ] } ); - const options = [ locale.contentLanguageDirection == 'rtl' ? 'left' : 'right', 'center', 'justify' ]; - - conversion.attributeToAttribute( { - model: { - name: 'tableCell', - key: 'horizontalAlignment', - values: options - }, - view: options.reduce( ( result, option ) => ( { - ...result, - [ option ]: { + conversion.for( 'downcast' ) + .attributeToAttribute( { + model: { + name: 'tableCell', + key: 'horizontalAlignment' + }, + view: alignment => ( { key: 'style', value: { - 'text-align': option + 'text-align': alignment + } + } ) + } ); + + conversion.for( 'upcast' ) + // Support for the `text-align:*;` CSS definition for the table cell alignment. + .attributeToAttribute( { + view: { + name: /^(td|th)$/, + styles: { + 'text-align': ALIGN_VALUES_REG_EXP + } + }, + model: { + key: 'horizontalAlignment', + value: viewElement => { + const align = viewElement.getStyle( 'text-align' ); + + return align === defaultValue ? null : align; } } - } ), {} ) - } ); + } ) + // Support for the `align` attribute as the backward compatibility while pasting from other sources. + .attributeToAttribute( { + view: { + name: /^(td|th)$/, + attributes: { + align: ALIGN_VALUES_REG_EXP + } + }, + model: { + key: 'horizontalAlignment', + value: viewElement => { + const align = viewElement.getAttribute( 'align' ); + + return align === defaultValue ? null : align; + } + } + } ); } // Enables the `'verticalAlignment'` attribute for table cells. // // @param {module:engine/model/schema~Schema} schema // @param {module:engine/conversion/conversion~Conversion} conversion -function enableVerticalAlignmentProperty( schema, conversion ) { +// @param {String} defaultValue The default vertical alignment value. +function enableVerticalAlignmentProperty( schema, conversion, defaultValue ) { schema.extend( 'tableCell', { allowAttributes: [ 'verticalAlignment' ] } ); - conversion.attributeToAttribute( { - model: { - name: 'tableCell', - key: 'verticalAlignment', - values: [ 'top', 'bottom' ] - }, - view: { - top: { - key: 'style', - value: { - 'vertical-align': 'top' - } + conversion.for( 'downcast' ) + .attributeToAttribute( { + model: { + name: 'tableCell', + key: 'verticalAlignment' }, - bottom: { + view: alignment => ( { key: 'style', value: { - 'vertical-align': 'bottom' + 'vertical-align': alignment } - } - } - } ); + } ) + } ); conversion.for( 'upcast' ) - // Support for backwards compatibility and pasting from other sources. + // Support for the `vertical-align:*;` CSS definition for the table cell alignment. .attributeToAttribute( { view: { + name: /^(td|th)$/, + styles: { + 'vertical-align': VALIGN_VALUES_REG_EXP + } + }, + model: { + key: 'verticalAlignment', + value: viewElement => { + const align = viewElement.getStyle( 'vertical-align' ); + + return align === defaultValue ? null : align; + } + } + } ) + // Support for the `align` attribute as the backward compatibility while pasting from other sources. + .attributeToAttribute( { + view: { + name: /^(td|th)$/, attributes: { valign: VALIGN_VALUES_REG_EXP } }, model: { - name: 'tableCell', key: 'verticalAlignment', - value: viewElement => viewElement.getAttribute( 'valign' ) + value: viewElement => { + const valign = viewElement.getAttribute( 'valign' ); + + return valign === defaultValue ? null : valign; + } } } ); } @@ -196,6 +289,7 @@ function enableVerticalAlignmentProperty( schema, conversion ) { // @param {Object} options // @param {String} options.modelAttribute // @param {String} options.styleName +// @param {String} options.defaultValue The default value for the specified `modelAttribute`. // @param {Boolean} [options.reduceBoxSides=false] function enableProperty( schema, conversion, options ) { const { modelAttribute } = options; diff --git a/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesui.js b/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesui.js index 691f3e123a3..2175f701218 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesui.js +++ b/packages/ckeditor5-table/src/tablecellproperties/tablecellpropertiesui.js @@ -24,6 +24,7 @@ import { getTableWidgetAncestor } from '../utils/ui/widget'; import { getBalloonCellPositionData, repositionContextualBalloon } from '../utils/ui/contextualballoon'; import tableCellProperties from './../../theme/icons/table-cell-properties.svg'; +import { getNormalizedDefaultProperties } from '../utils/table-properties'; const ERROR_TEXT_TIMEOUT = 500; @@ -83,6 +84,22 @@ export default class TableCellPropertiesUI extends Plugin { const editor = this.editor; const t = editor.t; + /** + * The default table cell properties. + * + * @protected + * @member {module:table/tablecellproperties~TableCellPropertiesOptions} + */ + this._defaultTableCellProperties = getNormalizedDefaultProperties( + editor.config.get( 'table.tableCellProperties.defaultProperties' ), + { + includeVerticalAlignmentProperty: true, + includeHorizontalAlignmentProperty: true, + includePaddingProperty: true, + isRightToLeftContent: editor.locale.contentLanguageDirection === 'rtl' + } + ); + /** * The contextual balloon plugin instance. * @@ -157,7 +174,8 @@ export default class TableCellPropertiesUI extends Plugin { const localizedBackgroundColors = getLocalizedColorOptions( editor.locale, backgroundColorsConfig ); const view = new TableCellPropertiesView( editor.locale, { borderColors: localizedBorderColors, - backgroundColors: localizedBackgroundColors + backgroundColors: localizedBackgroundColors, + defaultTableCellProperties: this._defaultTableCellProperties } ); const t = editor.t; @@ -208,52 +226,67 @@ export default class TableCellPropertiesUI extends Plugin { // property of the view has changed. They also validate the value and display errors in the UI // when necessary. This makes the view live, which means the changes are // visible in the editing as soon as the user types or changes fields' values. - view.on( 'change:borderStyle', this._getPropertyChangeCallback( 'tableCellBorderStyle' ) ); + view.on( + 'change:borderStyle', + this._getPropertyChangeCallback( 'tableCellBorderStyle', this._defaultTableCellProperties.borderStyle ) + ); view.on( 'change:borderColor', this._getValidatedPropertyChangeCallback( { viewField: view.borderColorInput, commandName: 'tableCellBorderColor', errorText: colorErrorText, - validator: colorFieldValidator + validator: colorFieldValidator, + defaultValue: this._defaultTableCellProperties.borderColor } ) ); view.on( 'change:borderWidth', this._getValidatedPropertyChangeCallback( { viewField: view.borderWidthInput, commandName: 'tableCellBorderWidth', errorText: lengthErrorText, - validator: lineWidthFieldValidator + validator: lineWidthFieldValidator, + defaultValue: this._defaultTableCellProperties.borderWidth } ) ); view.on( 'change:padding', this._getValidatedPropertyChangeCallback( { viewField: view.paddingInput, commandName: 'tableCellPadding', errorText: lengthErrorText, - validator: lengthFieldValidator + validator: lengthFieldValidator, + defaultValue: this._defaultTableCellProperties.padding } ) ); view.on( 'change:width', this._getValidatedPropertyChangeCallback( { viewField: view.widthInput, commandName: 'tableCellWidth', errorText: lengthErrorText, - validator: lengthFieldValidator + validator: lengthFieldValidator, + defaultValue: this._defaultTableCellProperties.width } ) ); view.on( 'change:height', this._getValidatedPropertyChangeCallback( { viewField: view.heightInput, commandName: 'tableCellHeight', errorText: lengthErrorText, - validator: lengthFieldValidator + validator: lengthFieldValidator, + defaultValue: this._defaultTableCellProperties.height } ) ); view.on( 'change:backgroundColor', this._getValidatedPropertyChangeCallback( { viewField: view.backgroundInput, commandName: 'tableCellBackgroundColor', errorText: colorErrorText, - validator: colorFieldValidator + validator: colorFieldValidator, + defaultValue: this._defaultTableCellProperties.backgroundColor } ) ); - view.on( 'change:horizontalAlignment', this._getPropertyChangeCallback( 'tableCellHorizontalAlignment' ) ); - view.on( 'change:verticalAlignment', this._getPropertyChangeCallback( 'tableCellVerticalAlignment' ) ); + view.on( + 'change:horizontalAlignment', + this._getPropertyChangeCallback( 'tableCellHorizontalAlignment', this._defaultTableCellProperties.horizontalAlignment ) + ); + view.on( + 'change:verticalAlignment', + this._getPropertyChangeCallback( 'tableCellVerticalAlignment', this._defaultTableCellProperties.verticalAlignment ) + ); return view; } @@ -270,10 +303,22 @@ export default class TableCellPropertiesUI extends Plugin { */ _fillViewFormFromCommandValues() { const commands = this.editor.commands; + const borderStyleCommand = commands.get( 'tableCellBorderStyle' ); Object.entries( propertyToCommandMap ) - .map( ( [ property, commandName ] ) => [ property, commands.get( commandName ).value || '' ] ) - .forEach( ( [ property, value ] ) => this.view.set( property, value ) ); + .map( ( [ property, commandName ] ) => { + const defaultValue = this._defaultTableCellProperties[ property ] || ''; + + return [ property, commands.get( commandName ).value || defaultValue ]; + } ) + .forEach( ( [ property, value ] ) => { + // Do not set the `border-color` and `border-width` fields if `border-style:none`. + if ( ( property === 'borderColor' || property === 'borderWidth' ) && borderStyleCommand.value === 'none' ) { + return; + } + + this.view.set( property, value ); + } ); } /** @@ -354,10 +399,17 @@ export default class TableCellPropertiesUI extends Plugin { * * @private * @param {String} commandName + * @param {String} defaultValue The default value of the command. * @returns {Function} */ - _getPropertyChangeCallback( commandName ) { - return ( evt, propertyName, newValue ) => { + _getPropertyChangeCallback( commandName, defaultValue ) { + return ( evt, propertyName, newValue, oldValue ) => { + // If the "oldValue" is missing and "newValue" is set to the default value, do not execute the command. + // It is an initial call (when opening the table properties view). + if ( !oldValue && defaultValue === newValue ) { + return; + } + this.editor.execute( commandName, { value: newValue, batch: this._undoStepBatch @@ -376,16 +428,24 @@ export default class TableCellPropertiesUI extends Plugin { * @param {module:ui/view~View} options.viewField * @param {Function} options.validator * @param {String} options.errorText + * @param {String} options.defaultValue * @returns {Function} */ - _getValidatedPropertyChangeCallback( { commandName, viewField, validator, errorText } ) { + _getValidatedPropertyChangeCallback( options ) { + const { commandName, viewField, validator, errorText, defaultValue } = options; const setErrorTextDebounced = debounce( () => { viewField.errorText = errorText; }, ERROR_TEXT_TIMEOUT ); - return ( evt, propertyName, newValue ) => { + return ( evt, propertyName, newValue, oldValue ) => { setErrorTextDebounced.cancel(); + // If the "oldValue" is missing and "newValue" is set to the default value, do not execute the command. + // It is an initial call (when opening the table properties view). + if ( !oldValue && defaultValue === newValue ) { + return; + } + if ( validator( newValue ) ) { this.editor.execute( commandName, { value: newValue, diff --git a/packages/ckeditor5-table/src/tablecellproperties/ui/tablecellpropertiesview.js b/packages/ckeditor5-table/src/tablecellproperties/ui/tablecellpropertiesview.js index 96c42daf725..4c743cd2c66 100644 --- a/packages/ckeditor5-table/src/tablecellproperties/ui/tablecellpropertiesview.js +++ b/packages/ckeditor5-table/src/tablecellproperties/ui/tablecellpropertiesview.js @@ -62,6 +62,8 @@ export default class TableCellPropertiesView extends View { * @param {module:table/table~TableColorConfig} options.backgroundColors A configuration of the background * color palette used by the * {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView#backgroundInput}. + * @param {module:table/tablecellproperties~TableCellPropertiesOptions} options.defaultTableCellProperties The default + * table cell properties. */ constructor( locale, options ) { super( locale ); @@ -446,9 +448,17 @@ export default class TableCellPropertiesView extends View { * @returns {Object.} */ _createBorderFields() { + const defaultTableCellProperties = this.options.defaultTableCellProperties; + const defaultBorder = { + style: defaultTableCellProperties.borderStyle, + width: defaultTableCellProperties.borderWidth, + color: defaultTableCellProperties.borderColor + }; + const colorInputCreator = getLabeledColorInputCreator( { colorConfig: this.options.borderColors, - columns: 5 + columns: 5, + defaultColorValue: defaultBorder.color } ); const locale = this.locale; const t = this.t; @@ -483,7 +493,7 @@ export default class TableCellPropertiesView extends View { borderStyleDropdown.bind( 'isEmpty' ).to( this, 'borderStyle', value => !value ); - addListToDropdown( borderStyleDropdown.fieldView, getBorderStyleDefinitions( this ) ); + addListToDropdown( borderStyleDropdown.fieldView, getBorderStyleDefinitions( this, defaultBorder.style ) ); // -- Width --------------------------------------------------- @@ -516,13 +526,20 @@ export default class TableCellPropertiesView extends View { this.borderColor = borderColorInput.fieldView.value; } ); - // Reset the border color and width fields when style is "none". - // https://github.com/ckeditor/ckeditor5/issues/6227 - this.on( 'change:borderStyle', ( evt, name, value ) => { - if ( !isBorderStyleSet( value ) ) { + // Reset the border color and width fields depending on the `border-style` value. + this.on( 'change:borderStyle', ( evt, name, newValue, oldValue ) => { + // When removing the border (`border-style:none`), clear the remaining `border-*` properties. + // See: https://github.com/ckeditor/ckeditor5/issues/6227. + if ( !isBorderStyleSet( newValue ) ) { this.borderColor = ''; this.borderWidth = ''; } + + // When setting the `border-style` from `none`, set the default `border-color` and `border-width` properties. + if ( !isBorderStyleSet( oldValue ) ) { + this.borderColor = defaultBorder.color; + this.borderWidth = defaultBorder.width; + } } ); return { @@ -554,7 +571,8 @@ export default class TableCellPropertiesView extends View { const colorInputCreator = getLabeledColorInputCreator( { colorConfig: this.options.backgroundColors, - columns: 5 + columns: 5, + defaultColorValue: this.options.defaultTableCellProperties.backgroundColor } ); const backgroundInput = new LabeledFieldView( locale, colorInputCreator ); @@ -705,8 +723,18 @@ export default class TableCellPropertiesView extends View { labels: this._horizontalAlignmentLabels, propertyName: 'horizontalAlignment', nameToValue: name => { - return name === ( isContentRTL ? 'right' : 'left' ) ? '' : name; - } + // For the RTL content, we want to swap the buttons "align to the left" and "align to the right". + if ( isContentRTL ) { + if ( name === 'left' ) { + return 'right'; + } else if ( name === 'right' ) { + return 'left'; + } + } + + return name; + }, + defaultValue: this.options.defaultTableCellProperties.horizontalAlignment } ); // -- Vertical ----------------------------------------------------- @@ -724,9 +752,7 @@ export default class TableCellPropertiesView extends View { toolbar: verticalAlignmentToolbar, labels: this._verticalAlignmentLabels, propertyName: 'verticalAlignment', - nameToValue: name => { - return name === 'middle' ? '' : name; - } + defaultValue: this.options.defaultTableCellProperties.verticalAlignment } ); return { @@ -825,10 +851,5 @@ export default class TableCellPropertiesView extends View { } function isBorderStyleSet( value ) { - // TODO: Unify this with TablePropertiesView when implementing the default cell properties. - if ( !value || !value.length ) { - return false; - } - return value !== 'none'; } diff --git a/packages/ckeditor5-table/src/tableproperties/commands/tablepropertycommand.js b/packages/ckeditor5-table/src/tableproperties/commands/tablepropertycommand.js index f8329e9d4f6..cbf71a6d3c5 100644 --- a/packages/ckeditor5-table/src/tableproperties/commands/tablepropertycommand.js +++ b/packages/ckeditor5-table/src/tableproperties/commands/tablepropertycommand.js @@ -98,13 +98,13 @@ export default class TablePropertyCommand extends Command { return; } - const attribute = table.getAttribute( this.attributeName ); + const value = table.getAttribute( this.attributeName ); - if ( attribute === this._defaultValue ) { + if ( value === this._defaultValue ) { return; } - return attribute; + return value; } /** diff --git a/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js b/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js index b10e20c29cd..349a16d809b 100644 --- a/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js +++ b/packages/ckeditor5-table/src/tableproperties/tablepropertiesediting.js @@ -73,7 +73,9 @@ export default class TablePropertiesEditing extends Plugin { editor.config.define( 'table.tableProperties.defaultProperties', {} ); - const defaultTableProperties = getNormalizedDefaultProperties( editor.config.get( 'table.tableProperties.defaultProperties' ) ); + const defaultTableProperties = getNormalizedDefaultProperties( editor.config.get( 'table.tableProperties.defaultProperties' ), { + includeAlignmentProperty: true + } ); editor.data.addStyleProcessorRules( addBorderRules ); enableBorderProperties( schema, conversion, { @@ -163,12 +165,12 @@ function enableAlignmentProperty( schema, conversion, defaultValue ) { // Support for the `float:*;` CSS definition for the table alignment. .attributeToAttribute( { view: { + name: /^(table|figure)$/, styles: { float: FLOAT_VALUES_REG_EXP } }, model: { - name: 'table', key: 'alignment', value: viewElement => { let align = viewElement.getStyle( 'float' ); @@ -208,6 +210,7 @@ function enableAlignmentProperty( schema, conversion, defaultValue ) { // @param {Object} options // @param {String} options.modelAttribute // @param {String} options.styleName +// @param {String} options.defaultValue The default value for the specified `modelAttribute`. function enableProperty( schema, conversion, options ) { const { modelAttribute } = options; diff --git a/packages/ckeditor5-table/src/tableproperties/tablepropertiesui.js b/packages/ckeditor5-table/src/tableproperties/tablepropertiesui.js index c1a814eaf93..195bc087512 100644 --- a/packages/ckeditor5-table/src/tableproperties/tablepropertiesui.js +++ b/packages/ckeditor5-table/src/tableproperties/tablepropertiesui.js @@ -88,7 +88,9 @@ export default class TablePropertiesUI extends Plugin { * @protected * @member {module:table/tableproperties~TablePropertiesOptions} */ - this._defaultTableProperties = getNormalizedDefaultProperties( editor.config.get( 'table.tableProperties.defaultProperties' ) ); + this._defaultTableProperties = getNormalizedDefaultProperties( editor.config.get( 'table.tableProperties.defaultProperties' ), { + includeAlignmentProperty: true + } ); /** * The contextual balloon plugin instance. diff --git a/packages/ckeditor5-table/src/utils/table-properties.js b/packages/ckeditor5-table/src/utils/table-properties.js index 4ceb7eda746..edd6a8dd01f 100644 --- a/packages/ckeditor5-table/src/utils/table-properties.js +++ b/packages/ckeditor5-table/src/utils/table-properties.js @@ -68,13 +68,17 @@ export function addDefaultUnitToNumericValue( value, defaultUnit ) { /** * Returns the normalized configuration. * - * @protected * @param {Object} config - * @returns {module:table/tableproperties~TablePropertiesOptions} + * @param {Object} [options={}] + * @param {Boolean} [options.includeAlignmentProperty=false] Whether the "alignment" property should be added. + * @param {Boolean} [options.includePaddingProperty=false] Whether the "padding" property should be added. + * @param {Boolean} [options.includeVerticalAlignmentProperty=false] Whether the "verticalAlignment" property should be added. + * @param {Boolean} [options.includeHorizontalAlignmentProperty=false] Whether the "horizontalAlignment" property should be added. + * @param {Boolean} [options.isRightToLeftContent=false] Whether the content is right-to-left. + * @returns {Object} */ -export function getNormalizedDefaultProperties( config ) { - return Object.assign( { - alignment: 'center', +export function getNormalizedDefaultProperties( config, options = {} ) { + const normalizedConfig = Object.assign( { borderStyle: 'none', borderWidth: '', borderColor: '', @@ -82,4 +86,22 @@ export function getNormalizedDefaultProperties( config ) { width: '', height: '' }, config ); + + if ( options.includeAlignmentProperty && !normalizedConfig.alignment ) { + normalizedConfig.alignment = 'center'; + } + + if ( options.includePaddingProperty && !normalizedConfig.padding ) { + normalizedConfig.padding = ''; + } + + if ( options.includeVerticalAlignmentProperty && !normalizedConfig.verticalAlignment ) { + normalizedConfig.verticalAlignment = 'middle'; + } + + if ( options.includeHorizontalAlignmentProperty && !normalizedConfig.horizontalAlignment ) { + normalizedConfig.horizontalAlignment = options.isRightToLeftContent ? 'right' : 'left'; + } + + return normalizedConfig; } diff --git a/packages/ckeditor5-table/tests/manual/tabledefaultproperties.html b/packages/ckeditor5-table/tests/manual/tabledefaultproperties.html index f58a7cd2d76..b1a15fc3133 100644 --- a/packages/ckeditor5-table/tests/manual/tabledefaultproperties.html +++ b/packages/ckeditor5-table/tests/manual/tabledefaultproperties.html @@ -11,6 +11,15 @@ border-width: 3px; background-color: #00f; } + + .ck-content .table table td { + border-style: dotted; + border-color: hsl(120, 75%, 60%); + border-width: 2px; + text-align: right; + vertical-align: bottom; + padding: 10px + }

The page defines the following styles in the <style> element.

@@ -20,7 +29,19 @@
- + + + + + + + + + + + + +
Foo.Left-top.Center-top.Right-top.
Left-middle.Center-middle.Right-middle.
Left-bottom.Center-bottom.Right-bottom.
diff --git a/packages/ckeditor5-table/tests/manual/tabledefaultproperties.js b/packages/ckeditor5-table/tests/manual/tabledefaultproperties.js index 1469664441a..2a208be399a 100644 --- a/packages/ckeditor5-table/tests/manual/tabledefaultproperties.js +++ b/packages/ckeditor5-table/tests/manual/tabledefaultproperties.js @@ -48,7 +48,8 @@ ClassicEditor borderColor: 'hsl(120, 75%, 60%)', borderWidth: '2px', horizontalAlignment: 'right', - verticalAlignment: 'bottom' + verticalAlignment: 'bottom', + padding: '10px' } } } diff --git a/packages/ckeditor5-table/tests/manual/tabledefaultproperties.md b/packages/ckeditor5-table/tests/manual/tabledefaultproperties.md index 459b75145de..0aa8afbc019 100644 --- a/packages/ckeditor5-table/tests/manual/tabledefaultproperties.md +++ b/packages/ckeditor5-table/tests/manual/tabledefaultproperties.md @@ -1,28 +1,48 @@ ### Table Default Properties * CSS stylesheet defined on the page is also displayed above the editor. -* Default values should not be applied in the model. -* Color pickers (for `border-color` and `background-color`) should not have the `Remove color` button. It should be replaced with the `Restore default` option. * The editor was initialized with the following configuration: ```js - const defaultProperties = { - borderStyle: 'dashed', - borderColor: 'hsl(0, 0%, 60%)', - borderWidth: '3px', - backgroundColor: '#00f', - alignment: 'left', - width: '300px', - height: '250px' + const tableConfig = { + tableProperties: { + defaultProperties: { + borderStyle: 'dashed', + borderColor: 'hsl(0, 0%, 60%)', + borderWidth: '3px', + backgroundColor: '#00f', + alignment: 'left', + width: '300px', + height: '250px' + } + }, + tableCellProperties: { + defaultProperties: { + borderStyle: 'dotted', + borderColor: 'hsl(120, 75%, 60%)', + borderWidth: '2px', + horizontalAlignment: 'right', + verticalAlignment: 'bottom', + padding: '10px' + } + } } ``` +* Default values should not be applied in the model. + 1. The last column should not contain the `horizontalAlignment` attribute. + 1. The last row should not contain the `verticalAlignment` attribute. + * The last cell (3, 3) should not contain any `*Alignment` attribute. + 1. The rest cells should match to the attributes to their content (`horizontalAlignment-verticalAlignment`). +* The color picker for the `border-color` property should contain the `Restore default` button for both – table and table cell views. +* The color picker for `background-color` property should contain the `Restore default` button for table view. * Calling `editor.getData()` on the initial data should return the data without any attribute (even if the editor's UI shows them). +* Change from the default value should be saved into the model. * Non-default values should be upcasted (set on the model element). Use the snippet for testing: ```js editor.setData( '' + '' + '' + - '' + '' + diff --git a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellbackgroundcolorcommand.js b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellbackgroundcolorcommand.js index 2dcbc75926b..29390fa346b 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellbackgroundcolorcommand.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellbackgroundcolorcommand.js @@ -15,7 +15,7 @@ import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils' describe( 'table cell properties', () => { describe( 'commands', () => { - describe( 'TableCellBackgroundColorCommand', () => { + describe( 'TableCellBackgroundColorCommand: empty default value', () => { let editor, model, command; beforeEach( async () => { @@ -24,7 +24,7 @@ describe( 'table cell properties', () => { } ); model = editor.model; - command = new TableCellBackgroundColorCommand( editor ); + command = new TableCellBackgroundColorCommand( editor, '' ); } ); afterEach( () => { @@ -255,5 +255,98 @@ describe( 'table cell properties', () => { } ); } ); } ); + + describe( 'TableCellBackgroundColorCommand: non-empty default value', () => { + let editor, model, command; + + beforeEach( async () => { + editor = await ModelTestEditor.create( { + plugins: [ Paragraph, TableCellPropertiesEditing ] + } ); + + model = editor.model; + command = new TableCellBackgroundColorCommand( editor, 'red' ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + describe( 'value', () => { + describe( 'collapsed selection', () => { + it( 'should be undefined if selected table cell has set the default value', () => { + setData( model, modelTable( [ [ { backgroundColor: 'red', contents: '[]foo' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should be undefined if selected table cell has the default value', () => { + setData( model, modelTable( [ [ { backgroundColor: 'red', contents: 'f[o]o' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'multi-cell selection', () => { + it( + 'should be undefined if all table cell have the same "backgroundColor" property value which is the default value', + () => { + setData( model, modelTable( [ + [ + { contents: '00', isSelected: true, backgroundColor: 'red' }, + { contents: '01', isSelected: true, backgroundColor: 'red' } + ], + [ + '10', + { contents: '11', isSelected: true, backgroundColor: 'red' } + ] + ] ) ); + + expect( command.value ).to.be.undefined; + } + ); + } ); + } ); + + describe( 'execute()', () => { + describe( 'collapsed selection', () => { + it( 'should remove backgroundColor from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ { backgroundColor: 'blue', contents: '[]foo' } ] ] ) ); + + command.execute( { value: 'red' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should remove backgroundColor from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ { backgroundColor: 'blue', contents: '[foo]' } ] ] ) ); + + command.execute( { value: 'red' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'multi-cell selection', () => { + it( 'should remove "backgroundColor" from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ + [ { contents: '00', isSelected: true, backgroundColor: '#f00' }, '01' ], + [ '10', { contents: '11', isSelected: true, backgroundColor: '#f00' } ] + ] ) ); + + command.execute( { value: 'red' } ); + + assertEqualMarkup( editor.getData(), viewTable( [ + [ '00', '01' ], + [ '10', '11' ] + ] ) ); + } ); + } ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellbordercolorcommand.js b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellbordercolorcommand.js index 385726b76ee..927672b70e8 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellbordercolorcommand.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellbordercolorcommand.js @@ -15,7 +15,7 @@ import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils' describe( 'table cell properties', () => { describe( 'commands', () => { - describe( 'TableCellBorderColorCommand', () => { + describe( 'TableCellBorderColorCommand: empty default value', () => { let editor, model, command; beforeEach( async () => { @@ -24,7 +24,7 @@ describe( 'table cell properties', () => { } ); model = editor.model; - command = new TableCellBorderColorCommand( editor ); + command = new TableCellBorderColorCommand( editor, '' ); } ); afterEach( () => { @@ -280,5 +280,109 @@ describe( 'table cell properties', () => { } ); } ); } ); + + describe( 'TableCellBorderColorCommand: non-default value', () => { + let editor, model, command; + + beforeEach( async () => { + editor = await ModelTestEditor.create( { + plugins: [ Paragraph, TableCellPropertiesEditing ] + } ); + + model = editor.model; + command = new TableCellBorderColorCommand( editor, 'red' ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + describe( 'value', () => { + describe( 'collapsed selection', () => { + it( 'should be undefined if selected table cell has the default borderColor property (single string)', () => { + setData( model, modelTable( [ [ { borderColor: 'red', contents: '[]foo' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + + it( 'should be undefined if selected table cell has the default borderColor property object with same values', () => { + setTableCellWithObjectAttributes( model, { + borderColor: { + top: 'red', + right: 'red', + bottom: 'red', + left: 'red' + } + }, '[]foo' ); + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should be undefined is selection contains the default value', () => { + setData( model, modelTable( [ [ { borderColor: 'red', contents: 'f[o]o' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'multi-cell selection', () => { + it( + 'should be undefined if all table cells have the same "borderColor" property value which is the default value', + () => { + setData( model, modelTable( [ + [ + { contents: '00', isSelected: true, borderColor: 'red' }, + { contents: '01', isSelected: true, borderColor: 'red' } + ], + [ + '10', + { contents: '11', isSelected: true, borderColor: 'red' } + ] + ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + } ); + + describe( 'execute()', () => { + describe( 'collapsed selection', () => { + it( 'should remove borderColor from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ { borderColor: 'blue', contents: '[]foo' } ] ] ) ); + + command.execute( { value: 'red' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should remove borderColor from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ '[foo]' ] ] ) ); + + command.execute( { value: 'red' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'multi-cell selection', () => { + it( 'should remove "borderColor" from the selected table cell if the default value is passed', () => { + setData( model, modelTable( [ + [ { contents: '00', isSelected: true, borderColor: '#f00' }, '01' ], + [ '10', { contents: '11', isSelected: true, borderColor: '#f00' } ] + ] ) ); + + command.execute( { value: 'red' } ); + + assertEqualMarkup( editor.getData(), viewTable( [ + [ '00', '01' ], + [ '10', '11' ] + ] ) ); + } ); + } ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellborderstylecommand.js b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellborderstylecommand.js index ee3d046d879..85dd069ae1d 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellborderstylecommand.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellborderstylecommand.js @@ -15,7 +15,7 @@ import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils' describe( 'table cell properties', () => { describe( 'commands', () => { - describe( 'TableCellBorderStyleCommand', () => { + describe( 'TableCellBorderStyleCommand: empty default value', () => { let editor, model, command; beforeEach( async () => { @@ -24,7 +24,7 @@ describe( 'table cell properties', () => { } ); model = editor.model; - command = new TableCellBorderStyleCommand( editor ); + command = new TableCellBorderStyleCommand( editor, '' ); } ); afterEach( () => { @@ -286,5 +286,110 @@ describe( 'table cell properties', () => { } ); } ); } ); + + describe( 'TableCellBorderStyleCommand: non-empty default value', () => { + let editor, model, command; + + beforeEach( async () => { + editor = await ModelTestEditor.create( { + plugins: [ Paragraph, TableCellPropertiesEditing ] + } ); + + model = editor.model; + command = new TableCellBorderStyleCommand( editor, 'solid' ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + describe( 'value', () => { + describe( 'collapsed selection', () => { + it( 'should be undefined if selected table cell has the default borderStyle property (single string)', () => { + setData( model, modelTable( [ [ { borderStyle: 'solid', contents: '[]foo' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + + it( 'should be undefined if selected table cell has the default borderStyle property object with same values', () => { + setTableCellWithObjectAttributes( model, { + borderStyle: { + top: 'solid', + right: 'solid', + bottom: 'solid', + left: 'solid' + } + }, '[]foo' ); + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should be undefined is selection contains the default value', () => { + setData( model, modelTable( [ [ { borderStyle: 'solid', contents: 'f[o]o' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'multi-cell selection', () => { + it( + 'should be undefined if all table cells have the same "borderStyle" property value which is the default value', + () => { + setData( model, modelTable( [ + [ + { contents: '00', isSelected: true, borderStyle: 'solid' }, + { contents: '01', isSelected: true, borderStyle: 'solid' } + ], + [ + '10', + { contents: '11', isSelected: true, borderStyle: 'solid' } + ] + ] ) ); + + expect( command.value ).to.be.undefined; + } + ); + } ); + } ); + + describe( 'execute()', () => { + describe( 'collapsed selection', () => { + it( 'should remove borderStyle from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ { borderStyle: 'ridge', contents: '[]foo' } ] ] ) ); + + command.execute( { value: 'solid' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should remove borderStyle from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ { borderStyle: 'ridge', contents: '[foo]' } ] ] ) ); + + command.execute( { value: 'solid' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'multi-cell selection', () => { + it( 'should remove "borderStyle" from selected table cells if the default value is passed', () => { + setData( model, modelTable( [ + [ { contents: '00', isSelected: true, borderStyle: 'solid' }, '01' ], + [ '10', { contents: '11', isSelected: true, borderStyle: 'solid' } ] + ] ) ); + + command.execute( { value: 'solid' } ); + + assertEqualMarkup( editor.getData(), viewTable( [ + [ '00', '01' ], + [ '10', '11' ] + ] ) ); + } ); + } ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellborderwidthcommand.js b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellborderwidthcommand.js index e4e2b790e3b..bd05cdd93c3 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellborderwidthcommand.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellborderwidthcommand.js @@ -15,7 +15,7 @@ import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils' describe( 'table cell properties', () => { describe( 'commands', () => { - describe( 'TableCellBorderWidthCommand', () => { + describe( 'TableCellBorderWidthCommand: empty default value', () => { let editor, model, command; beforeEach( async () => { @@ -24,7 +24,7 @@ describe( 'table cell properties', () => { } ); model = editor.model; - command = new TableCellBorderWidthCommand( editor ); + command = new TableCellBorderWidthCommand( editor, '' ); } ); afterEach( () => { @@ -342,5 +342,110 @@ describe( 'table cell properties', () => { } ); } ); } ); + + describe( 'TableCellBorderWidthCommand: non-empty default value', () => { + let editor, model, command; + + beforeEach( async () => { + editor = await ModelTestEditor.create( { + plugins: [ Paragraph, TableCellPropertiesEditing ] + } ); + + model = editor.model; + command = new TableCellBorderWidthCommand( editor, '3px' ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + describe( 'value', () => { + describe( 'collapsed selection', () => { + it( 'should be undefined if selected table cell has the default borderWidth property (single string)', () => { + setData( model, modelTable( [ [ { borderWidth: '3px', contents: '[]foo' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + + it( 'should be undefined if selected table cell hast the default borderWidth property object with same values', () => { + setTableCellWithObjectAttributes( model, { + borderWidth: { + top: '3px', + right: '3px', + bottom: '3px', + left: '3px' + } + }, '[]foo' ); + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should be undefined is selection contains the default valuel', () => { + setData( model, modelTable( [ [ { borderWidth: '3px', contents: 'f[o]o' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'multi-cell selection', () => { + it( + 'should be undefined if all table cells have the same "borderWidth" property value which is the default value', + () => { + setData( model, modelTable( [ + [ + { contents: '00', isSelected: true, borderWidth: '3px' }, + { contents: '01', isSelected: true, borderWidth: '3px' } + ], + [ + '10', + { contents: '11', isSelected: true, borderWidth: '3px' } + ] + ] ) ); + + expect( command.value ).to.be.undefined; + } + ); + } ); + } ); + + describe( 'execute()', () => { + describe( 'collapsed selection', () => { + it( 'should remove borderWidth from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ { borderWidth: '2em', contents: '[]foo' } ] ] ) ); + + command.execute( { value: '3px' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should remove borderWidth from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ '[foo]' ] ] ) ); + + command.execute( { value: '3px' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'multi-cell selection', () => { + it( 'should remove "borderWidth" from selected table cells if the default value is passed', () => { + setData( model, modelTable( [ + [ { contents: '00', isSelected: true, borderWidth: '1px' }, '01' ], + [ '10', { contents: '11', isSelected: true, borderWidth: '1px' } ] + ] ) ); + + command.execute( { value: '3px' } ); + + assertEqualMarkup( editor.getData(), viewTable( [ + [ '00', '01' ], + [ '10', '11' ] + ] ) ); + } ); + } ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellheightcommand.js b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellheightcommand.js index 1947483fb39..3e34c3127be 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellheightcommand.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellheightcommand.js @@ -15,7 +15,7 @@ import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils' describe( 'table cell properties', () => { describe( 'commands', () => { - describe( 'TableCellHeightCommand', () => { + describe( 'TableCellHeightCommand: empty default value', () => { let editor, model, command; beforeEach( async () => { @@ -24,7 +24,7 @@ describe( 'table cell properties', () => { } ); model = editor.model; - command = new TableCellHeightCommand( editor ); + command = new TableCellHeightCommand( editor, '' ); } ); afterEach( () => { @@ -311,5 +311,95 @@ describe( 'table cell properties', () => { } ); } ); } ); + + describe( 'TableCellHeightCommand: non-empty default value', () => { + let editor, model, command; + + beforeEach( async () => { + editor = await ModelTestEditor.create( { + plugins: [ Paragraph, TableCellPropertiesEditing ] + } ); + + model = editor.model; + command = new TableCellHeightCommand( editor, '30px' ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + describe( 'value', () => { + describe( 'collapsed selection', () => { + it( 'should be undefined if selected table cell has the default value property', () => { + setData( model, modelTable( [ [ { height: '30px', contents: '[]foo' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should be undefined if selected table cell has the default value', () => { + setData( model, modelTable( [ [ { height: '30px', contents: 'f[o]o' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'multi-cell selection', () => { + it( 'should be undefined if all table cell have the same "height" property value which is the default value', () => { + setData( model, modelTable( [ + [ + { contents: '00', isSelected: true, height: '30px' }, + { contents: '01', isSelected: true, height: '30px' } + ], + [ + '10', + { contents: '11', isSelected: true, height: '30px' } + ] + ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + } ); + + describe( 'execute()', () => { + describe( 'collapsed selection', () => { + it( 'should remove height from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ { height: '100px', contents: '[]foo' } ] ] ) ); + + command.execute( { value: '30px' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should remove height from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ '[foo]' ] ] ) ); + + command.execute( { value: '30px' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'multi-cell selection', () => { + it( 'should remove "height" from selected table cells if the default value is passed', () => { + setData( model, modelTable( [ + [ { contents: '00', isSelected: true, height: '100px' }, '01' ], + [ '10', { contents: '11', isSelected: true, height: '100px' } ] + ] ) ); + + command.execute( { value: '30px' } ); + + assertEqualMarkup( editor.getData(), viewTable( [ + [ '00', '01' ], + [ '10', '11' ] + ] ) ); + } ); + } ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js index 46107e7e9c8..5f38747171d 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js @@ -15,7 +15,7 @@ import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils' describe( 'table cell properties', () => { describe( 'commands', () => { - describe( 'TableCellHorizontalAlignmentCommand', () => { + describe( 'TableCellHorizontalAlignmentCommand: empty default value', () => { let editor, model, command; beforeEach( async () => { @@ -24,7 +24,7 @@ describe( 'table cell properties', () => { } ); model = editor.model; - command = new TableCellHorizontalAlignmentCommand( editor ); + command = new TableCellHorizontalAlignmentCommand( editor, '' ); } ); afterEach( () => { @@ -255,5 +255,100 @@ describe( 'table cell properties', () => { } ); } ); } ); + + describe( 'TableCellHorizontalAlignmentCommand: non-0empty default value', () => { + let editor, model, command; + + beforeEach( async () => { + editor = await ModelTestEditor.create( { + plugins: [ Paragraph, TableCellPropertiesEditing ] + } ); + + model = editor.model; + command = new TableCellHorizontalAlignmentCommand( editor, 'left' ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + describe( 'value', () => { + describe( 'collapsed selection', () => { + it( 'should be undefined if selected table cell has the default value', () => { + setData( model, modelTable( [ [ { horizontalAlignment: 'left', contents: '[]foo' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should be undefined is selection contains the default value', () => { + setData( model, modelTable( [ [ { horizontalAlignment: 'left', contents: 'f[o]o' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'multi-cell selection', () => { + it( + 'should be set if all table cells have the same "horizontalAlignment" property value which is the default value', + () => { + setData( model, modelTable( [ + [ + { contents: '00', isSelected: true, horizontalAlignment: 'left' }, + { contents: '01', isSelected: true, horizontalAlignment: 'left' } + ], + [ + '10', + { contents: '11', isSelected: true, horizontalAlignment: 'left' } + ] + ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + } ); + + describe( 'execute()', () => { + describe( 'collapsed selection', () => { + it( 'should remove horizontalAlignment from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ { horizontalAlignment: 'center', contents: '[]foo' } ] ] ) ); + + command.execute( { value: 'left' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should remove horizontalAlignment from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ '[foo]' ] ] ) ); + + command.execute( { value: 'left' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'multi-cell selection', () => { + it( + 'should remove the "horizontalAlignment" attribute from selected table cells if the default value is passed', + () => { + setData( model, modelTable( [ + [ { contents: '00', isSelected: true, horizontalAlignment: 'right' }, '01' ], + [ '10', { contents: '11', isSelected: true, horizontalAlignment: 'right' } ] + ] ) ); + + command.execute( { value: 'left' } ); + + assertEqualMarkup( editor.getData(), viewTable( [ + [ '00', '01' ], + [ '10', '11' ] + ] ) ); + } + ); + } ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellpaddingcommand.js b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellpaddingcommand.js index 80d3de4317a..3bc87366eec 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellpaddingcommand.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellpaddingcommand.js @@ -15,7 +15,7 @@ import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils' describe( 'table cell properties', () => { describe( 'commands', () => { - describe( 'TableCellPaddingCommand', () => { + describe( 'TableCellPaddingCommand: empty default value', () => { let editor, model, command; beforeEach( async () => { @@ -336,5 +336,107 @@ describe( 'table cell properties', () => { } ); } ); } ); + + describe( 'TableCellPaddingCommand: non-default value', () => { + let editor, model, command; + + beforeEach( async () => { + editor = await ModelTestEditor.create( { + plugins: [ Paragraph, TableCellPropertiesEditing ] + } ); + + model = editor.model; + command = new TableCellPaddingCommand( editor, '10px' ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + describe( 'value', () => { + describe( 'collapsed selection', () => { + it( 'should be undefined if selected table cell has the default padding property (single string)', () => { + setData( model, modelTable( [ [ { padding: '10px', contents: '[]foo' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + + it( 'should be undefined if selected table cell has the default property object with same values', () => { + setTableCellWithObjectAttributes( model, { + padding: { + top: '10px', + right: '10px', + bottom: '10px', + left: '10px' + } + }, '[]foo' ); + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should be undefined is selection contains the default value', () => { + setData( model, modelTable( [ [ { padding: '10px', contents: 'f[o]o' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'multi-cell selection', () => { + it( 'should be undefined if all table cells have the same "padding" property value which is the default value', () => { + setData( model, modelTable( [ + [ + { contents: '00', isSelected: true, padding: '10px' }, + { contents: '01', isSelected: true, padding: '10px' } + ], + [ + '10', + { contents: '11', isSelected: true, padding: '10px' } + ] + ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + } ); + + describe( 'execute()', () => { + describe( 'collapsed selection', () => { + it( 'should remove padding from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ { padding: '2em', contents: '[]foo' } ] ] ) ); + + command.execute( { value: '10px' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should remove padding from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ '[foo]' ] ] ) ); + + command.execute( { value: '10px' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'multi-cell selection', () => { + it( 'should remove "padding" from selected table cells if the default value is passed', () => { + setData( model, modelTable( [ + [ { contents: '00', isSelected: true, padding: '25px' }, '01' ], + [ '10', { contents: '11', isSelected: true, padding: '25px' } ] + ] ) ); + + command.execute( { value: '10px' } ); + + assertEqualMarkup( editor.getData(), viewTable( [ + [ '00', '01' ], + [ '10', '11' ] + ] ) ); + } ); + } ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellverticalalignmentcommand.js b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellverticalalignmentcommand.js index 4ac2b173659..aff46ee3f5e 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellverticalalignmentcommand.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellverticalalignmentcommand.js @@ -15,7 +15,7 @@ import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils' describe( 'table cell properties', () => { describe( 'commands', () => { - describe( 'TableCellVerticalAlignmentCommand', () => { + describe( 'TableCellVerticalAlignmentCommand: empty default value', () => { let editor, model, command; beforeEach( async () => { @@ -24,7 +24,7 @@ describe( 'table cell properties', () => { } ); model = editor.model; - command = new TableCellVerticalAlignmentCommand( editor ); + command = new TableCellVerticalAlignmentCommand( editor, '' ); } ); afterEach( () => { @@ -255,5 +255,99 @@ describe( 'table cell properties', () => { } ); } ); } ); + + describe( 'TableCellVerticalAlignmentCommand: non-empty default value', () => { + let editor, model, command; + + beforeEach( async () => { + editor = await ModelTestEditor.create( { + plugins: [ Paragraph, TableCellPropertiesEditing ] + } ); + + model = editor.model; + command = new TableCellVerticalAlignmentCommand( editor, 'bottom' ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + describe( 'value', () => { + describe( 'collapsed selection', () => { + it( 'should be undefined if selected table cell has the default verticalAlignment property', () => { + setData( model, modelTable( [ [ { verticalAlignment: 'bottom', contents: '[]foo' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should be undefined is selection contains the default value', () => { + setData( model, modelTable( [ [ { verticalAlignment: 'bottom', contents: 'f[o]o' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'multi-cell selection', () => { + it( + 'should be undefined if all table cells have the same "verticalAlignment" property ' + + 'value which is the default value', + () => { + setData( model, modelTable( [ + [ + { contents: '00', isSelected: true, verticalAlignment: 'bottom' }, + { contents: '01', isSelected: true, verticalAlignment: 'bottom' } + ], + [ + '10', + { contents: '11', isSelected: true, verticalAlignment: 'bottom' } + ] + ] ) ); + + expect( command.value ).to.be.undefined; + } + ); + } ); + } ); + + describe( 'execute()', () => { + describe( 'collapsed selection', () => { + it( 'should remove verticalAlignment from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ { verticalAlignment: 'bottom', contents: '[]foo' } ] ] ) ); + + command.execute( { value: 'bottom' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should remove verticalAlignment from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ '[foo]' ] ] ) ); + + command.execute( { value: 'bottom' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'multi-cell selection', () => { + it( 'should remove "verticalAlignment" from selected table cells if the default value is passed', () => { + setData( model, modelTable( [ + [ { contents: '00', isSelected: true, verticalAlignment: 'top' }, '01' ], + [ '10', { contents: '11', isSelected: true, verticalAlignment: 'top' } ] + ] ) ); + + command.execute( { value: 'bottom' } ); + + assertEqualMarkup( editor.getData(), viewTable( [ + [ '00', '01' ], + [ '10', '11' ] + ] ) ); + } ); + } ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellwidthcommand.js b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellwidthcommand.js index 38e8f5ad87d..5ebea02c395 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellwidthcommand.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellwidthcommand.js @@ -15,7 +15,7 @@ import { assertEqualMarkup } from '@ckeditor/ckeditor5-utils/tests/_utils/utils' describe( 'table cell properties', () => { describe( 'commands', () => { - describe( 'TableCellWidthCommand', () => { + describe( 'TableCellWidthCommand: empty default value', () => { let editor, model, command; beforeEach( async () => { @@ -24,7 +24,7 @@ describe( 'table cell properties', () => { } ); model = editor.model; - command = new TableCellWidthCommand( editor ); + command = new TableCellWidthCommand( editor, '' ); } ); afterEach( () => { @@ -311,5 +311,95 @@ describe( 'table cell properties', () => { } ); } ); } ); + + describe( 'TableCellWidthCommand: non-empty default value', () => { + let editor, model, command; + + beforeEach( async () => { + editor = await ModelTestEditor.create( { + plugins: [ Paragraph, TableCellPropertiesEditing ] + } ); + + model = editor.model; + command = new TableCellWidthCommand( editor, '50px' ); + } ); + + afterEach( () => { + return editor.destroy(); + } ); + + describe( 'value', () => { + describe( 'collapsed selection', () => { + it( 'should be undefined if selected table cell has the default width property', () => { + setData( model, modelTable( [ [ { width: '50px', contents: '[]foo' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should be undefined is selection contains the default value', () => { + setData( model, modelTable( [ [ { width: '50px', contents: 'f[o]o' } ] ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + + describe( 'multi-cell selection', () => { + it( 'should be undefined if all table cells have the same "width" property value which is the default value', () => { + setData( model, modelTable( [ + [ + { contents: '00', isSelected: true, width: '50px' }, + { contents: '01', isSelected: true, width: '50px' } + ], + [ + '10', + { contents: '11', isSelected: true, width: '50px' } + ] + ] ) ); + + expect( command.value ).to.be.undefined; + } ); + } ); + } ); + + describe( 'execute()', () => { + describe( 'collapsed selection', () => { + it( 'should remove width from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ { width: '100px', contents: '[]foo' } ] ] ) ); + + command.execute( { value: '50px' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'non-collapsed selection', () => { + it( 'should remove width from a selected table cell if the default value is passed', () => { + setData( model, modelTable( [ [ '[foo]' ] ] ) ); + + command.execute( { value: '50px' } ); + + assertTableCellStyle( editor, '' ); + } ); + } ); + + describe( 'multi-cell selection', () => { + it( 'should remove "width" from selected table cells if the default value is passed', () => { + setData( model, modelTable( [ + [ { contents: '00', isSelected: true, width: '25px' }, '01' ], + [ '10', { contents: '11', isSelected: true, width: '25px' } ] + ] ) ); + + command.execute( { value: '50px' } ); + + assertEqualMarkup( editor.getData(), viewTable( [ + [ '00', '01' ], + [ '10', '11' ] + ] ) ); + } ); + } ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js index e3e05a5e34b..3ca8479a2f6 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesediting.js @@ -43,6 +43,14 @@ describe( 'table cell properties', () => { expect( TableCellPropertiesEditing.pluginName ).to.equal( 'TableCellPropertiesEditing' ); } ); + it( 'should define table.tableCellProperties config', () => { + const config = editor.config.get( 'table.tableCellProperties' ); + + expect( config ).to.be.an( 'object' ); + expect( config ).to.have.property( 'defaultProperties' ); + expect( config.defaultProperties ).to.deep.equal( {} ); + } ); + it( 'adds tableCellBorderColor command', () => { expect( editor.commands.get( 'tableCellBorderColor' ) ).to.be.instanceOf( TableCellBorderColorCommand ); } ); @@ -669,7 +677,7 @@ describe( 'table cell properties', () => { } ); describe( 'upcast conversion', () => { - it( 'should not upcast text-align:left style', () => { + it( 'should upcast text-align:left style (due to the default value of the property)', () => { editor.setData( '
parent:00' + + '' + '
child:00
' + '
foo
' ); const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); @@ -683,7 +691,7 @@ describe( 'table cell properties', () => { expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.equal( 'right' ); } ); - it( 'should upcast text-align:center style', () => { + it( 'should not upcast text-align:center style', () => { editor.setData( '
foo
' ); const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); @@ -697,6 +705,36 @@ describe( 'table cell properties', () => { expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.equal( 'justify' ); } ); + describe( 'the [align] attribute', () => { + it( 'should not upcast the align=left attribute (due to the default value of the property)', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.be.undefined; + } ); + + it( 'should upcast the align=right attribute', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.equal( 'right' ); + } ); + + it( 'should upcast the align=center attribute', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.equal( 'center' ); + } ); + + it( 'should upcast the align=justify attribute', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.equal( 'justify' ); + } ); + } ); + describe( 'for RTL content language', () => { let editor, model; @@ -713,7 +751,7 @@ describe( 'table cell properties', () => { await editor.destroy(); } ); - it( 'should not upcast text-align:right style', () => { + it( 'should not upcast text-align:right style (due to the default value of the property)', () => { editor.setData( '
foo
' ); const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); @@ -727,7 +765,7 @@ describe( 'table cell properties', () => { expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.equal( 'left' ); } ); - it( 'should upcast text-align:center style', () => { + it( 'should not upcast text-align:center style', () => { editor.setData( '
foo
' ); const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); @@ -740,6 +778,36 @@ describe( 'table cell properties', () => { expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.equal( 'justify' ); } ); + + describe( 'the [align] attribute', () => { + it( 'should upcast the align=left attribute', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.equal( 'left' ); + } ); + + it( 'should not upcast the align=right attribute (due to the default value of the property)', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.be.undefined; + } ); + + it( 'should upcast the align=center attribute', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.equal( 'center' ); + } ); + + it( 'should upcast the align=justify attribute', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.equal( 'justify' ); + } ); + } ); } ); } ); @@ -780,10 +848,10 @@ describe( 'table cell properties', () => { assertTableCellStyle( editor, '' ); } ); - it( 'should not downcast horizontalAlignment=left', () => { + it( 'should downcast horizontalAlignment=left', () => { model.change( writer => writer.setAttribute( 'horizontalAlignment', 'left', tableCell ) ); - assertTableCellStyle( editor ); + assertTableCellStyle( editor, 'text-align:left;' ); } ); it( 'should downcast horizontalAlignment=right', () => { @@ -856,7 +924,7 @@ describe( 'table cell properties', () => { it( 'should not downcast horizontalAlignment=right', () => { model.change( writer => writer.setAttribute( 'horizontalAlignment', 'right', tableCell ) ); - assertTableCellStyle( editor ); + assertTableCellStyle( editor, 'text-align:right;' ); } ); it( 'should downcast horizontalAlignment=left', () => { @@ -900,7 +968,7 @@ describe( 'table cell properties', () => { expect( tableCell.getAttribute( 'verticalAlignment' ) ).to.equal( 'bottom' ); } ); - it( 'should not upcast "middle" vertical-align', () => { + it( 'should not upcast "middle" vertical-align (due to the default value of the property)', () => { editor.setData( '
foo
' ); const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); @@ -921,7 +989,7 @@ describe( 'table cell properties', () => { expect( tableCell.getAttribute( 'verticalAlignment' ) ).to.equal( 'bottom' ); } ); - it( 'should not upcast "middle" valign attribute', () => { + it( 'should not upcast "middle" valign attribute (due to the default value of the property)', () => { editor.setData( '
foo
' ); const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); @@ -1228,5 +1296,232 @@ describe( 'table cell properties', () => { } ); } ); } ); + + // When default properties are specified, we do not want to put them into the model values if they are equal to the defaults. + describe( 'default table cell properties', () => { + let editor, model; + + beforeEach( () => { + return VirtualTestEditor + .create( { + plugins: [ TableCellPropertiesEditing, Paragraph, TableEditing ], + table: { + tableCellProperties: { + defaultProperties: { + horizontalAlignment: 'left', + verticalAlignment: 'bottom', + borderStyle: 'dashed', + borderColor: '#ff0', + borderWidth: '2px', + backgroundColor: '#00f', + width: '250px', + height: '150px', + padding: '10px' + } + } + } + } ) + .then( newEditor => { + editor = newEditor; + + model = editor.model; + } ); + } ); + + afterEach( () => { + editor.destroy(); + } ); + + describe( 'border', () => { + it( 'should not upcast the default `border` values from ', () => { + editor.setData( '
foo
' ); + + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'borderColor' ) ).to.be.undefined; + expect( tableCell.getAttribute( 'borderStyle' ) ).to.be.undefined; + expect( tableCell.getAttribute( 'borderWidth' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default `border` values from ', () => { + editor.setData( '
foo
' ); + + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'borderColor' ) ).to.be.undefined; + expect( tableCell.getAttribute( 'borderStyle' ) ).to.be.undefined; + expect( tableCell.getAttribute( 'borderWidth' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default `border-color` value from ', () => { + editor.setData( '
foo
' ); + + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'borderColor' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default `border-style` value from ', () => { + editor.setData( '
foo
' ); + + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'borderStyle' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default `border-width` value from ', () => { + editor.setData( '
foo
' ); + + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'borderWidth' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default `border-width` value from ', () => { + editor.setData( '
foo
' ); + + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'borderWidth' ) ).to.be.undefined; + } ); + } ); + + describe( 'background color', () => { + it( 'should not upcast the default `background-color` value from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'backgroundColor' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default `background` value from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'backgroundColor' ) ).to.be.undefined; + } ); + it( 'should not upcast the default `background-color` value from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'backgroundColor' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default `background` value from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'backgroundColor' ) ).to.be.undefined; + } ); + } ); + + describe( 'width', () => { + it( 'should upcast the default `width` value from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'width' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default `width` value from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'width' ) ).to.be.undefined; + } ); + } ); + + describe( 'height', () => { + it( 'should not upcast the default `height` value from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'height' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default `height` value from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'height' ) ).to.be.undefined; + } ); + } ); + + describe( 'padding', () => { + it( 'should not upcast the default `padding` value from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'padding' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default `padding` value from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'padding' ) ).to.be.undefined; + } ); + } ); + + describe( 'horizontalAlignment', () => { + it( 'should not upcast the default value from the style attribute (text-align:left) from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default value from the style attribute (text-align:left) from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default value from the align attribute (left) from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default value from the align attribute (left) from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'horizontalAlignment' ) ).to.be.undefined; + } ); + } ); + + describe( 'verticalAlignment', () => { + it( 'should not upcast the default value from the style attribute (vertical-align:bottom;) from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'verticalAlignment' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default value from the style attribute (vertical-align:bottom;) from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'verticalAlignment' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default value from the valign attribute (bottom) from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'verticalAlignment' ) ).to.be.undefined; + } ); + + it( 'should not upcast the default value from the valign attribute (bottom) from ', () => { + editor.setData( '
foo
' ); + const tableCell = model.document.getRoot().getNodeByPath( [ 0, 0, 0 ] ); + + expect( tableCell.getAttribute( 'verticalAlignment' ) ).to.be.undefined; + } ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js index f5538646802..31003afa570 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/tablecellpropertiesui.js @@ -72,10 +72,12 @@ describe( 'table cell properties', () => { describe( 'constructor()', () => { it( 'should define table.tableCellProperties config', () => { - expect( editor.config.get( 'table.tableCellProperties' ) ).to.deep.equal( { - borderColors: defaultColors, - backgroundColors: defaultColors - } ); + expect( editor.config.get( 'table.tableCellProperties' ) ).to.be.an( 'object' ); + + expect( editor.config.get( 'table.tableCellProperties' ) ).to.have.property( 'borderColors' ); + expect( editor.config.get( 'table.tableCellProperties.borderColors' ) ).to.deep.equal( defaultColors ); + expect( editor.config.get( 'table.tableCellProperties' ) ).to.have.property( 'backgroundColors' ); + expect( editor.config.get( 'table.tableCellProperties.backgroundColors' ) ).to.deep.equal( defaultColors ); } ); } ); @@ -622,15 +624,15 @@ describe( 'table cell properties', () => { expect( contextualBalloon.visibleView ).to.equal( tableCellPropertiesView ); expect( tableCellPropertiesView ).to.include( { - borderStyle: '', + borderStyle: 'none', borderColor: '', borderWidth: '', width: '', height: '', padding: '', backgroundColor: '', - horizontalAlignment: '', - verticalAlignment: '' + horizontalAlignment: 'left', + verticalAlignment: 'middle' } ); } ); } ); @@ -675,5 +677,130 @@ describe( 'table cell properties', () => { sinon.assert.calledOnce( spy ); } ); } ); + + describe( 'default table properties', () => { + let editor, editorElement, contextualBalloon, + tableCellPropertiesUI, tableCellPropertiesView, tableCellPropertiesButton; + + testUtils.createSinonSandbox(); + + beforeEach( () => { + editorElement = document.createElement( 'div' ); + document.body.appendChild( editorElement ); + + return ClassicTestEditor + .create( editorElement, { + plugins: [ Table, TableCellPropertiesEditing, TableCellPropertiesUI, Paragraph, Undo ], + initialData: '
foo

bar

', + table: { + tableCellProperties: { + defaultProperties: { + horizontalAlignment: 'center', + verticalAlignment: 'bottom', + borderStyle: 'dashed', + borderColor: '#ff0', + borderWidth: '2px', + backgroundColor: '#00f', + width: '250px', + height: '150px', + padding: '10px' + } + } + } + } ) + .then( newEditor => { + editor = newEditor; + + tableCellPropertiesUI = editor.plugins.get( TableCellPropertiesUI ); + tableCellPropertiesButton = editor.ui.componentFactory.create( 'tableCellProperties' ); + contextualBalloon = editor.plugins.get( ContextualBalloon ); + tableCellPropertiesView = tableCellPropertiesUI.view; + + // There is no point to execute BalloonPanelView attachTo and pin methods so lets override it. + testUtils.sinon.stub( contextualBalloon.view, 'attachTo' ).returns( {} ); + testUtils.sinon.stub( contextualBalloon.view, 'pin' ).returns( {} ); + } ); + } ); + + afterEach( () => { + editorElement.remove(); + + return editor.destroy(); + } ); + + describe( 'init()', () => { + describe( '#view', () => { + it( 'should get the default table cell properties configurations', () => { + expect( tableCellPropertiesView.options.defaultTableCellProperties ).to.deep.equal( { + horizontalAlignment: 'center', + verticalAlignment: 'bottom', + borderStyle: 'dashed', + borderColor: '#ff0', + borderWidth: '2px', + backgroundColor: '#00f', + width: '250px', + height: '150px', + padding: '10px' + } ); + } ); + } ); + } ); + + describe( 'Showing the #view', () => { + beforeEach( () => { + editor.model.change( writer => { + writer.setSelection( editor.model.document.getRoot().getChild( 0 ).getChild( 0 ).getChild( 0 ), 0 ); + } ); + } ); + + describe( 'initial data', () => { + it( 'should use default values when command has no value', () => { + editor.commands.get( 'tableCellBorderStyle' ).value = null; + editor.commands.get( 'tableCellBorderColor' ).value = null; + editor.commands.get( 'tableCellBorderWidth' ).value = null; + editor.commands.get( 'tableCellBackgroundColor' ).value = null; + editor.commands.get( 'tableCellWidth' ).value = null; + editor.commands.get( 'tableCellHeight' ).value = null; + editor.commands.get( 'tableCellPadding' ).value = null; + editor.commands.get( 'tableCellHorizontalAlignment' ).value = null; + editor.commands.get( 'tableCellVerticalAlignment' ).value = null; + + tableCellPropertiesButton.fire( 'execute' ); + + expect( contextualBalloon.visibleView ).to.equal( tableCellPropertiesView ); + expect( tableCellPropertiesView ).to.include( { + borderStyle: 'dashed', + borderColor: '#ff0', + borderWidth: '2px', + backgroundColor: '#00f', + width: '250px', + height: '150px', + padding: '10px', + horizontalAlignment: 'center', + verticalAlignment: 'bottom' + } ); + } ); + + it( 'should not set `borderColor` and `borderWidth` attributes if borderStyle="none"', () => { + editor.commands.get( 'tableCellBorderStyle' ).value = 'none'; + + tableCellPropertiesButton.fire( 'execute' ); + + expect( contextualBalloon.visibleView ).to.equal( tableCellPropertiesView ); + expect( tableCellPropertiesView ).to.include( { + borderStyle: 'none', + borderColor: '', + borderWidth: '', + backgroundColor: '#00f', + width: '250px', + height: '150px', + padding: '10px', + horizontalAlignment: 'center', + verticalAlignment: 'bottom' + } ); + } ); + } ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-table/tests/tablecellproperties/ui/tablecellpropertiesview.js b/packages/ckeditor5-table/tests/tablecellproperties/ui/tablecellpropertiesview.js index 2196fdb8294..8deb652117c 100644 --- a/packages/ckeditor5-table/tests/tablecellproperties/ui/tablecellpropertiesview.js +++ b/packages/ckeditor5-table/tests/tablecellproperties/ui/tablecellpropertiesview.js @@ -37,7 +37,18 @@ const VIEW_OPTIONS = { label: 'Green', hasBorder: false } - ] + ], + defaultTableCellProperties: { + borderColor: '', + borderStyle: 'none', + borderWidth: '', + horizontalAlignment: 'left', + verticalAlignment: 'middle', + width: '', + height: '', + padding: '', + backgroundColor: '' + } }; describe( 'table cell properties', () => { @@ -178,7 +189,7 @@ describe( 'table cell properties', () => { view.borderWidth = '1px'; view.borderColor = 'red'; - view.borderStyle = ''; + view.borderStyle = 'none'; expect( view.borderColor ).to.equal( '' ); expect( view.borderWidth ).to.equal( '' ); @@ -207,7 +218,7 @@ describe( 'table cell properties', () => { } ); it( 'should be enabled only when #borderStyle is different than "none"', () => { - view.borderStyle = ''; + view.borderStyle = 'none'; expect( labeledInput.isEnabled ).to.be.false; view.borderStyle = 'dotted'; @@ -265,7 +276,7 @@ describe( 'table cell properties', () => { } ); it( 'should be enabled only when #borderStyle is different than "none"', () => { - view.borderStyle = ''; + view.borderStyle = 'none'; expect( labeledInput.isEnabled ).to.be.false; view.borderStyle = 'dotted'; @@ -529,7 +540,7 @@ describe( 'table cell properties', () => { expect( toolbar.items.last.isOn ).to.be.true; toolbar.items.first.fire( 'execute' ); - expect( view.horizontalAlignment ).to.equal( '' ); + expect( view.horizontalAlignment ).to.equal( 'left' ); expect( toolbar.items.last.isOn ).to.be.false; expect( toolbar.items.first.isOn ).to.be.true; } ); diff --git a/packages/ckeditor5-table/tests/utils/table-properties.js b/packages/ckeditor5-table/tests/utils/table-properties.js index 61858c62f45..bef3d54ea83 100644 --- a/packages/ckeditor5-table/tests/utils/table-properties.js +++ b/packages/ckeditor5-table/tests/utils/table-properties.js @@ -12,7 +12,6 @@ describe( 'table utils', () => { const editorConfig = {}; expect( getNormalizedDefaultProperties( editorConfig ) ).to.deep.equal( { - alignment: 'center', borderStyle: 'none', borderWidth: '', borderColor: '', @@ -24,14 +23,12 @@ describe( 'table utils', () => { it( 'should return an object with provided configuration and added missing properties', () => { const editorConfig = { - alignment: 'left', borderStyle: 'dashed', width: '500px', height: '300px' }; expect( getNormalizedDefaultProperties( editorConfig ) ).to.deep.equal( { - alignment: 'left', backgroundColor: '', borderColor: '', borderStyle: 'dashed', @@ -40,6 +37,141 @@ describe( 'table utils', () => { width: '500px' } ); } ); + + it( 'should add the alignment property', () => { + const editorConfig = {}; + + expect( getNormalizedDefaultProperties( editorConfig, { includeAlignmentProperty: true } ) ).to.deep.equal( { + alignment: 'center', + borderStyle: 'none', + borderWidth: '', + borderColor: '', + backgroundColor: '', + width: '', + height: '' + } ); + } ); + + it( 'should not overwrite the alignment property', () => { + const editorConfig = { + alignment: 'left' + }; + + expect( getNormalizedDefaultProperties( editorConfig, { includeAlignmentProperty: true } ) ).to.deep.equal( { + alignment: 'left', + borderStyle: 'none', + borderWidth: '', + borderColor: '', + backgroundColor: '', + width: '', + height: '' + } ); + } ); + + it( 'should add the horizontalAlignment property (left-to-right)', () => { + const editorConfig = {}; + + expect( getNormalizedDefaultProperties( editorConfig, { includeHorizontalAlignmentProperty: true } ) ).to.deep.equal( { + horizontalAlignment: 'left', + borderStyle: 'none', + borderWidth: '', + borderColor: '', + backgroundColor: '', + width: '', + height: '' + } ); + } ); + + it( 'should add the horizontalAlignment property (right-to-left)', () => { + const editorConfig = {}; + const options = { includeHorizontalAlignmentProperty: true, isRightToLeftContent: true }; + + expect( getNormalizedDefaultProperties( editorConfig, options ) ).to.deep.equal( { + horizontalAlignment: 'right', + borderStyle: 'none', + borderWidth: '', + borderColor: '', + backgroundColor: '', + width: '', + height: '' + } ); + } ); + + it( 'should not overwrite the horizontalAlignment property', () => { + const editorConfig = { + horizontalAlignment: 'center' + }; + + expect( getNormalizedDefaultProperties( editorConfig, { includeHorizontalAlignmentProperty: true } ) ).to.deep.equal( { + horizontalAlignment: 'center', + borderStyle: 'none', + borderWidth: '', + borderColor: '', + backgroundColor: '', + width: '', + height: '' + } ); + } ); + + it( 'should add the verticalAlignment property', () => { + const editorConfig = {}; + + expect( getNormalizedDefaultProperties( editorConfig, { includeVerticalAlignmentProperty: true } ) ).to.deep.equal( { + verticalAlignment: 'middle', + borderStyle: 'none', + borderWidth: '', + borderColor: '', + backgroundColor: '', + width: '', + height: '' + } ); + } ); + + it( 'should not overwrite the verticalAlignment property', () => { + const editorConfig = { + verticalAlignment: 'top' + }; + + expect( getNormalizedDefaultProperties( editorConfig, { includeVerticalAlignmentProperty: true } ) ).to.deep.equal( { + verticalAlignment: 'top', + borderStyle: 'none', + borderWidth: '', + borderColor: '', + backgroundColor: '', + width: '', + height: '' + } ); + } ); + + it( 'should add the alignment padding', () => { + const editorConfig = {}; + + expect( getNormalizedDefaultProperties( editorConfig, { includePaddingProperty: true } ) ).to.deep.equal( { + padding: '', + borderStyle: 'none', + borderWidth: '', + borderColor: '', + backgroundColor: '', + width: '', + height: '' + } ); + } ); + + it( 'should not overwrite the alignment padding', () => { + const editorConfig = { + padding: '10px' + }; + + expect( getNormalizedDefaultProperties( editorConfig, { includePaddingProperty: true } ) ).to.deep.equal( { + padding: '10px', + borderStyle: 'none', + borderWidth: '', + borderColor: '', + backgroundColor: '', + width: '', + height: '' + } ); + } ); } ); } ); } );