@ckeditor/ckeditor5-table 36.0.1 → 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,121 +2,94 @@
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/upcasttable
8
- */
9
-
10
5
  import { createEmptyTableCell } from '../utils/common';
11
6
  import { first } from 'ckeditor5/src/utils';
12
-
13
7
  /**
14
8
  * Returns a function that converts the table view representation:
15
9
  *
16
- * <figure class="table"><table>...</table></figure>
10
+ * ```xml
11
+ * <figure class="table"><table>...</table></figure>
12
+ * ```
17
13
  *
18
14
  * to the model representation:
19
15
  *
20
- * <table></table>
21
- *
22
- * @returns {Function}
16
+ * ```xml
17
+ * <table></table>
18
+ * ```
23
19
  */
24
20
  export function upcastTableFigure() {
25
- return dispatcher => {
26
- dispatcher.on( 'element:figure', ( evt, data, conversionApi ) => {
27
- // Do not convert if this is not a "table figure".
28
- if ( !conversionApi.consumable.test( data.viewItem, { name: true, classes: 'table' } ) ) {
29
- return;
30
- }
31
-
32
- // Find a table element inside the figure element.
33
- const viewTable = getViewTableFromFigure( data.viewItem );
34
-
35
- // Do not convert if table element is absent or was already converted.
36
- if ( !viewTable || !conversionApi.consumable.test( viewTable, { name: true } ) ) {
37
- return;
38
- }
39
-
40
- // Consume the figure to prevent other converters from processing it again.
41
- conversionApi.consumable.consume( data.viewItem, { name: true, classes: 'table' } );
42
-
43
- // Convert view table to model table.
44
- const conversionResult = conversionApi.convertItem( viewTable, data.modelCursor );
45
-
46
- // Get table element from conversion result.
47
- const modelTable = first( conversionResult.modelRange.getItems() );
48
-
49
- // When table wasn't successfully converted then finish conversion.
50
- if ( !modelTable ) {
51
- // Revert consumed figure so other features can convert it.
52
- conversionApi.consumable.revert( data.viewItem, { name: true, classes: 'table' } );
53
-
54
- return;
55
- }
56
-
57
- conversionApi.convertChildren( data.viewItem, conversionApi.writer.createPositionAt( modelTable, 'end' ) );
58
- conversionApi.updateConversionResult( modelTable, data );
59
- } );
60
- };
21
+ return (dispatcher) => {
22
+ dispatcher.on('element:figure', (evt, data, conversionApi) => {
23
+ // Do not convert if this is not a "table figure".
24
+ if (!conversionApi.consumable.test(data.viewItem, { name: true, classes: 'table' })) {
25
+ return;
26
+ }
27
+ // Find a table element inside the figure element.
28
+ const viewTable = getViewTableFromFigure(data.viewItem);
29
+ // Do not convert if table element is absent or was already converted.
30
+ if (!viewTable || !conversionApi.consumable.test(viewTable, { name: true })) {
31
+ return;
32
+ }
33
+ // Consume the figure to prevent other converters from processing it again.
34
+ conversionApi.consumable.consume(data.viewItem, { name: true, classes: 'table' });
35
+ // Convert view table to model table.
36
+ const conversionResult = conversionApi.convertItem(viewTable, data.modelCursor);
37
+ // Get table element from conversion result.
38
+ const modelTable = first(conversionResult.modelRange.getItems());
39
+ // When table wasn't successfully converted then finish conversion.
40
+ if (!modelTable) {
41
+ // Revert consumed figure so other features can convert it.
42
+ conversionApi.consumable.revert(data.viewItem, { name: true, classes: 'table' });
43
+ return;
44
+ }
45
+ conversionApi.convertChildren(data.viewItem, conversionApi.writer.createPositionAt(modelTable, 'end'));
46
+ conversionApi.updateConversionResult(modelTable, data);
47
+ });
48
+ };
61
49
  }
62
-
63
50
  /**
64
51
  * View table element to model table element conversion helper.
65
52
  *
66
53
  * This conversion helper converts the table element as well as table rows.
67
54
  *
68
- * @returns {Function} Conversion helper.
55
+ * @returns Conversion helper.
69
56
  */
70
57
  export default function upcastTable() {
71
- return dispatcher => {
72
- dispatcher.on( 'element:table', ( evt, data, conversionApi ) => {
73
- const viewTable = data.viewItem;
74
-
75
- // When element was already consumed then skip it.
76
- if ( !conversionApi.consumable.test( viewTable, { name: true } ) ) {
77
- return;
78
- }
79
-
80
- const { rows, headingRows, headingColumns } = scanTable( viewTable );
81
-
82
- // Only set attributes if values is greater then 0.
83
- const attributes = {};
84
-
85
- if ( headingColumns ) {
86
- attributes.headingColumns = headingColumns;
87
- }
88
-
89
- if ( headingRows ) {
90
- attributes.headingRows = headingRows;
91
- }
92
-
93
- const table = conversionApi.writer.createElement( 'table', attributes );
94
-
95
- if ( !conversionApi.safeInsert( table, data.modelCursor ) ) {
96
- return;
97
- }
98
-
99
- conversionApi.consumable.consume( viewTable, { name: true } );
100
-
101
- // Upcast table rows in proper order (heading rows first).
102
- rows.forEach( row => conversionApi.convertItem( row, conversionApi.writer.createPositionAt( table, 'end' ) ) );
103
-
104
- // Convert everything else.
105
- conversionApi.convertChildren( viewTable, conversionApi.writer.createPositionAt( table, 'end' ) );
106
-
107
- // Create one row and one table cell for empty table.
108
- if ( table.isEmpty ) {
109
- const row = conversionApi.writer.createElement( 'tableRow' );
110
- conversionApi.writer.insert( row, conversionApi.writer.createPositionAt( table, 'end' ) );
111
-
112
- createEmptyTableCell( conversionApi.writer, conversionApi.writer.createPositionAt( row, 'end' ) );
113
- }
114
-
115
- conversionApi.updateConversionResult( table, data );
116
- } );
117
- };
58
+ return (dispatcher) => {
59
+ dispatcher.on('element:table', (evt, data, conversionApi) => {
60
+ const viewTable = data.viewItem;
61
+ // When element was already consumed then skip it.
62
+ if (!conversionApi.consumable.test(viewTable, { name: true })) {
63
+ return;
64
+ }
65
+ const { rows, headingRows, headingColumns } = scanTable(viewTable);
66
+ // Only set attributes if values is greater then 0.
67
+ const attributes = {};
68
+ if (headingColumns) {
69
+ attributes.headingColumns = headingColumns;
70
+ }
71
+ if (headingRows) {
72
+ attributes.headingRows = headingRows;
73
+ }
74
+ const table = conversionApi.writer.createElement('table', attributes);
75
+ if (!conversionApi.safeInsert(table, data.modelCursor)) {
76
+ return;
77
+ }
78
+ conversionApi.consumable.consume(viewTable, { name: true });
79
+ // Upcast table rows in proper order (heading rows first).
80
+ rows.forEach(row => conversionApi.convertItem(row, conversionApi.writer.createPositionAt(table, 'end')));
81
+ // Convert everything else.
82
+ conversionApi.convertChildren(viewTable, conversionApi.writer.createPositionAt(table, 'end'));
83
+ // Create one row and one table cell for empty table.
84
+ if (table.isEmpty) {
85
+ const row = conversionApi.writer.createElement('tableRow');
86
+ conversionApi.writer.insert(row, conversionApi.writer.createPositionAt(table, 'end'));
87
+ createEmptyTableCell(conversionApi.writer, conversionApi.writer.createPositionAt(row, 'end'));
88
+ }
89
+ conversionApi.updateConversionResult(table, data);
90
+ });
91
+ };
118
92
  }
119
-
120
93
  /**
121
94
  * A conversion helper that skips empty <tr> elements from upcasting at the beginning of the table.
122
95
  *
@@ -127,169 +100,141 @@ export default function upcastTable() {
127
100
  * *Note:* Only the first empty rows are removed because they have no meaning and it solves the issue
128
101
  * of an improper table with all empty rows.
129
102
  *
130
- * @returns {Function} Conversion helper.
103
+ * @returns Conversion helper.
131
104
  */
132
105
  export function skipEmptyTableRow() {
133
- return dispatcher => {
134
- dispatcher.on( 'element:tr', ( evt, data ) => {
135
- if ( data.viewItem.isEmpty && data.modelCursor.index == 0 ) {
136
- evt.stop();
137
- }
138
- }, { priority: 'high' } );
139
- };
106
+ return (dispatcher) => {
107
+ dispatcher.on('element:tr', (evt, data) => {
108
+ if (data.viewItem.isEmpty && data.modelCursor.index == 0) {
109
+ evt.stop();
110
+ }
111
+ }, { priority: 'high' });
112
+ };
140
113
  }
141
-
142
114
  /**
143
115
  * A converter that ensures an empty paragraph is inserted in a table cell if no other content was converted.
144
116
  *
145
- * @returns {Function} Conversion helper.
117
+ * @returns Conversion helper.
146
118
  */
147
- export function ensureParagraphInTableCell( elementName ) {
148
- return dispatcher => {
149
- dispatcher.on( `element:${ elementName }`, ( evt, data, { writer } ) => {
150
- // The default converter will create a model range on converted table cell.
151
- if ( !data.modelRange ) {
152
- return;
153
- }
154
-
155
- const tableCell = data.modelRange.start.nodeAfter;
156
- const modelCursor = writer.createPositionAt( tableCell, 0 );
157
-
158
- // Ensure a paragraph in the model for empty table cells for converted table cells.
159
- if ( data.viewItem.isEmpty ) {
160
- writer.insertElement( 'paragraph', modelCursor );
161
-
162
- return;
163
- }
164
-
165
- const childNodes = Array.from( tableCell.getChildren() );
166
-
167
- // In case there are only markers inside the table cell then move them to the paragraph.
168
- if ( childNodes.every( node => node.is( 'element', '$marker' ) ) ) {
169
- const paragraph = writer.createElement( 'paragraph' );
170
-
171
- writer.insert( paragraph, writer.createPositionAt( tableCell, 0 ) );
172
-
173
- for ( const node of childNodes ) {
174
- writer.move( writer.createRangeOn( node ), writer.createPositionAt( paragraph, 'end' ) );
175
- }
176
- }
177
- }, { priority: 'low' } );
178
- };
119
+ export function ensureParagraphInTableCell(elementName) {
120
+ return (dispatcher) => {
121
+ dispatcher.on(`element:${elementName}`, (evt, data, { writer }) => {
122
+ // The default converter will create a model range on converted table cell.
123
+ if (!data.modelRange) {
124
+ return;
125
+ }
126
+ const tableCell = data.modelRange.start.nodeAfter;
127
+ const modelCursor = writer.createPositionAt(tableCell, 0);
128
+ // Ensure a paragraph in the model for empty table cells for converted table cells.
129
+ if (data.viewItem.isEmpty) {
130
+ writer.insertElement('paragraph', modelCursor);
131
+ return;
132
+ }
133
+ const childNodes = Array.from(tableCell.getChildren());
134
+ // In case there are only markers inside the table cell then move them to the paragraph.
135
+ if (childNodes.every(node => node.is('element', '$marker'))) {
136
+ const paragraph = writer.createElement('paragraph');
137
+ writer.insert(paragraph, writer.createPositionAt(tableCell, 0));
138
+ for (const node of childNodes) {
139
+ writer.move(writer.createRangeOn(node), writer.createPositionAt(paragraph, 'end'));
140
+ }
141
+ }
142
+ }, { priority: 'low' });
143
+ };
179
144
  }
180
-
181
- // Get view `<table>` element from the view widget (`<figure>`).
182
- //
183
- // @private
184
- // @param {module:engine/view/element~Element} figureView
185
- // @returns {module:engine/view/element~Element}
186
- function getViewTableFromFigure( figureView ) {
187
- for ( const figureChild of figureView.getChildren() ) {
188
- if ( figureChild.is( 'element', 'table' ) ) {
189
- return figureChild;
190
- }
191
- }
145
+ /**
146
+ * Get view `<table>` element from the view widget (`<figure>`).
147
+ */
148
+ function getViewTableFromFigure(figureView) {
149
+ for (const figureChild of figureView.getChildren()) {
150
+ if (figureChild.is('element', 'table')) {
151
+ return figureChild;
152
+ }
153
+ }
192
154
  }
193
-
194
- // Scans table rows and extracts required metadata from the table:
195
- //
196
- // headingRows - The number of rows that go as table headers.
197
- // headingColumns - The maximum number of row headings.
198
- // rows - Sorted `<tr>` elements as they should go into the model - ie. if `<thead>` is inserted after `<tbody>` in the view.
199
- //
200
- // @private
201
- // @param {module:engine/view/element~Element} viewTable
202
- // @returns {{headingRows, headingColumns, rows}}
203
- function scanTable( viewTable ) {
204
- const tableMeta = {
205
- headingRows: 0,
206
- headingColumns: 0
207
- };
208
-
209
- // The `<tbody>` and `<thead>` sections in the DOM do not have to be in order `<thead>` -> `<tbody>` and there might be more than one
210
- // of them.
211
- // As the model does not have these sections, rows from different sections must be sorted.
212
- // For example, below is a valid HTML table:
213
- //
214
- // <table>
215
- // <tbody><tr><td>2</td></tr></tbody>
216
- // <thead><tr><td>1</td></tr></thead>
217
- // <tbody><tr><td>3</td></tr></tbody>
218
- // </table>
219
- //
220
- // But browsers will render rows in order as: 1 as the heading and 2 and 3 as the body.
221
- const headRows = [];
222
- const bodyRows = [];
223
-
224
- // Currently the editor does not support more then one <thead> section.
225
- // Only the first <thead> from the view will be used as a heading row and the others will be converted to body rows.
226
- let firstTheadElement;
227
-
228
- for ( const tableChild of Array.from( viewTable.getChildren() ) ) {
229
- // Only `<thead>`, `<tbody>` & `<tfoot>` from allowed table children can have `<tr>`s.
230
- // The else is for future purposes (mainly `<caption>`).
231
- if ( tableChild.name === 'tbody' || tableChild.name === 'thead' || tableChild.name === 'tfoot' ) {
232
- // Save the first `<thead>` in the table as table header - all other ones will be converted to table body rows.
233
- if ( tableChild.name === 'thead' && !firstTheadElement ) {
234
- firstTheadElement = tableChild;
235
- }
236
-
237
- // There might be some extra empty text nodes between the `<tr>`s.
238
- // Make sure further code operates on `tr`s only. (#145)
239
- const trs = Array.from( tableChild.getChildren() ).filter( el => el.is( 'element', 'tr' ) );
240
-
241
- for ( const tr of trs ) {
242
- // This <tr> is a child of a first <thead> element.
243
- if ( tr.parent.name === 'thead' && tr.parent === firstTheadElement ) {
244
- tableMeta.headingRows++;
245
- headRows.push( tr );
246
- } else {
247
- bodyRows.push( tr );
248
- // For other rows check how many column headings this row has.
249
-
250
- const headingCols = scanRowForHeadingColumns( tr, tableMeta, firstTheadElement );
251
-
252
- if ( headingCols > tableMeta.headingColumns ) {
253
- tableMeta.headingColumns = headingCols;
254
- }
255
- }
256
- }
257
- }
258
- }
259
-
260
- tableMeta.rows = [ ...headRows, ...bodyRows ];
261
-
262
- return tableMeta;
155
+ /**
156
+ * Scans table rows and extracts required metadata from the table:
157
+ *
158
+ * headingRows - The number of rows that go as table headers.
159
+ * headingColumns - The maximum number of row headings.
160
+ * rows - Sorted `<tr>` elements as they should go into the model - ie. if `<thead>` is inserted after `<tbody>` in the view.
161
+ */
162
+ function scanTable(viewTable) {
163
+ const tableMeta = {
164
+ headingRows: 0,
165
+ headingColumns: 0
166
+ };
167
+ // The `<tbody>` and `<thead>` sections in the DOM do not have to be in order `<thead>` -> `<tbody>` and there might be more than one
168
+ // of them.
169
+ // As the model does not have these sections, rows from different sections must be sorted.
170
+ // For example, below is a valid HTML table:
171
+ //
172
+ // <table>
173
+ // <tbody><tr><td>2</td></tr></tbody>
174
+ // <thead><tr><td>1</td></tr></thead>
175
+ // <tbody><tr><td>3</td></tr></tbody>
176
+ // </table>
177
+ //
178
+ // But browsers will render rows in order as: 1 as the heading and 2 and 3 as the body.
179
+ const headRows = [];
180
+ const bodyRows = [];
181
+ // Currently the editor does not support more then one <thead> section.
182
+ // Only the first <thead> from the view will be used as a heading row and the others will be converted to body rows.
183
+ let firstTheadElement;
184
+ for (const tableChild of Array.from(viewTable.getChildren())) {
185
+ // Only `<thead>`, `<tbody>` & `<tfoot>` from allowed table children can have `<tr>`s.
186
+ // The else is for future purposes (mainly `<caption>`).
187
+ if (tableChild.name === 'tbody' || tableChild.name === 'thead' || tableChild.name === 'tfoot') {
188
+ // Save the first `<thead>` in the table as table header - all other ones will be converted to table body rows.
189
+ if (tableChild.name === 'thead' && !firstTheadElement) {
190
+ firstTheadElement = tableChild;
191
+ }
192
+ // There might be some extra empty text nodes between the `<tr>`s.
193
+ // Make sure further code operates on `tr`s only. (#145)
194
+ const trs = Array.from(tableChild.getChildren()).filter((el) => el.is('element', 'tr'));
195
+ for (const tr of trs) {
196
+ // This <tr> is a child of a first <thead> element.
197
+ if (tr.parent.name === 'thead' && tr.parent === firstTheadElement) {
198
+ tableMeta.headingRows++;
199
+ headRows.push(tr);
200
+ }
201
+ else {
202
+ bodyRows.push(tr);
203
+ // For other rows check how many column headings this row has.
204
+ const headingCols = scanRowForHeadingColumns(tr);
205
+ if (headingCols > tableMeta.headingColumns) {
206
+ tableMeta.headingColumns = headingCols;
207
+ }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ return {
213
+ ...tableMeta,
214
+ rows: [...headRows, ...bodyRows]
215
+ };
263
216
  }
264
-
265
- // Scans a `<tr>` element and its children for metadata:
266
- // - For heading row:
267
- // - Adds this row to either the heading or the body rows.
268
- // - Updates the number of heading rows.
269
- // - For body rows:
270
- // - Calculates the number of column headings.
271
- //
272
- // @private
273
- // @param {module:engine/view/element~Element} tr
274
- // @returns {Number}
275
- function scanRowForHeadingColumns( tr ) {
276
- let headingColumns = 0;
277
- let index = 0;
278
-
279
- // Filter out empty text nodes from tr children.
280
- const children = Array.from( tr.getChildren() )
281
- .filter( child => child.name === 'th' || child.name === 'td' );
282
-
283
- // Count starting adjacent <th> elements of a <tr>.
284
- while ( index < children.length && children[ index ].name === 'th' ) {
285
- const th = children[ index ];
286
-
287
- // Adjust columns calculation by the number of spanned columns.
288
- const colspan = parseInt( th.getAttribute( 'colspan' ) || 1 );
289
-
290
- headingColumns = headingColumns + colspan;
291
- index++;
292
- }
293
-
294
- return headingColumns;
217
+ /**
218
+ * Scans a `<tr>` element and its children for metadata:
219
+ * - For heading row:
220
+ * - Adds this row to either the heading or the body rows.
221
+ * - Updates the number of heading rows.
222
+ * - For body rows:
223
+ * - Calculates the number of column headings.
224
+ */
225
+ function scanRowForHeadingColumns(tr) {
226
+ let headingColumns = 0;
227
+ let index = 0;
228
+ // Filter out empty text nodes from tr children.
229
+ const children = Array.from(tr.getChildren())
230
+ .filter(child => child.name === 'th' || child.name === 'td');
231
+ // Count starting adjacent <th> elements of a <tr>.
232
+ while (index < children.length && children[index].name === 'th') {
233
+ const th = children[index];
234
+ // Adjust columns calculation by the number of spanned columns.
235
+ const colspan = parseInt(th.getAttribute('colspan') || '1');
236
+ headingColumns = headingColumns + colspan;
237
+ index++;
238
+ }
239
+ return headingColumns;
295
240
  }
package/src/index.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, 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
+ * @module table
7
+ */
8
+ export { default as PlainTableOutput } from './plaintableoutput';
9
+ export { default as Table } from './table';
10
+ export { default as TableEditing } from './tableediting';
11
+ export { default as TableUI } from './tableui';
12
+ export { default as TableToolbar } from './tabletoolbar';
13
+ export { default as TableCellProperties } from './tablecellproperties';
14
+ export { default as TableCellPropertiesEditing } from './tablecellproperties/tablecellpropertiesediting';
15
+ export { default as TableCellPropertiesUI } from './tablecellproperties/tablecellpropertiesui';
16
+ export { default as TableCellWidthEditing } from './tablecellwidth/tablecellwidthediting';
17
+ export { default as TableProperties } from './tableproperties';
18
+ export { default as TablePropertiesEditing } from './tableproperties/tablepropertiesediting';
19
+ export { default as TablePropertiesUI } from './tableproperties/tablepropertiesui';
20
+ export { default as TableCaption } from './tablecaption';
21
+ export { default as TableCaptionEditing } from './tablecaption/tablecaptionediting';
22
+ export { default as TableCaptionUI } from './tablecaption/tablecaptionui';
23
+ export { default as TableClipboard } from './tableclipboard';
24
+ export { default as TableMouse } from './tablemouse';
25
+ export { default as TableKeyboard } from './tablekeyboard';
26
+ export { default as TableSelection } from './tableselection';
27
+ export { default as TableUtils } from './tableutils';
28
+ export { default as TableColumnResize } from './tablecolumnresize';
29
+ export { default as TableColumnResizeEditing } from './tablecolumnresize/tablecolumnresizeediting';
package/src/index.js CHANGED
@@ -2,11 +2,9 @@
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
5
  /**
7
6
  * @module table
8
7
  */
9
-
10
8
  export { default as PlainTableOutput } from './plaintableoutput';
11
9
  export { default as Table } from './table';
12
10
  export { default as TableEditing } from './tableediting';
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, 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
+ * @module table/plaintableoutput
7
+ */
8
+ import { Plugin, type PluginDependencies } from 'ckeditor5/src/core';
9
+ /**
10
+ * The plain table output feature.
11
+ */
12
+ export default class PlainTableOutput extends Plugin {
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ static get pluginName(): 'PlainTableOutput';
17
+ /**
18
+ * @inheritDoc
19
+ */
20
+ static get requires(): PluginDependencies;
21
+ /**
22
+ * @inheritDoc
23
+ */
24
+ init(): void;
25
+ }
26
+ declare module '@ckeditor/ckeditor5-core' {
27
+ interface PluginsMap {
28
+ [PlainTableOutput.pluginName]: PlainTableOutput;
29
+ }
30
+ }