tablepropertiesediting.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /**
  2. * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. /**
  6. * @module table/tableproperties/tablepropertiesediting
  7. */
  8. import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
  9. import { addBorderRules } from '@ckeditor/ckeditor5-engine/src/view/styles/border';
  10. import { addBackgroundRules } from '@ckeditor/ckeditor5-engine/src/view/styles/background';
  11. import TableEditing from './../tableediting';
  12. import { downcastTableAttribute, upcastStyleToAttribute, upcastBorderStyles } from './../converters/tableproperties';
  13. import { defaultColors } from '../ui/utils';
  14. import TableBackgroundColorCommand from './commands/tablebackgroundcolorcommand';
  15. import TableBorderColorCommand from './commands/tablebordercolorcommand';
  16. import TableBorderStyleCommand from './commands/tableborderstylecommand';
  17. import TableBorderWidthCommand from './commands/tableborderwidthcommand';
  18. import TableWidthCommand from './commands/tablewidthcommand';
  19. import TableHeightCommand from './commands/tableheightcommand';
  20. import TableAlignmentCommand from './commands/tablealignmentcommand';
  21. // RegExp used for matching margin style in converters.
  22. const MARGIN_REG_EXP = /^(auto|0(%|[a-z]{2,4})?)$/;
  23. const ALIGN_VALUES_REG_EXP = /^(left|right|center)$/;
  24. /**
  25. * The table properties editing feature.
  26. *
  27. * Introduces table's model attributes and their conversion:
  28. *
  29. * - border: `borderStyle`, `borderColor` and `borderWidth`
  30. * - background color: `backgroundColor`
  31. * - horizontal alignment: `alignment`
  32. * - width & height: `width` & `height`
  33. *
  34. * It also registers commands used to manipulate the above attributes:
  35. *
  36. * - border: `'tableBorderStyle'`, `'tableBorderColor'` and `'tableBorderWidth'` commands
  37. * - background color: `'tableBackgroundColor'`
  38. * - horizontal alignment: `'tableAlignment'`
  39. * - width & height: `'tableWidth'` & `'tableHeight'`
  40. *
  41. * @extends module:core/plugin~Plugin
  42. */
  43. export default class TablePropertiesEditing extends Plugin {
  44. /**
  45. * @inheritDoc
  46. */
  47. static get pluginName() {
  48. return 'TablePropertiesEditing';
  49. }
  50. /**
  51. * @inheritDoc
  52. */
  53. static get requires() {
  54. return [ TableEditing ];
  55. }
  56. /**
  57. * @inheritDoc
  58. */
  59. constructor( editor ) {
  60. super( editor );
  61. editor.config.define( 'table.tableProperties', {
  62. border: {
  63. colors: defaultColors
  64. },
  65. backgroundColors: defaultColors
  66. } );
  67. }
  68. /**
  69. * @inheritDoc
  70. */
  71. init() {
  72. const editor = this.editor;
  73. const schema = editor.model.schema;
  74. const conversion = editor.conversion;
  75. const viewDoc = editor.editing.view.document;
  76. viewDoc.addStyleProcessorRules( addBorderRules );
  77. enableBorderProperties( schema, conversion );
  78. editor.commands.add( 'tableBorderColor', new TableBorderColorCommand( editor ) );
  79. editor.commands.add( 'tableBorderStyle', new TableBorderStyleCommand( editor ) );
  80. editor.commands.add( 'tableBorderWidth', new TableBorderWidthCommand( editor ) );
  81. enableAlignmentProperty( schema, conversion );
  82. editor.commands.add( 'tableAlignment', new TableAlignmentCommand( editor ) );
  83. enableProperty( schema, conversion, 'width', 'width' );
  84. editor.commands.add( 'tableWidth', new TableWidthCommand( editor ) );
  85. enableProperty( schema, conversion, 'height', 'height' );
  86. editor.commands.add( 'tableHeight', new TableHeightCommand( editor ) );
  87. viewDoc.addStyleProcessorRules( addBackgroundRules );
  88. enableProperty( schema, conversion, 'backgroundColor', 'background-color' );
  89. editor.commands.add( 'tableBackgroundColor', new TableBackgroundColorCommand( editor ) );
  90. }
  91. }
  92. // Enables `'borderStyle'`, `'borderColor'` and `'borderWidth'` attributes for table.
  93. //
  94. // @param {module:engine/model/schema~Schema} schema
  95. // @param {module:engine/conversion/conversion~Conversion} conversion
  96. function enableBorderProperties( schema, conversion ) {
  97. schema.extend( 'table', {
  98. allowAttributes: [ 'borderWidth', 'borderColor', 'borderStyle' ]
  99. } );
  100. upcastBorderStyles( conversion, 'table' );
  101. downcastTableAttribute( conversion, 'borderColor', 'border-color' );
  102. downcastTableAttribute( conversion, 'borderStyle', 'border-style' );
  103. downcastTableAttribute( conversion, 'borderWidth', 'border-width' );
  104. }
  105. // Enables the `'alignment'` attribute for table.
  106. //
  107. // @param {module:engine/model/schema~Schema} schema
  108. // @param {module:engine/conversion/conversion~Conversion} conversion
  109. function enableAlignmentProperty( schema, conversion ) {
  110. schema.extend( 'table', {
  111. allowAttributes: [ 'alignment' ]
  112. } );
  113. conversion.for( 'upcast' )
  114. .attributeToAttribute( {
  115. view: {
  116. styles: {
  117. 'margin-right': MARGIN_REG_EXP,
  118. 'margin-left': MARGIN_REG_EXP
  119. }
  120. },
  121. model: {
  122. name: 'table',
  123. key: 'alignment',
  124. value: viewElement => {
  125. // At this point we only have auto or 0 value (with a unit).
  126. if ( viewElement.getStyle( 'margin-right' ) != 'auto' ) {
  127. return 'right';
  128. }
  129. if ( viewElement.getStyle( 'margin-left' ) != 'auto' ) {
  130. return 'left';
  131. }
  132. return 'center';
  133. }
  134. }
  135. } )
  136. // Support for backwards compatibility and pasting from other sources.
  137. .attributeToAttribute( {
  138. view: {
  139. attributes: {
  140. align: ALIGN_VALUES_REG_EXP
  141. }
  142. },
  143. model: {
  144. name: 'table',
  145. key: 'alignment',
  146. value: viewElement => viewElement.getAttribute( 'align' )
  147. }
  148. } );
  149. conversion.for( 'downcast' ).add( dispatcher => dispatcher.on( 'attribute:alignment:table', ( evt, data, conversionApi ) => {
  150. const { item, attributeNewValue } = data;
  151. const { mapper, writer } = conversionApi;
  152. const table = [ ...mapper.toViewElement( item ).getChildren() ].find( child => child.is( 'table' ) );
  153. if ( !attributeNewValue ) {
  154. writer.removeStyle( 'margin-left', table );
  155. writer.removeStyle( 'margin-right', table );
  156. return;
  157. }
  158. const styles = {
  159. 'margin-right': 'auto',
  160. 'margin-left': 'auto'
  161. };
  162. if ( attributeNewValue == 'left' ) {
  163. styles[ 'margin-left' ] = '0';
  164. }
  165. if ( attributeNewValue == 'right' ) {
  166. styles[ 'margin-right' ] = '0';
  167. }
  168. writer.setStyle( styles, table );
  169. } ) );
  170. }
  171. // Enables conversion for an attribute for simple view-model mappings.
  172. //
  173. // @param {String} modelAttribute
  174. // @param {String} styleName
  175. // @param {module:engine/model/schema~Schema} schema
  176. // @param {module:engine/conversion/conversion~Conversion} conversion
  177. function enableProperty( schema, conversion, modelAttribute, styleName ) {
  178. schema.extend( 'table', {
  179. allowAttributes: [ modelAttribute ]
  180. } );
  181. upcastStyleToAttribute( conversion, 'table', modelAttribute, styleName );
  182. downcastTableAttribute( conversion, modelAttribute, styleName );
  183. }