@ckeditor/ckeditor5-table 36.0.0 → 37.0.0-alpha.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 (166) hide show
  1. package/build/table.js +1 -1
  2. package/package.json +34 -29
  3. package/src/commands/insertcolumncommand.d.ts +61 -0
  4. package/src/commands/insertcolumncommand.js +45 -60
  5. package/src/commands/insertrowcommand.d.ts +60 -0
  6. package/src/commands/insertrowcommand.js +44 -59
  7. package/src/commands/inserttablecommand.d.ts +50 -0
  8. package/src/commands/inserttablecommand.js +51 -68
  9. package/src/commands/mergecellcommand.d.ts +76 -0
  10. package/src/commands/mergecellcommand.js +169 -244
  11. package/src/commands/mergecellscommand.d.ts +33 -0
  12. package/src/commands/mergecellscommand.js +72 -101
  13. package/src/commands/removecolumncommand.d.ts +34 -0
  14. package/src/commands/removecolumncommand.js +88 -102
  15. package/src/commands/removerowcommand.d.ts +34 -0
  16. package/src/commands/removerowcommand.js +63 -80
  17. package/src/commands/selectcolumncommand.d.ts +38 -0
  18. package/src/commands/selectcolumncommand.js +41 -54
  19. package/src/commands/selectrowcommand.d.ts +38 -0
  20. package/src/commands/selectrowcommand.js +38 -48
  21. package/src/commands/setheadercolumncommand.d.ts +55 -0
  22. package/src/commands/setheadercolumncommand.js +48 -73
  23. package/src/commands/setheaderrowcommand.d.ts +58 -0
  24. package/src/commands/setheaderrowcommand.js +56 -85
  25. package/src/commands/splitcellcommand.d.ts +49 -0
  26. package/src/commands/splitcellcommand.js +35 -49
  27. package/src/converters/downcast.d.ts +63 -0
  28. package/src/converters/downcast.js +98 -130
  29. package/src/converters/table-caption-post-fixer.d.ts +20 -0
  30. package/src/converters/table-caption-post-fixer.js +36 -52
  31. package/src/converters/table-cell-paragraph-post-fixer.d.ts +32 -0
  32. package/src/converters/table-cell-paragraph-post-fixer.js +88 -119
  33. package/src/converters/table-cell-refresh-handler.d.ts +18 -0
  34. package/src/converters/table-cell-refresh-handler.js +29 -48
  35. package/src/converters/table-headings-refresh-handler.d.ts +17 -0
  36. package/src/converters/table-headings-refresh-handler.js +35 -54
  37. package/src/converters/table-layout-post-fixer.d.ts +226 -0
  38. package/src/converters/table-layout-post-fixer.js +276 -313
  39. package/src/converters/tableproperties.d.ts +54 -0
  40. package/src/converters/tableproperties.js +136 -168
  41. package/src/converters/upcasttable.d.ts +49 -0
  42. package/src/converters/upcasttable.js +196 -251
  43. package/src/index.d.ts +29 -0
  44. package/src/index.js +0 -2
  45. package/src/plaintableoutput.d.ts +30 -0
  46. package/src/plaintableoutput.js +107 -135
  47. package/src/table.d.ts +38 -0
  48. package/src/table.js +12 -88
  49. package/src/tablecaption/tablecaptionediting.d.ts +68 -0
  50. package/src/tablecaption/tablecaptionediting.js +104 -135
  51. package/src/tablecaption/tablecaptionui.d.ts +26 -0
  52. package/src/tablecaption/tablecaptionui.js +42 -58
  53. package/src/tablecaption/toggletablecaptioncommand.d.ts +73 -0
  54. package/src/tablecaption/toggletablecaptioncommand.js +77 -92
  55. package/src/tablecaption/utils.d.ts +42 -0
  56. package/src/tablecaption/utils.js +35 -61
  57. package/src/tablecaption.d.ts +27 -0
  58. package/src/tablecaption.js +12 -19
  59. package/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.d.ts +37 -0
  60. package/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.js +14 -20
  61. package/src/tablecellproperties/commands/tablecellbordercolorcommand.d.ts +42 -0
  62. package/src/tablecellproperties/commands/tablecellbordercolorcommand.js +27 -37
  63. package/src/tablecellproperties/commands/tablecellborderstylecommand.d.ts +42 -0
  64. package/src/tablecellproperties/commands/tablecellborderstylecommand.js +27 -37
  65. package/src/tablecellproperties/commands/tablecellborderwidthcommand.d.ts +56 -0
  66. package/src/tablecellproperties/commands/tablecellborderwidthcommand.js +42 -53
  67. package/src/tablecellproperties/commands/tablecellheightcommand.d.ts +51 -0
  68. package/src/tablecellproperties/commands/tablecellheightcommand.js +29 -36
  69. package/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.d.ts +37 -0
  70. package/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js +14 -20
  71. package/src/tablecellproperties/commands/tablecellpaddingcommand.d.ts +56 -0
  72. package/src/tablecellproperties/commands/tablecellpaddingcommand.js +42 -53
  73. package/src/tablecellproperties/commands/tablecellpropertycommand.d.ts +62 -0
  74. package/src/tablecellproperties/commands/tablecellpropertycommand.js +77 -122
  75. package/src/tablecellproperties/commands/tablecellverticalalignmentcommand.d.ts +45 -0
  76. package/src/tablecellproperties/commands/tablecellverticalalignmentcommand.js +14 -20
  77. package/src/tablecellproperties/tablecellpropertiesediting.d.ts +47 -0
  78. package/src/tablecellproperties/tablecellpropertiesediting.js +194 -236
  79. package/src/tablecellproperties/tablecellpropertiesui.d.ts +117 -0
  80. package/src/tablecellproperties/tablecellpropertiesui.js +303 -456
  81. package/src/tablecellproperties/ui/tablecellpropertiesview.d.ts +227 -0
  82. package/src/tablecellproperties/ui/tablecellpropertiesview.js +509 -844
  83. package/src/tablecellproperties.d.ts +33 -0
  84. package/src/tablecellproperties.js +12 -98
  85. package/src/tablecellwidth/commands/tablecellwidthcommand.d.ts +51 -0
  86. package/src/tablecellwidth/commands/tablecellwidthcommand.js +29 -35
  87. package/src/tablecellwidth/tablecellwidthediting.d.ts +34 -0
  88. package/src/tablecellwidth/tablecellwidthediting.js +26 -38
  89. package/src/tableclipboard.d.ts +68 -0
  90. package/src/tableclipboard.js +429 -568
  91. package/src/tablecolumnresize/constants.d.ts +20 -0
  92. package/src/tablecolumnresize/constants.js +0 -10
  93. package/src/tablecolumnresize/converters.d.ts +18 -0
  94. package/src/tablecolumnresize/converters.js +35 -119
  95. package/src/tablecolumnresize/tablecolumnresizeediting.d.ts +142 -0
  96. package/src/tablecolumnresize/tablecolumnresizeediting.js +545 -711
  97. package/src/tablecolumnresize/tablewidthscommand.d.ts +38 -0
  98. package/src/tablecolumnresize/tablewidthscommand.js +61 -0
  99. package/src/tablecolumnresize/utils.d.ts +141 -0
  100. package/src/tablecolumnresize/utils.js +256 -233
  101. package/src/tablecolumnresize.d.ts +29 -0
  102. package/src/tablecolumnresize.js +12 -19
  103. package/src/tableconfig.d.ts +341 -0
  104. package/src/tableconfig.js +5 -0
  105. package/src/tableediting.d.ts +102 -0
  106. package/src/tableediting.js +157 -176
  107. package/src/tablekeyboard.d.ts +68 -0
  108. package/src/tablekeyboard.js +261 -344
  109. package/src/tablemouse/mouseeventsobserver.d.ts +62 -0
  110. package/src/tablemouse/mouseeventsobserver.js +12 -49
  111. package/src/tablemouse.d.ts +51 -0
  112. package/src/tablemouse.js +154 -202
  113. package/src/tableproperties/commands/tablealignmentcommand.d.ts +37 -0
  114. package/src/tableproperties/commands/tablealignmentcommand.js +14 -20
  115. package/src/tableproperties/commands/tablebackgroundcolorcommand.d.ts +37 -0
  116. package/src/tableproperties/commands/tablebackgroundcolorcommand.js +14 -20
  117. package/src/tableproperties/commands/tablebordercolorcommand.d.ts +42 -0
  118. package/src/tableproperties/commands/tablebordercolorcommand.js +27 -37
  119. package/src/tableproperties/commands/tableborderstylecommand.d.ts +42 -0
  120. package/src/tableproperties/commands/tableborderstylecommand.js +27 -37
  121. package/src/tableproperties/commands/tableborderwidthcommand.d.ts +56 -0
  122. package/src/tableproperties/commands/tableborderwidthcommand.js +42 -53
  123. package/src/tableproperties/commands/tableheightcommand.d.ts +51 -0
  124. package/src/tableproperties/commands/tableheightcommand.js +29 -33
  125. package/src/tableproperties/commands/tablepropertycommand.d.ts +61 -0
  126. package/src/tableproperties/commands/tablepropertycommand.js +68 -112
  127. package/src/tableproperties/commands/tablewidthcommand.d.ts +51 -0
  128. package/src/tableproperties/commands/tablewidthcommand.js +29 -33
  129. package/src/tableproperties/tablepropertiesediting.d.ts +45 -0
  130. package/src/tableproperties/tablepropertiesediting.js +164 -210
  131. package/src/tableproperties/tablepropertiesui.d.ts +119 -0
  132. package/src/tableproperties/tablepropertiesui.js +294 -439
  133. package/src/tableproperties/ui/tablepropertiesview.d.ts +203 -0
  134. package/src/tableproperties/ui/tablepropertiesview.js +427 -718
  135. package/src/tableproperties.d.ts +33 -0
  136. package/src/tableproperties.js +12 -95
  137. package/src/tableselection.d.ts +111 -0
  138. package/src/tableselection.js +279 -376
  139. package/src/tabletoolbar.d.ts +37 -0
  140. package/src/tabletoolbar.js +39 -92
  141. package/src/tableui.d.ts +58 -0
  142. package/src/tableui.js +281 -338
  143. package/src/tableutils.d.ts +453 -0
  144. package/src/tableutils.js +1015 -1229
  145. package/src/tablewalker.d.ts +323 -0
  146. package/src/tablewalker.js +308 -548
  147. package/src/ui/colorinputview.d.ts +143 -0
  148. package/src/ui/colorinputview.js +229 -366
  149. package/src/ui/formrowview.d.ts +61 -0
  150. package/src/ui/formrowview.js +38 -84
  151. package/src/ui/inserttableview.d.ts +77 -0
  152. package/src/ui/inserttableview.js +152 -242
  153. package/src/utils/common.d.ts +42 -0
  154. package/src/utils/common.js +33 -57
  155. package/src/utils/structure.d.ts +245 -0
  156. package/src/utils/structure.js +261 -379
  157. package/src/utils/table-properties.d.ts +67 -0
  158. package/src/utils/table-properties.js +60 -81
  159. package/src/utils/ui/contextualballoon.d.ts +34 -0
  160. package/src/utils/ui/contextualballoon.js +70 -89
  161. package/src/utils/ui/table-properties.d.ts +193 -0
  162. package/src/utils/ui/table-properties.js +259 -319
  163. package/src/utils/ui/widget.d.ts +16 -0
  164. package/src/utils/ui/widget.js +24 -46
  165. package/src/tablecolumnresize/tablecolumnwidthscommand.js +0 -55
  166. package/src/tablecolumnresize/tablewidthresizecommand.js +0 -65
@@ -2,14 +2,8 @@
2
2
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
- /**
7
- * @module table/converters/table-layout-post-fixer
8
- */
9
-
10
5
  import TableWalker from './../tablewalker';
11
6
  import { createEmptyTableCell, updateNumericAttribute } from '../utils/common';
12
-
13
7
  /**
14
8
  * Injects a table layout post-fixer into the model.
15
9
  *
@@ -33,33 +27,37 @@ import { createEmptyTableCell, updateNumericAttribute } from '../utils/common';
33
27
  *
34
28
  * For example, see the following table which has a cell (FOO) with the rowspan attribute (2):
35
29
  *
36
- * <table headingRows="1">
37
- * <tableRow>
38
- * <tableCell rowspan="2"><paragraph>FOO</paragraph></tableCell>
39
- * <tableCell colspan="2"><paragraph>BAR</paragraph></tableCell>
40
- * </tableRow>
41
- * <tableRow>
42
- * <tableCell><paragraph>BAZ</paragraph></tableCell>
43
- * <tableCell><paragraph>XYZ</paragraph></tableCell>
44
- * </tableRow>
45
- * </table>
30
+ * ```xml
31
+ * <table headingRows="1">
32
+ * <tableRow>
33
+ * <tableCell rowspan="2"><paragraph>FOO</paragraph></tableCell>
34
+ * <tableCell colspan="2"><paragraph>BAR</paragraph></tableCell>
35
+ * </tableRow>
36
+ * <tableRow>
37
+ * <tableCell><paragraph>BAZ</paragraph></tableCell>
38
+ * <tableCell><paragraph>XYZ</paragraph></tableCell>
39
+ * </tableRow>
40
+ * </table>
41
+ * ```
46
42
  *
47
43
  * It will be rendered in the view as:
48
44
  *
49
- * <table>
50
- * <thead>
51
- * <tr>
52
- * <td rowspan="2">FOO</td>
53
- * <td colspan="2">BAR</td>
54
- * </tr>
55
- * </thead>
56
- * <tbody>
57
- * <tr>
58
- * <td>BAZ</td>
59
- * <td>XYZ</td>
60
- * </tr>
61
- * </tbody>
62
- * </table>
45
+ * ```xml
46
+ * <table>
47
+ * <thead>
48
+ * <tr>
49
+ * <td rowspan="2">FOO</td>
50
+ * <td colspan="2">BAR</td>
51
+ * </tr>
52
+ * </thead>
53
+ * <tbody>
54
+ * <tr>
55
+ * <td>BAZ</td>
56
+ * <td>XYZ</td>
57
+ * </tr>
58
+ * </tbody>
59
+ * </table>
60
+ * ```
63
61
  *
64
62
  * In the above example the table will be rendered as a table with two rows: one in the header and second one in the body.
65
63
  * The table cell (FOO) cannot span over multiple rows as it would extend from the header to the body section.
@@ -81,20 +79,22 @@ import { createEmptyTableCell, updateNumericAttribute } from '../utils/common';
81
79
  *
82
80
  * The table from the above example will be fixed and rendered to the view as below:
83
81
  *
84
- * <table>
85
- * <thead>
86
- * <tr>
87
- * <td rowspan="2">FOO</td>
88
- * <td colspan="2">BAR</td>
89
- * </tr>
90
- * </thead>
91
- * <tbody>
92
- * <tr>
93
- * <td>BAZ</td>
94
- * <td>XYZ</td>
95
- * </tr>
96
- * </tbody>
97
- * </table>
82
+ * ```xml
83
+ * <table>
84
+ * <thead>
85
+ * <tr>
86
+ * <td rowspan="2">FOO</td>
87
+ * <td colspan="2">BAR</td>
88
+ * </tr>
89
+ * </thead>
90
+ * <tbody>
91
+ * <tr>
92
+ * <td>BAZ</td>
93
+ * <td>XYZ</td>
94
+ * </tr>
95
+ * </tbody>
96
+ * </table>
97
+ * ```
98
98
  *
99
99
  * ## Collaboration and undo - Expectations vs post-fixer results
100
100
  *
@@ -106,18 +106,20 @@ import { createEmptyTableCell, updateNumericAttribute } from '../utils/common';
106
106
  *
107
107
  * As an example see the table below:
108
108
  *
109
- * <table>
110
- * <tbody>
111
- * <tr>
112
- * <td>11</td>
113
- * <td>12</td>
114
- * </tr>
115
- * <tr>
116
- * <td>21</td>
117
- * <td>22</td>
118
- * </tr>
119
- * </tbody>
120
- * </table>
109
+ * ```xml
110
+ * <table>
111
+ * <tbody>
112
+ * <tr>
113
+ * <td>11</td>
114
+ * <td>12</td>
115
+ * </tr>
116
+ * <tr>
117
+ * <td>21</td>
118
+ * <td>22</td>
119
+ * </tr>
120
+ * </tbody>
121
+ * </table>
122
+ * ```
121
123
  *
122
124
  * and the user actions:
123
125
  *
@@ -126,279 +128,240 @@ import { createEmptyTableCell, updateNumericAttribute } from '../utils/common';
126
128
  * 3. User B adds a row at the end of the table. This will insert a row with two empty table cells.
127
129
  * 4. Both users will have a table as below:
128
130
  *
129
- *
130
- * <table>
131
- * <tbody>
132
- * <tr>
133
- * <td>11</td>
134
- * <td>12</td>
135
- * <td>(empty, inserted by A)</td>
136
- * </tr>
137
- * <tr>
138
- * <td>21</td>
139
- * <td>22</td>
140
- * <td>(empty, inserted by A)</td>
141
- * </tr>
142
- * <tr>
143
- * <td>(empty, inserted by B)</td>
144
- * <td>(empty, inserted by B)</td>
145
- * </tr>
146
- * </tbody>
147
- * </table>
131
+ * ```xml
132
+ * <table>
133
+ * <tbody>
134
+ * <tr>
135
+ * <td>11</td>
136
+ * <td>12</td>
137
+ * <td>(empty, inserted by A)</td>
138
+ * </tr>
139
+ * <tr>
140
+ * <td>21</td>
141
+ * <td>22</td>
142
+ * <td>(empty, inserted by A)</td>
143
+ * </tr>
144
+ * <tr>
145
+ * <td>(empty, inserted by B)</td>
146
+ * <td>(empty, inserted by B)</td>
147
+ * </tr>
148
+ * </tbody>
149
+ * </table>
150
+ * ```
148
151
  *
149
152
  * The last row is shorter then others so the table post-fixer will add an empty row to the last row:
150
153
  *
151
- * <table>
152
- * <tbody>
153
- * <tr>
154
- * <td>11</td>
155
- * <td>12</td>
156
- * <td>(empty, inserted by A)</td>
157
- * </tr>
158
- * <tr>
159
- * <td>21</td>
160
- * <td>22</td>
161
- * <td>(empty, inserted by A)</td>
162
- * </tr>
163
- * <tr>
164
- * <td>(empty, inserted by B)</td>
165
- * <td>(empty, inserted by B)</td>
166
- * <td>(empty, inserted by the post-fixer)</td>
167
- * </tr>
168
- * </tbody>
169
- * </table>
154
+ * ```xml
155
+ * <table>
156
+ * <tbody>
157
+ * <tr>
158
+ * <td>11</td>
159
+ * <td>12</td>
160
+ * <td>(empty, inserted by A)</td>
161
+ * </tr>
162
+ * <tr>
163
+ * <td>21</td>
164
+ * <td>22</td>
165
+ * <td>(empty, inserted by A)</td>
166
+ * </tr>
167
+ * <tr>
168
+ * <td>(empty, inserted by B)</td>
169
+ * <td>(empty, inserted by B)</td>
170
+ * <td>(empty, inserted by the post-fixer)</td>
171
+ * </tr>
172
+ * </tbody>
173
+ * </table>
174
+ * ```
170
175
  *
171
176
  * Unfortunately undo does not know the nature of the changes and depending on which user applies the post-fixer changes, undoing them
172
177
  * might lead to a broken table. If User B undoes inserting the column to the table, the undo engine will undo only the operations of
173
178
  * inserting empty cells to rows from the initial table state (row 1 and 2) but the cell in the post-fixed row will remain:
174
179
  *
175
- * <table>
176
- * <tbody>
177
- * <tr>
178
- * <td>11</td>
179
- * <td>12</td>
180
- * </tr>
181
- * <tr>
182
- * <td>21</td>
183
- * <td>22</td>
184
- * </tr>
185
- * <tr>
186
- * <td>(empty, inserted by B)</td>
187
- * <td>(empty, inserted by B)</td>
188
- * <td>(empty, inserted by a post-fixer)</td>
189
- * </tr>
190
- * </tbody>
191
- * </table>
180
+ * ```xml
181
+ * <table>
182
+ * <tbody>
183
+ * <tr>
184
+ * <td>11</td>
185
+ * <td>12</td>
186
+ * </tr>
187
+ * <tr>
188
+ * <td>21</td>
189
+ * <td>22</td>
190
+ * </tr>
191
+ * <tr>
192
+ * <td>(empty, inserted by B)</td>
193
+ * <td>(empty, inserted by B)</td>
194
+ * <td>(empty, inserted by a post-fixer)</td>
195
+ * </tr>
196
+ * </tbody>
197
+ * </table>
198
+ * ```
192
199
  *
193
200
  * After undo, the table post-fixer will detect that two rows are shorter than others and will fix the table to:
194
201
  *
195
- * <table>
196
- * <tbody>
197
- * <tr>
198
- * <td>11</td>
199
- * <td>12</td>
200
- * <td>(empty, inserted by a post-fixer after undo)</td>
201
- * </tr>
202
- * <tr>
203
- * <td>21</td>
204
- * <td>22</td>
205
- * <td>(empty, inserted by a post-fixer after undo)</td>
206
- * </tr>
207
- * <tr>
208
- * <td>(empty, inserted by B)</td>
209
- * <td>(empty, inserted by B)</td>
210
- * <td>(empty, inserted by a post-fixer)</td>
211
- * </tr>
212
- * </tbody>
213
- * </table>
214
- * @param {module:engine/model/model~Model} model
202
+ * ```xml
203
+ * <table>
204
+ * <tbody>
205
+ * <tr>
206
+ * <td>11</td>
207
+ * <td>12</td>
208
+ * <td>(empty, inserted by a post-fixer after undo)</td>
209
+ * </tr>
210
+ * <tr>
211
+ * <td>21</td>
212
+ * <td>22</td>
213
+ * <td>(empty, inserted by a post-fixer after undo)</td>
214
+ * </tr>
215
+ * <tr>
216
+ * <td>(empty, inserted by B)</td>
217
+ * <td>(empty, inserted by B)</td>
218
+ * <td>(empty, inserted by a post-fixer)</td>
219
+ * </tr>
220
+ * </tbody>
221
+ * </table>
222
+ * ```
215
223
  */
216
- export default function injectTableLayoutPostFixer( model ) {
217
- model.document.registerPostFixer( writer => tableLayoutPostFixer( writer, model ) );
224
+ export default function injectTableLayoutPostFixer(model) {
225
+ model.document.registerPostFixer(writer => tableLayoutPostFixer(writer, model));
218
226
  }
219
-
220
- // The table layout post-fixer.
221
- //
222
- // @param {module:engine/model/writer~Writer} writer
223
- // @param {module:engine/model/model~Model} model
224
- function tableLayoutPostFixer( writer, model ) {
225
- const changes = model.document.differ.getChanges();
226
-
227
- let wasFixed = false;
228
-
229
- // Do not analyze the same table more then once - may happen for multiple changes in the same table.
230
- const analyzedTables = new Set();
231
-
232
- for ( const entry of changes ) {
233
- let table;
234
-
235
- if ( entry.name == 'table' && entry.type == 'insert' ) {
236
- table = entry.position.nodeAfter;
237
- }
238
-
239
- // Fix table on adding/removing table cells and rows.
240
- if ( entry.name == 'tableRow' || entry.name == 'tableCell' ) {
241
- table = entry.position.findAncestor( 'table' );
242
- }
243
-
244
- // Fix table on any table's attribute change - including attributes of table cells.
245
- if ( isTableAttributeEntry( entry ) ) {
246
- table = entry.range.start.findAncestor( 'table' );
247
- }
248
-
249
- if ( table && !analyzedTables.has( table ) ) {
250
- // Step 1: correct rowspans of table cells if necessary.
251
- // The wasFixed flag should be true if any of tables in batch was fixed - might be more then one.
252
- wasFixed = fixTableCellsRowspan( table, writer ) || wasFixed;
253
- // Step 2: fix table rows sizes.
254
- wasFixed = fixTableRowsSizes( table, writer ) || wasFixed;
255
-
256
- analyzedTables.add( table );
257
- }
258
- }
259
-
260
- return wasFixed;
227
+ /**
228
+ * The table layout post-fixer.
229
+ */
230
+ function tableLayoutPostFixer(writer, model) {
231
+ const changes = model.document.differ.getChanges();
232
+ let wasFixed = false;
233
+ // Do not analyze the same table more then once - may happen for multiple changes in the same table.
234
+ const analyzedTables = new Set();
235
+ for (const entry of changes) {
236
+ let table = null;
237
+ if (entry.type == 'insert' && entry.name == 'table') {
238
+ table = entry.position.nodeAfter;
239
+ }
240
+ // Fix table on adding/removing table cells and rows.
241
+ if ((entry.type == 'insert' || entry.type == 'remove') && (entry.name == 'tableRow' || entry.name == 'tableCell')) {
242
+ table = entry.position.findAncestor('table');
243
+ }
244
+ // Fix table on any table's attribute change - including attributes of table cells.
245
+ if (isTableAttributeEntry(entry)) {
246
+ table = entry.range.start.findAncestor('table');
247
+ }
248
+ if (table && !analyzedTables.has(table)) {
249
+ // Step 1: correct rowspans of table cells if necessary.
250
+ // The wasFixed flag should be true if any of tables in batch was fixed - might be more then one.
251
+ wasFixed = fixTableCellsRowspan(table, writer) || wasFixed;
252
+ // Step 2: fix table rows sizes.
253
+ wasFixed = fixTableRowsSizes(table, writer) || wasFixed;
254
+ analyzedTables.add(table);
255
+ }
256
+ }
257
+ return wasFixed;
261
258
  }
262
-
263
- // Fixes the invalid value of the `rowspan` attribute because a table cell cannot vertically extend beyond the table section it belongs to.
264
- //
265
- // @param {module:engine/model/element~Element} table
266
- // @param {module:engine/model/writer~Writer} writer
267
- // @returns {Boolean} Returns `true` if the table was fixed.
268
- function fixTableCellsRowspan( table, writer ) {
269
- let wasFixed = false;
270
-
271
- const cellsToTrim = findCellsToTrim( table );
272
-
273
- if ( cellsToTrim.length ) {
274
- // @if CK_DEBUG_TABLE // console.log( `Post-fixing table: trimming cells row-spans (${ cellsToTrim.length }).` );
275
-
276
- wasFixed = true;
277
-
278
- for ( const data of cellsToTrim ) {
279
- updateNumericAttribute( 'rowspan', data.rowspan, data.cell, writer, 1 );
280
- }
281
- }
282
-
283
- return wasFixed;
259
+ /**
260
+ * Fixes the invalid value of the `rowspan` attribute because a table cell cannot vertically extend beyond the table section it belongs to.
261
+ *
262
+ * @returns Returns `true` if the table was fixed.
263
+ */
264
+ function fixTableCellsRowspan(table, writer) {
265
+ let wasFixed = false;
266
+ const cellsToTrim = findCellsToTrim(table);
267
+ if (cellsToTrim.length) {
268
+ // @if CK_DEBUG_TABLE // console.log( `Post-fixing table: trimming cells row-spans (${ cellsToTrim.length }).` );
269
+ wasFixed = true;
270
+ for (const data of cellsToTrim) {
271
+ updateNumericAttribute('rowspan', data.rowspan, data.cell, writer, 1);
272
+ }
273
+ }
274
+ return wasFixed;
284
275
  }
285
-
286
- // Makes all table rows in a table the same size.
287
- //
288
- // @param {module:engine/model/element~Element} table
289
- // @param {module:engine/model/writer~Writer} writer
290
- // @returns {Boolean} Returns `true` if the table was fixed.
291
- function fixTableRowsSizes( table, writer ) {
292
- let wasFixed = false;
293
-
294
- const childrenLengths = getChildrenLengths( table );
295
- const rowsToRemove = [];
296
-
297
- // Find empty rows.
298
- for ( const [ rowIndex, size ] of childrenLengths.entries() ) {
299
- // Ignore all non-row models.
300
- if ( !size && table.getChild( rowIndex ).is( 'element', 'tableRow' ) ) {
301
- rowsToRemove.push( rowIndex );
302
- }
303
- }
304
-
305
- // Remove empty rows.
306
- if ( rowsToRemove.length ) {
307
- // @if CK_DEBUG_TABLE // console.log( `Post-fixing table: remove empty rows (${ rowsToRemove.length }).` );
308
-
309
- wasFixed = true;
310
-
311
- for ( const rowIndex of rowsToRemove.reverse() ) {
312
- writer.remove( table.getChild( rowIndex ) );
313
- childrenLengths.splice( rowIndex, 1 );
314
- }
315
- }
316
-
317
- // Filter out everything that's not a table row.
318
- const rowsLengths = childrenLengths.filter( ( row, rowIndex ) => table.getChild( rowIndex ).is( 'element', 'tableRow' ) );
319
-
320
- // Verify if all the rows have the same number of columns.
321
- const tableSize = rowsLengths[ 0 ];
322
- const isValid = rowsLengths.every( length => length === tableSize );
323
-
324
- if ( !isValid ) {
325
- // @if CK_DEBUG_TABLE // console.log( 'Post-fixing table: adding missing cells.' );
326
-
327
- // Find the maximum number of columns.
328
- const maxColumns = rowsLengths.reduce( ( prev, current ) => current > prev ? current : prev, 0 );
329
-
330
- for ( const [ rowIndex, size ] of rowsLengths.entries() ) {
331
- const columnsToInsert = maxColumns - size;
332
-
333
- if ( columnsToInsert ) {
334
- for ( let i = 0; i < columnsToInsert; i++ ) {
335
- createEmptyTableCell( writer, writer.createPositionAt( table.getChild( rowIndex ), 'end' ) );
336
- }
337
-
338
- wasFixed = true;
339
- }
340
- }
341
- }
342
-
343
- return wasFixed;
276
+ /**
277
+ * Makes all table rows in a table the same size.
278
+ *
279
+ * @returns Returns `true` if the table was fixed.
280
+ */
281
+ function fixTableRowsSizes(table, writer) {
282
+ let wasFixed = false;
283
+ const childrenLengths = getChildrenLengths(table);
284
+ const rowsToRemove = [];
285
+ // Find empty rows.
286
+ for (const [rowIndex, size] of childrenLengths.entries()) {
287
+ // Ignore all non-row models.
288
+ if (!size && table.getChild(rowIndex).is('element', 'tableRow')) {
289
+ rowsToRemove.push(rowIndex);
290
+ }
291
+ }
292
+ // Remove empty rows.
293
+ if (rowsToRemove.length) {
294
+ // @if CK_DEBUG_TABLE // console.log( `Post-fixing table: remove empty rows (${ rowsToRemove.length }).` );
295
+ wasFixed = true;
296
+ for (const rowIndex of rowsToRemove.reverse()) {
297
+ writer.remove(table.getChild(rowIndex));
298
+ childrenLengths.splice(rowIndex, 1);
299
+ }
300
+ }
301
+ // Filter out everything that's not a table row.
302
+ const rowsLengths = childrenLengths.filter((row, rowIndex) => table.getChild(rowIndex).is('element', 'tableRow'));
303
+ // Verify if all the rows have the same number of columns.
304
+ const tableSize = rowsLengths[0];
305
+ const isValid = rowsLengths.every(length => length === tableSize);
306
+ if (!isValid) {
307
+ // @if CK_DEBUG_TABLE // console.log( 'Post-fixing table: adding missing cells.' );
308
+ // Find the maximum number of columns.
309
+ const maxColumns = rowsLengths.reduce((prev, current) => current > prev ? current : prev, 0);
310
+ for (const [rowIndex, size] of rowsLengths.entries()) {
311
+ const columnsToInsert = maxColumns - size;
312
+ if (columnsToInsert) {
313
+ for (let i = 0; i < columnsToInsert; i++) {
314
+ createEmptyTableCell(writer, writer.createPositionAt(table.getChild(rowIndex), 'end'));
315
+ }
316
+ wasFixed = true;
317
+ }
318
+ }
319
+ }
320
+ return wasFixed;
344
321
  }
345
-
346
- // Searches for table cells that extend beyond the table section to which they belong to. It will return an array of objects
347
- // that stores table cells to be trimmed and the correct value of the `rowspan` attribute to set.
348
- //
349
- // @param {module:engine/model/element~Element} table
350
- // @returns {Array.<{{cell, rowspan}}>}
351
- function findCellsToTrim( table ) {
352
- const headingRows = parseInt( table.getAttribute( 'headingRows' ) || 0 );
353
- const maxRows = Array.from( table.getChildren() )
354
- .reduce( ( count, row ) => row.is( 'element', 'tableRow' ) ? count + 1 : count, 0 );
355
-
356
- const cellsToTrim = [];
357
-
358
- for ( const { row, cell, cellHeight } of new TableWalker( table ) ) {
359
- // Skip cells that do not expand over its row.
360
- if ( cellHeight < 2 ) {
361
- continue;
362
- }
363
-
364
- const isInHeader = row < headingRows;
365
-
366
- // Row limit is either end of header section or whole table as table body is after the header.
367
- const rowLimit = isInHeader ? headingRows : maxRows;
368
-
369
- // If table cell expands over its limit reduce it height to proper value.
370
- if ( row + cellHeight > rowLimit ) {
371
- const newRowspan = rowLimit - row;
372
-
373
- cellsToTrim.push( { cell, rowspan: newRowspan } );
374
- }
375
- }
376
-
377
- return cellsToTrim;
322
+ /**
323
+ * Searches for table cells that extend beyond the table section to which they belong to. It will return an array of objects
324
+ * that stores table cells to be trimmed and the correct value of the `rowspan` attribute to set.
325
+ */
326
+ function findCellsToTrim(table) {
327
+ const headingRows = parseInt(table.getAttribute('headingRows') || '0');
328
+ const maxRows = Array.from(table.getChildren())
329
+ .reduce((count, row) => row.is('element', 'tableRow') ? count + 1 : count, 0);
330
+ const cellsToTrim = [];
331
+ for (const { row, cell, cellHeight } of new TableWalker(table)) {
332
+ // Skip cells that do not expand over its row.
333
+ if (cellHeight < 2) {
334
+ continue;
335
+ }
336
+ const isInHeader = row < headingRows;
337
+ // Row limit is either end of header section or whole table as table body is after the header.
338
+ const rowLimit = isInHeader ? headingRows : maxRows;
339
+ // If table cell expands over its limit reduce it height to proper value.
340
+ if (row + cellHeight > rowLimit) {
341
+ const newRowspan = rowLimit - row;
342
+ cellsToTrim.push({ cell, rowspan: newRowspan });
343
+ }
344
+ }
345
+ return cellsToTrim;
378
346
  }
379
-
380
- // Returns an array with lengths of rows assigned to the corresponding row index.
381
- //
382
- // @param {module:engine/model/element~Element} table
383
- // @returns {Array.<Number>}
384
- function getChildrenLengths( table ) {
385
- // TableWalker will not provide items for the empty rows, we need to pre-fill this array.
386
- const lengths = new Array( table.childCount ).fill( 0 );
387
-
388
- for ( const { rowIndex } of new TableWalker( table, { includeAllSlots: true } ) ) {
389
- lengths[ rowIndex ]++;
390
- }
391
-
392
- return lengths;
347
+ /**
348
+ * Returns an array with lengths of rows assigned to the corresponding row index.
349
+ */
350
+ function getChildrenLengths(table) {
351
+ // TableWalker will not provide items for the empty rows, we need to pre-fill this array.
352
+ const lengths = new Array(table.childCount).fill(0);
353
+ for (const { rowIndex } of new TableWalker(table, { includeAllSlots: true })) {
354
+ lengths[rowIndex]++;
355
+ }
356
+ return lengths;
393
357
  }
394
-
395
- // Checks if the differ entry for an attribute change is one of the table's attributes.
396
- //
397
- // @param entry
398
- // @returns {Boolean}
399
- function isTableAttributeEntry( entry ) {
400
- const isAttributeType = entry.type === 'attribute';
401
- const key = entry.attributeKey;
402
-
403
- return isAttributeType && ( key === 'headingRows' || key === 'colspan' || key === 'rowspan' );
358
+ /**
359
+ * Checks if the differ entry for an attribute change is one of the table's attributes.
360
+ */
361
+ function isTableAttributeEntry(entry) {
362
+ if (entry.type !== 'attribute') {
363
+ return false;
364
+ }
365
+ const key = entry.attributeKey;
366
+ return key === 'headingRows' || key === 'colspan' || key === 'rowspan';
404
367
  }