@ckeditor/ckeditor5-table 32.0.0 → 34.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/LICENSE.md +2 -2
  2. package/README.md +2 -1
  3. package/build/table.js +2 -2
  4. package/build/translations/el.js +1 -0
  5. package/build/translations/en-au.js +1 -1
  6. package/build/translations/es.js +1 -1
  7. package/build/translations/hr.js +1 -1
  8. package/build/translations/lv.js +1 -1
  9. package/build/translations/sk.js +1 -1
  10. package/build/translations/ur.js +1 -0
  11. package/ckeditor5-metadata.json +19 -0
  12. package/lang/translations/el.po +261 -0
  13. package/lang/translations/en-au.po +3 -3
  14. package/lang/translations/es.po +32 -32
  15. package/lang/translations/hr.po +3 -3
  16. package/lang/translations/lv.po +40 -40
  17. package/lang/translations/sk.po +3 -3
  18. package/lang/translations/ur.po +261 -0
  19. package/package.json +26 -21
  20. package/src/commands/insertcolumncommand.js +4 -4
  21. package/src/commands/insertrowcommand.js +4 -4
  22. package/src/commands/inserttablecommand.js +1 -5
  23. package/src/commands/mergecellcommand.js +4 -5
  24. package/src/commands/mergecellscommand.js +5 -4
  25. package/src/commands/removecolumncommand.js +8 -7
  26. package/src/commands/removerowcommand.js +5 -6
  27. package/src/commands/selectcolumncommand.js +4 -4
  28. package/src/commands/selectrowcommand.js +5 -5
  29. package/src/commands/setheadercolumncommand.js +5 -4
  30. package/src/commands/setheaderrowcommand.js +7 -4
  31. package/src/commands/splitcellcommand.js +4 -4
  32. package/src/converters/downcast.js +76 -407
  33. package/src/converters/{table-cell-refresh-post-fixer.js → table-cell-refresh-handler.js} +8 -19
  34. package/src/converters/table-headings-refresh-handler.js +68 -0
  35. package/src/index.js +3 -0
  36. package/src/plaintableoutput.js +151 -0
  37. package/src/tablecellproperties/commands/tablecellpropertycommand.js +4 -3
  38. package/src/tableclipboard.js +18 -15
  39. package/src/tablecolumnresize/constants.js +32 -0
  40. package/src/tablecolumnresize/converters.js +126 -0
  41. package/src/tablecolumnresize/tablecolumnresizeediting.js +758 -0
  42. package/src/tablecolumnresize/utils.js +367 -0
  43. package/src/tablecolumnresize.js +36 -0
  44. package/src/tableediting.js +51 -32
  45. package/src/tablekeyboard.js +73 -70
  46. package/src/tablemouse.js +6 -4
  47. package/src/tableselection.js +9 -8
  48. package/src/tableutils.js +310 -0
  49. package/theme/table.css +1 -1
  50. package/theme/tablecolumnresize.css +59 -0
  51. package/src/converters/table-heading-rows-refresh-post-fixer.js +0 -72
  52. package/src/utils/selection.js +0 -276
@@ -0,0 +1,367 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+
6
+ /**
7
+ * @module table/tablecolumnresize/utils
8
+ */
9
+
10
+ /* istanbul ignore file */
11
+
12
+ import { global } from 'ckeditor5/src/utils';
13
+ import {
14
+ COLUMN_WIDTH_PRECISION,
15
+ COLUMN_MIN_WIDTH_AS_PERCENTAGE,
16
+ COLUMN_MIN_WIDTH_IN_PIXELS
17
+ } from './constants';
18
+
19
+ /**
20
+ * Collects all affected by the differ table model elements. The returned set may be empty.
21
+ *
22
+ * @param {Array.<module:engine/model/differ~DiffItem>} changes
23
+ * @param {module:engine/model/model~Model} model
24
+ * @returns {Set.<module:engine/model/element~Element>}
25
+ */
26
+ export function getAffectedTables( changes, model ) {
27
+ const tablesToProcess = new Set();
28
+
29
+ for ( const change of changes ) {
30
+ let referencePosition = null;
31
+
32
+ // Checks if the particular change from the differ is:
33
+ // - an insertion or removal of a table, a row or a cell,
34
+ // - an attribute change on a table, a row or a cell.
35
+ switch ( change.type ) {
36
+ case 'insert':
37
+ case 'remove':
38
+ referencePosition = [ 'table', 'tableRow', 'tableCell' ].includes( change.name ) ?
39
+ change.position :
40
+ null;
41
+
42
+ break;
43
+
44
+ case 'attribute':
45
+ if ( change.range.start.nodeAfter ) {
46
+ referencePosition = [ 'table', 'tableRow', 'tableCell' ].includes( change.range.start.nodeAfter.name ) ?
47
+ change.range.start :
48
+ null;
49
+ }
50
+
51
+ break;
52
+ }
53
+
54
+ const affectedTables = [];
55
+
56
+ if ( referencePosition ) {
57
+ const tableNode = ( referencePosition.nodeAfter && referencePosition.nodeAfter.name === 'table' ) ?
58
+ referencePosition.nodeAfter : referencePosition.findAncestor( 'table' );
59
+
60
+ if ( tableNode ) {
61
+ const range = model.createRangeOn( tableNode );
62
+
63
+ for ( const node of range.getItems() ) {
64
+ if ( node.is( 'element' ) && node.name === 'table' ) {
65
+ affectedTables.push( node );
66
+ }
67
+ }
68
+ }
69
+ }
70
+
71
+ const table = affectedTables;
72
+
73
+ if ( table ) {
74
+ for ( const tableItem of table ) {
75
+ tablesToProcess.add( tableItem );
76
+ }
77
+ }
78
+ }
79
+
80
+ return tablesToProcess;
81
+ }
82
+
83
+ /**
84
+ * Returns the computed width (in pixels) of the DOM element.
85
+ *
86
+ * @param {HTMLElement} domElement
87
+ * @returns {Number}
88
+ */
89
+ export function getElementWidthInPixels( domElement ) {
90
+ return parseFloat( global.window.getComputedStyle( domElement ).width );
91
+ }
92
+
93
+ /**
94
+ * Calculates the table width in pixels.
95
+ *
96
+ * @param {module:engine/model/element~Element} table
97
+ * @param {module:core/editor/editor~Editor} editor
98
+ * @returns {Number}
99
+ */
100
+ export function getTableWidthInPixels( table, editor ) {
101
+ const viewTbody = getTbodyViewElement( table, editor );
102
+ const domTbody = editor.editing.view.domConverter.mapViewToDom( viewTbody );
103
+
104
+ return getElementWidthInPixels( domTbody );
105
+ }
106
+
107
+ /**
108
+ * Calculates the column widths in pixels basing on the `columnWidths` table attribute:
109
+ * - If the value for a given column is provided in pixels then it is just converted to a number and returned.
110
+ * - Otherwise, it is assumed that unit is percentage and the column width is calculated proportionally to the whole table width.
111
+ *
112
+ * @param {module:engine/model/element~Element} table
113
+ * @param {module:core/editor/editor~Editor} editor
114
+ * @returns {Array.<Number>}
115
+ */
116
+ export function getColumnWidthsInPixels( table, editor ) {
117
+ const tableWidthInPixels = getTableWidthInPixels( table, editor );
118
+
119
+ return table.getAttribute( 'columnWidths' )
120
+ .split( ',' )
121
+ .map( columnWidth => columnWidth.trim() )
122
+ .map( columnWidth => {
123
+ return columnWidth.endsWith( 'px' ) ?
124
+ parseFloat( columnWidth ) :
125
+ parseFloat( columnWidth ) * tableWidthInPixels / 100;
126
+ } );
127
+ }
128
+
129
+ /**
130
+ * Calculates the percentage of the minimum column width given in pixels for a given table.
131
+ *
132
+ * @param {module:engine/model/element~Element} table
133
+ * @param {module:core/editor/editor~Editor} editor
134
+ * @returns {Number}
135
+ */
136
+ export function getColumnMinWidthAsPercentage( table, editor ) {
137
+ const tableWidthInPixels = getTableWidthInPixels( table, editor );
138
+
139
+ return COLUMN_MIN_WIDTH_IN_PIXELS * 100 / tableWidthInPixels;
140
+ }
141
+
142
+ /**
143
+ * Returns the column indexes on the left and right edges of a cell.
144
+ *
145
+ * @param {module:engine/model/element~Element} cell
146
+ * @returns {Object}
147
+ */
148
+ export function getColumnIndex( cell, columnIndexMap ) {
149
+ const cellColumnIndex = columnIndexMap.get( cell );
150
+ const cellWidth = cell.getAttribute( 'colspan' ) || 1;
151
+
152
+ return {
153
+ leftEdge: cellColumnIndex,
154
+ rightEdge: cellColumnIndex + cellWidth - 1
155
+ };
156
+ }
157
+
158
+ /**
159
+ * Returns the total number of columns in a table.
160
+ *
161
+ * @param {module:engine/model/element~Element} table
162
+ * @param {module:core/editor/editor~Editor} editor
163
+ * @returns {Number}
164
+ */
165
+ export function getNumberOfColumn( table, editor ) {
166
+ return editor.plugins.get( 'TableUtils' ).getColumns( table );
167
+ }
168
+
169
+ /**
170
+ * Checks if the table is already fully rendered, with the `<colgroup>` element that defines the widths for each column.
171
+ *
172
+ * @param {module:engine/model/element~Element} table
173
+ * @param {module:core/editor/editor~Editor} editor
174
+ * @returns {Number}
175
+ */
176
+ export function isTableRendered( table, editor ) {
177
+ return !!getColgroupViewElement( table, editor );
178
+ }
179
+
180
+ // Returns the `<colgroup>` view element, if it exists in a table. Returns `undefined` otherwise.
181
+ //
182
+ // @private
183
+ // @param {module:engine/model/element~Element} table
184
+ // @param {module:core/editor/editor~Editor} editor
185
+ // @returns {module:engine/view/element~Element|undefined}
186
+ function getColgroupViewElement( table, editor ) {
187
+ const viewFigure = editor.editing.mapper.toViewElement( table );
188
+ const viewTable = [ ...viewFigure.getChildren() ].find( viewChild => viewChild.is( 'element', 'table' ) );
189
+
190
+ return [ ...viewTable.getChildren() ].find( viewChild => viewChild.is( 'element', 'colgroup' ) );
191
+ }
192
+
193
+ // Returns the `<tbody>` view element, if it exists in a table. Returns `undefined` otherwise.
194
+ //
195
+ // @private
196
+ // @param {module:engine/model/element~Element} table
197
+ // @param {module:core/editor/editor~Editor} editor
198
+ // @returns {module:engine/view/element~Element|undefined}
199
+ function getTbodyViewElement( table, editor ) {
200
+ const viewFigure = editor.editing.mapper.toViewElement( table );
201
+ const viewTable = [ ...viewFigure.getChildren() ].find( viewChild => viewChild.is( 'element', 'table' ) );
202
+
203
+ return [ ...viewTable.getChildren() ].find( viewChild => viewChild.is( 'element', 'tbody' ) );
204
+ }
205
+
206
+ /**
207
+ * Rounds the provided value to a fixed-point number with defined number of digits after the decimal point.
208
+ *
209
+ * @param {Number|String} value
210
+ * @returns {Number}
211
+ */
212
+ export function toPrecision( value ) {
213
+ const multiplier = Math.pow( 10, COLUMN_WIDTH_PRECISION );
214
+ const number = parseFloat( value );
215
+
216
+ return Math.round( number * multiplier ) / multiplier;
217
+ }
218
+
219
+ /**
220
+ * Clamps the number within the inclusive lower (min) and upper (max) bounds. Returned number is rounded using the
221
+ * {@link ~toPrecision `toPrecision()`} function.
222
+ *
223
+ * @param {Number} number
224
+ * @param {Number} min
225
+ * @param {Number} max
226
+ * @returns {Number}
227
+ */
228
+ export function clamp( number, min, max ) {
229
+ if ( number <= min ) {
230
+ return toPrecision( min );
231
+ }
232
+
233
+ if ( number >= max ) {
234
+ return toPrecision( max );
235
+ }
236
+
237
+ return toPrecision( number );
238
+ }
239
+
240
+ /**
241
+ * Creates an array with defined length and fills all elements with defined value.
242
+ *
243
+ * @param {Number} length
244
+ * @param {*} value
245
+ * @returns {Array.<*>}
246
+ */
247
+ export function fillArray( length, value ) {
248
+ return Array( length ).fill( value );
249
+ }
250
+
251
+ /**
252
+ * Sums all array values that can be parsed to a float.
253
+ *
254
+ * @param {Array.<Number>} array
255
+ * @returns {Number}
256
+ */
257
+ export function sumArray( array ) {
258
+ return array
259
+ .map( value => parseFloat( value ) )
260
+ .filter( value => !Number.isNaN( value ) )
261
+ .reduce( ( result, item ) => result + item, 0 );
262
+ }
263
+
264
+ /**
265
+ * Makes sure that the sum of the widths from all columns is 100%. If the sum of all the widths is not equal 100%, all the widths are
266
+ * changed proportionally so that they all sum back to 100%.
267
+ *
268
+ * Currently, only widths provided as percentage values are supported.
269
+ *
270
+ * @param {String} columnWidthsAttribute
271
+ * @returns {Array.<Number>}
272
+ */
273
+ export function normalizeColumnWidthsAttribute( columnWidthsAttribute ) {
274
+ const columnWidths = prepareColumnWidths( columnWidthsAttribute );
275
+ const totalWidth = sumArray( columnWidths );
276
+
277
+ if ( totalWidth === 100 ) {
278
+ return columnWidths;
279
+ }
280
+
281
+ return columnWidths
282
+ // Adjust all the columns proportionally.
283
+ .map( columnWidth => toPrecision( columnWidth * 100 / totalWidth ) )
284
+ // Due to rounding of numbers it may happen that the sum of the widths of all columns will not be exactly 100%. Therefore, the width
285
+ // of the last column is explicitly adjusted (narrowed or expanded), since all the columns have been proportionally changed already.
286
+ .map( ( columnWidth, columnIndex, columnWidths ) => {
287
+ const isLastColumn = columnIndex === columnWidths.length - 1;
288
+
289
+ if ( !isLastColumn ) {
290
+ return columnWidth;
291
+ }
292
+
293
+ const totalWidth = sumArray( columnWidths );
294
+
295
+ return toPrecision( columnWidth + 100 - totalWidth );
296
+ } );
297
+ }
298
+
299
+ // Initializes the column widths by parsing the attribute value and calculating the uninitialized column widths. The special value 'auto'
300
+ // indicates that width for the column must be calculated. The width of such uninitialized column is calculated as follows:
301
+ // - If there is enough free space in the table for all uninitialized columns to have at least the minimum allowed width for all of them,
302
+ // then set this width equally for all uninitialized columns.
303
+ // - Otherwise, just set the minimum allowed width for all uninitialized columns. The sum of all column widths will be greater than 100%,
304
+ // but then it will be adjusted proportionally to 100% in {@link #normalizeColumnWidthsAttribute `normalizeColumnWidthsAttribute()`}.
305
+ //
306
+ // @private
307
+ // @param {String} columnWidthsAttribute
308
+ // @returns {Array.<Number>}
309
+ function prepareColumnWidths( columnWidthsAttribute ) {
310
+ const columnWidths = columnWidthsAttribute
311
+ .split( ',' )
312
+ .map( columnWidth => columnWidth.trim() );
313
+
314
+ const numberOfUninitializedColumns = columnWidths.filter( columnWidth => columnWidth === 'auto' ).length;
315
+
316
+ if ( numberOfUninitializedColumns === 0 ) {
317
+ return columnWidths.map( columnWidth => toPrecision( columnWidth ) );
318
+ }
319
+
320
+ const totalWidthOfInitializedColumns = sumArray( columnWidths );
321
+
322
+ const widthForUninitializedColumn = Math.max(
323
+ ( 100 - totalWidthOfInitializedColumns ) / numberOfUninitializedColumns,
324
+ COLUMN_MIN_WIDTH_AS_PERCENTAGE
325
+ );
326
+
327
+ return columnWidths
328
+ .map( columnWidth => columnWidth === 'auto' ? widthForUninitializedColumn : columnWidth )
329
+ .map( columnWidth => toPrecision( columnWidth ) );
330
+ }
331
+
332
+ // Inserts column resizer element into a view cell.
333
+ //
334
+ // @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter View writer instance.
335
+ // @param {module:engine/view/element~Element} viewCell View cell.
336
+ export function insertColumnResizerElements( viewWriter, viewCell ) {
337
+ let viewTableColumnResizerElement = [ ...viewCell.getChildren() ]
338
+ .find( viewElement => viewElement.hasClass( 'table-column-resizer' ) );
339
+
340
+ if ( viewTableColumnResizerElement ) {
341
+ return;
342
+ }
343
+
344
+ viewTableColumnResizerElement = viewWriter.createUIElement( 'div', {
345
+ class: 'table-column-resizer'
346
+ } );
347
+
348
+ viewWriter.insert(
349
+ viewWriter.createPositionAt( viewCell, 'end' ),
350
+ viewTableColumnResizerElement
351
+ );
352
+ }
353
+
354
+ // Removes column resizer element from a view cell.
355
+ //
356
+ // @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter View writer instance.
357
+ // @param {module:engine/view/element~Element} viewCell View cell.
358
+ export function removeColumnResizerElements( viewWriter, viewCell ) {
359
+ const viewTableColumnResizerElement = [ ...viewCell.getChildren() ]
360
+ .find( viewElement => viewElement.hasClass( 'table-column-resizer' ) );
361
+
362
+ if ( !viewTableColumnResizerElement ) {
363
+ return;
364
+ }
365
+
366
+ viewWriter.remove( viewTableColumnResizerElement );
367
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+
6
+ /**
7
+ * @module table/tablecolumnresize
8
+ */
9
+
10
+ import { Plugin } from 'ckeditor5/src/core';
11
+ import TableColumnResizeEditing from './tablecolumnresize/tablecolumnresizeediting';
12
+
13
+ import '../theme/tablecolumnresize.css';
14
+
15
+ /**
16
+ * The table column resizer feature.
17
+ *
18
+ * It provides the possibility to set the width of each column in a table using a resize handle.
19
+ *
20
+ * @extends module:core/plugin~Plugin
21
+ */
22
+ export default class TableColumnResize extends Plugin {
23
+ /**
24
+ * @inheritDoc
25
+ */
26
+ static get requires() {
27
+ return [ TableColumnResizeEditing ];
28
+ }
29
+
30
+ /**
31
+ * @inheritDoc
32
+ */
33
+ static get pluginName() {
34
+ return 'TableColumnResize';
35
+ }
36
+ }
@@ -10,14 +10,7 @@
10
10
  import { Plugin } from 'ckeditor5/src/core';
11
11
 
12
12
  import upcastTable, { ensureParagraphInTableCell, skipEmptyTableRow, upcastTableFigure } from './converters/upcasttable';
13
- import {
14
- convertParagraphInTableCell,
15
- downcastInsertCell,
16
- downcastInsertRow,
17
- downcastInsertTable,
18
- downcastRemoveRow,
19
- downcastTableHeadingColumnsChange
20
- } from './converters/downcast';
13
+ import { convertParagraphInTableCell, downcastCell, downcastRow, downcastTable } from './converters/downcast';
21
14
 
22
15
  import InsertTableCommand from './commands/inserttablecommand';
23
16
  import InsertRowCommand from './commands/insertrowcommand';
@@ -35,8 +28,9 @@ import TableUtils from '../src/tableutils';
35
28
 
36
29
  import injectTableLayoutPostFixer from './converters/table-layout-post-fixer';
37
30
  import injectTableCellParagraphPostFixer from './converters/table-cell-paragraph-post-fixer';
38
- import injectTableCellRefreshPostFixer from './converters/table-cell-refresh-post-fixer';
39
- import injectTableHeadingRowsRefreshPostFixer from './converters/table-heading-rows-refresh-post-fixer';
31
+
32
+ import tableHeadingsRefreshHandler from './converters/table-headings-refresh-handler';
33
+ import tableCellRefreshHandler from './converters/table-cell-refresh-handler';
40
34
 
41
35
  import '../theme/tableediting.css';
42
36
 
@@ -53,6 +47,13 @@ export default class TableEditing extends Plugin {
53
47
  return 'TableEditing';
54
48
  }
55
49
 
50
+ /**
51
+ * @inheritDoc
52
+ */
53
+ static get requires() {
54
+ return [ TableUtils ];
55
+ }
56
+
56
57
  /**
57
58
  * @inheritDoc
58
59
  */
@@ -61,12 +62,11 @@ export default class TableEditing extends Plugin {
61
62
  const model = editor.model;
62
63
  const schema = model.schema;
63
64
  const conversion = editor.conversion;
65
+ const tableUtils = editor.plugins.get( TableUtils );
64
66
 
65
67
  schema.register( 'table', {
66
- allowWhere: '$block',
67
- allowAttributes: [ 'headingRows', 'headingColumns' ],
68
- isObject: true,
69
- isBlock: true
68
+ inheritAllFrom: '$blockObject',
69
+ allowAttributes: [ 'headingRows', 'headingColumns' ]
70
70
  } );
71
71
 
72
72
  schema.register( 'tableRow', {
@@ -75,8 +75,8 @@ export default class TableEditing extends Plugin {
75
75
  } );
76
76
 
77
77
  schema.register( 'tableCell', {
78
+ allowContentOf: '$container',
78
79
  allowIn: 'tableRow',
79
- allowChildren: '$block',
80
80
  allowAttributes: [ 'colspan', 'rowspan' ],
81
81
  isLimit: true,
82
82
  isSelectable: true
@@ -88,15 +88,29 @@ export default class TableEditing extends Plugin {
88
88
  // Table conversion.
89
89
  conversion.for( 'upcast' ).add( upcastTable() );
90
90
 
91
- conversion.for( 'editingDowncast' ).add( downcastInsertTable( { asWidget: true } ) );
92
- conversion.for( 'dataDowncast' ).add( downcastInsertTable() );
91
+ conversion.for( 'editingDowncast' ).elementToStructure( {
92
+ model: {
93
+ name: 'table',
94
+ attributes: [ 'headingRows' ]
95
+ },
96
+ view: downcastTable( tableUtils, { asWidget: true } )
97
+ } );
98
+ conversion.for( 'dataDowncast' ).elementToStructure( {
99
+ model: {
100
+ name: 'table',
101
+ attributes: [ 'headingRows' ]
102
+ },
103
+ view: downcastTable( tableUtils )
104
+ } );
93
105
 
94
106
  // Table row conversion.
95
107
  conversion.for( 'upcast' ).elementToElement( { model: 'tableRow', view: 'tr' } );
96
108
  conversion.for( 'upcast' ).add( skipEmptyTableRow() );
97
109
 
98
- conversion.for( 'editingDowncast' ).add( downcastInsertRow() );
99
- conversion.for( 'editingDowncast' ).add( downcastRemoveRow() );
110
+ conversion.for( 'downcast' ).elementToElement( {
111
+ model: 'tableRow',
112
+ view: downcastRow()
113
+ } );
100
114
 
101
115
  // Table cell conversion.
102
116
  conversion.for( 'upcast' ).elementToElement( { model: 'tableCell', view: 'td' } );
@@ -104,12 +118,24 @@ export default class TableEditing extends Plugin {
104
118
  conversion.for( 'upcast' ).add( ensureParagraphInTableCell( 'td' ) );
105
119
  conversion.for( 'upcast' ).add( ensureParagraphInTableCell( 'th' ) );
106
120
 
107
- conversion.for( 'editingDowncast' ).add( downcastInsertCell() );
121
+ conversion.for( 'editingDowncast' ).elementToElement( {
122
+ model: 'tableCell',
123
+ view: downcastCell( { asWidget: true } )
124
+ } );
125
+ conversion.for( 'dataDowncast' ).elementToElement( {
126
+ model: 'tableCell',
127
+ view: downcastCell()
128
+ } );
108
129
 
109
130
  // Duplicates code - needed to properly refresh paragraph inside a table cell.
110
131
  conversion.for( 'editingDowncast' ).elementToElement( {
111
132
  model: 'paragraph',
112
- view: convertParagraphInTableCell,
133
+ view: convertParagraphInTableCell( { asWidget: true } ),
134
+ converterPriority: 'high'
135
+ } );
136
+ conversion.for( 'dataDowncast' ).elementToElement( {
137
+ model: 'paragraph',
138
+ view: convertParagraphInTableCell(),
113
139
  converterPriority: 'high'
114
140
  } );
115
141
 
@@ -126,9 +152,6 @@ export default class TableEditing extends Plugin {
126
152
  view: 'rowspan'
127
153
  } );
128
154
 
129
- // Table heading columns conversion (a change of heading rows requires a reconversion of the whole table).
130
- conversion.for( 'editingDowncast' ).add( downcastTableHeadingColumnsChange() );
131
-
132
155
  // Manually adjust model position mappings in a special case, when a table cell contains a paragraph, which is bound
133
156
  // to its parent (to the table cell). This custom model-to-view position mapping is necessary in data pipeline only,
134
157
  // because only during this conversion a paragraph can be bound to its parent.
@@ -164,17 +187,13 @@ export default class TableEditing extends Plugin {
164
187
  editor.commands.add( 'selectTableRow', new SelectRowCommand( editor ) );
165
188
  editor.commands.add( 'selectTableColumn', new SelectColumnCommand( editor ) );
166
189
 
167
- injectTableHeadingRowsRefreshPostFixer( model );
168
190
  injectTableLayoutPostFixer( model );
169
- injectTableCellRefreshPostFixer( model, editor.editing.mapper );
170
191
  injectTableCellParagraphPostFixer( model );
171
- }
172
192
 
173
- /**
174
- * @inheritDoc
175
- */
176
- static get requires() {
177
- return [ TableUtils ];
193
+ this.listenTo( model.document, 'change:data', () => {
194
+ tableHeadingsRefreshHandler( model, editor.editing );
195
+ tableCellRefreshHandler( model, editor.editing );
196
+ } );
178
197
  }
179
198
  }
180
199