@ckeditor/ckeditor5-table 47.2.0-alpha.7 → 47.3.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.
- package/LICENSE.md +4 -4
- package/build/table.js +2 -2
- package/build/translations/af.js +1 -1
- package/build/translations/ar.js +1 -1
- package/build/translations/ast.js +1 -1
- package/build/translations/az.js +1 -1
- package/build/translations/be.js +1 -1
- package/build/translations/bg.js +1 -1
- package/build/translations/bn.js +1 -1
- package/build/translations/bs.js +1 -1
- package/build/translations/ca.js +1 -1
- package/build/translations/cs.js +1 -1
- package/build/translations/da.js +1 -1
- package/build/translations/de-ch.js +1 -1
- package/build/translations/de.js +1 -1
- package/build/translations/el.js +1 -1
- package/build/translations/en-au.js +1 -1
- package/build/translations/en-gb.js +1 -1
- package/build/translations/eo.js +1 -1
- package/build/translations/es-co.js +1 -1
- package/build/translations/es.js +1 -1
- package/build/translations/et.js +1 -1
- package/build/translations/eu.js +1 -1
- package/build/translations/fa.js +1 -1
- package/build/translations/fi.js +1 -1
- package/build/translations/fr.js +1 -1
- package/build/translations/gl.js +1 -1
- package/build/translations/gu.js +1 -1
- package/build/translations/he.js +1 -1
- package/build/translations/hi.js +1 -1
- package/build/translations/hr.js +1 -1
- package/build/translations/hu.js +1 -1
- package/build/translations/hy.js +1 -1
- package/build/translations/id.js +1 -1
- package/build/translations/it.js +1 -1
- package/build/translations/ja.js +1 -1
- package/build/translations/jv.js +1 -1
- package/build/translations/kk.js +1 -1
- package/build/translations/km.js +1 -1
- package/build/translations/kn.js +1 -1
- package/build/translations/ko.js +1 -1
- package/build/translations/ku.js +1 -1
- package/build/translations/lt.js +1 -1
- package/build/translations/lv.js +1 -1
- package/build/translations/ms.js +1 -1
- package/build/translations/nb.js +1 -1
- package/build/translations/ne.js +1 -1
- package/build/translations/nl.js +1 -1
- package/build/translations/no.js +1 -1
- package/build/translations/oc.js +1 -1
- package/build/translations/pl.js +1 -1
- package/build/translations/pt-br.js +1 -1
- package/build/translations/pt.js +1 -1
- package/build/translations/ro.js +1 -1
- package/build/translations/ru.js +1 -1
- package/build/translations/si.js +1 -1
- package/build/translations/sk.js +1 -1
- package/build/translations/sl.js +1 -1
- package/build/translations/sq.js +1 -1
- package/build/translations/sr-latn.js +1 -1
- package/build/translations/sr.js +1 -1
- package/build/translations/sv.js +1 -1
- package/build/translations/th.js +1 -1
- package/build/translations/ti.js +1 -1
- package/build/translations/tk.js +1 -1
- package/build/translations/tr.js +1 -1
- package/build/translations/tt.js +1 -1
- package/build/translations/ug.js +1 -1
- package/build/translations/uk.js +1 -1
- package/build/translations/ur.js +1 -1
- package/build/translations/uz.js +1 -1
- package/build/translations/vi.js +1 -1
- package/build/translations/zh-cn.js +1 -1
- package/build/translations/zh.js +1 -1
- package/dist/index-content.css +32 -3
- package/dist/index-editor.css +181 -88
- package/dist/index.css +302 -160
- package/dist/index.css.map +1 -1
- package/dist/index.js +11215 -8546
- package/dist/index.js.map +1 -1
- package/dist/translations/af.js +1 -1
- package/dist/translations/af.umd.js +1 -1
- package/dist/translations/ar.js +1 -1
- package/dist/translations/ar.umd.js +1 -1
- package/dist/translations/ast.js +1 -1
- package/dist/translations/ast.umd.js +1 -1
- package/dist/translations/az.js +1 -1
- package/dist/translations/az.umd.js +1 -1
- package/dist/translations/be.js +1 -1
- package/dist/translations/be.umd.js +1 -1
- package/dist/translations/bg.js +1 -1
- package/dist/translations/bg.umd.js +1 -1
- package/dist/translations/bn.js +1 -1
- package/dist/translations/bn.umd.js +1 -1
- package/dist/translations/bs.js +1 -1
- package/dist/translations/bs.umd.js +1 -1
- package/dist/translations/ca.js +1 -1
- package/dist/translations/ca.umd.js +1 -1
- package/dist/translations/cs.js +1 -1
- package/dist/translations/cs.umd.js +1 -1
- package/dist/translations/da.js +1 -1
- package/dist/translations/da.umd.js +1 -1
- package/dist/translations/de-ch.js +1 -1
- package/dist/translations/de-ch.umd.js +1 -1
- package/dist/translations/de.js +1 -1
- package/dist/translations/de.umd.js +1 -1
- package/dist/translations/el.js +1 -1
- package/dist/translations/el.umd.js +1 -1
- package/dist/translations/en-au.js +1 -1
- package/dist/translations/en-au.umd.js +1 -1
- package/dist/translations/en-gb.js +1 -1
- package/dist/translations/en-gb.umd.js +1 -1
- package/dist/translations/en.js +1 -1
- package/dist/translations/en.umd.js +1 -1
- package/dist/translations/eo.js +1 -1
- package/dist/translations/eo.umd.js +1 -1
- package/dist/translations/es-co.js +1 -1
- package/dist/translations/es-co.umd.js +1 -1
- package/dist/translations/es.js +1 -1
- package/dist/translations/es.umd.js +1 -1
- package/dist/translations/et.js +1 -1
- package/dist/translations/et.umd.js +1 -1
- package/dist/translations/eu.js +1 -1
- package/dist/translations/eu.umd.js +1 -1
- package/dist/translations/fa.js +1 -1
- package/dist/translations/fa.umd.js +1 -1
- package/dist/translations/fi.js +1 -1
- package/dist/translations/fi.umd.js +1 -1
- package/dist/translations/fr.js +1 -1
- package/dist/translations/fr.umd.js +1 -1
- package/dist/translations/gl.js +1 -1
- package/dist/translations/gl.umd.js +1 -1
- package/dist/translations/gu.js +1 -1
- package/dist/translations/gu.umd.js +1 -1
- package/dist/translations/he.js +1 -1
- package/dist/translations/he.umd.js +1 -1
- package/dist/translations/hi.js +1 -1
- package/dist/translations/hi.umd.js +1 -1
- package/dist/translations/hr.js +1 -1
- package/dist/translations/hr.umd.js +1 -1
- package/dist/translations/hu.js +1 -1
- package/dist/translations/hu.umd.js +1 -1
- package/dist/translations/hy.js +1 -1
- package/dist/translations/hy.umd.js +1 -1
- package/dist/translations/id.js +1 -1
- package/dist/translations/id.umd.js +1 -1
- package/dist/translations/it.js +1 -1
- package/dist/translations/it.umd.js +1 -1
- package/dist/translations/ja.js +1 -1
- package/dist/translations/ja.umd.js +1 -1
- package/dist/translations/jv.js +1 -1
- package/dist/translations/jv.umd.js +1 -1
- package/dist/translations/kk.js +1 -1
- package/dist/translations/kk.umd.js +1 -1
- package/dist/translations/km.js +1 -1
- package/dist/translations/km.umd.js +1 -1
- package/dist/translations/kn.js +1 -1
- package/dist/translations/kn.umd.js +1 -1
- package/dist/translations/ko.js +1 -1
- package/dist/translations/ko.umd.js +1 -1
- package/dist/translations/ku.js +1 -1
- package/dist/translations/ku.umd.js +1 -1
- package/dist/translations/lt.js +1 -1
- package/dist/translations/lt.umd.js +1 -1
- package/dist/translations/lv.js +1 -1
- package/dist/translations/lv.umd.js +1 -1
- package/dist/translations/ms.js +1 -1
- package/dist/translations/ms.umd.js +1 -1
- package/dist/translations/nb.js +1 -1
- package/dist/translations/nb.umd.js +1 -1
- package/dist/translations/ne.js +1 -1
- package/dist/translations/ne.umd.js +1 -1
- package/dist/translations/nl.js +1 -1
- package/dist/translations/nl.umd.js +1 -1
- package/dist/translations/no.js +1 -1
- package/dist/translations/no.umd.js +1 -1
- package/dist/translations/oc.js +1 -1
- package/dist/translations/oc.umd.js +1 -1
- package/dist/translations/pl.js +1 -1
- package/dist/translations/pl.umd.js +1 -1
- package/dist/translations/pt-br.js +1 -1
- package/dist/translations/pt-br.umd.js +1 -1
- package/dist/translations/pt.js +1 -1
- package/dist/translations/pt.umd.js +1 -1
- package/dist/translations/ro.js +1 -1
- package/dist/translations/ro.umd.js +1 -1
- package/dist/translations/ru.js +1 -1
- package/dist/translations/ru.umd.js +1 -1
- package/dist/translations/si.js +1 -1
- package/dist/translations/si.umd.js +1 -1
- package/dist/translations/sk.js +1 -1
- package/dist/translations/sk.umd.js +1 -1
- package/dist/translations/sl.js +1 -1
- package/dist/translations/sl.umd.js +1 -1
- package/dist/translations/sq.js +1 -1
- package/dist/translations/sq.umd.js +1 -1
- package/dist/translations/sr-latn.js +1 -1
- package/dist/translations/sr-latn.umd.js +1 -1
- package/dist/translations/sr.js +1 -1
- package/dist/translations/sr.umd.js +1 -1
- package/dist/translations/sv.js +1 -1
- package/dist/translations/sv.umd.js +1 -1
- package/dist/translations/th.js +1 -1
- package/dist/translations/th.umd.js +1 -1
- package/dist/translations/ti.js +1 -1
- package/dist/translations/ti.umd.js +1 -1
- package/dist/translations/tk.js +1 -1
- package/dist/translations/tk.umd.js +1 -1
- package/dist/translations/tr.js +1 -1
- package/dist/translations/tr.umd.js +1 -1
- package/dist/translations/tt.js +1 -1
- package/dist/translations/tt.umd.js +1 -1
- package/dist/translations/ug.js +1 -1
- package/dist/translations/ug.umd.js +1 -1
- package/dist/translations/uk.js +1 -1
- package/dist/translations/uk.umd.js +1 -1
- package/dist/translations/ur.js +1 -1
- package/dist/translations/ur.umd.js +1 -1
- package/dist/translations/uz.js +1 -1
- package/dist/translations/uz.umd.js +1 -1
- package/dist/translations/vi.js +1 -1
- package/dist/translations/vi.umd.js +1 -1
- package/dist/translations/zh-cn.js +1 -1
- package/dist/translations/zh-cn.umd.js +1 -1
- package/dist/translations/zh.js +1 -1
- package/dist/translations/zh.umd.js +1 -1
- package/lang/contexts.json +6 -0
- package/lang/translations/af.po +24 -0
- package/lang/translations/ar.po +24 -0
- package/lang/translations/ast.po +24 -0
- package/lang/translations/az.po +24 -0
- package/lang/translations/be.po +24 -0
- package/lang/translations/bg.po +24 -0
- package/lang/translations/bn.po +24 -0
- package/lang/translations/bs.po +24 -0
- package/lang/translations/ca.po +24 -0
- package/lang/translations/cs.po +24 -0
- package/lang/translations/da.po +24 -0
- package/lang/translations/de-ch.po +24 -0
- package/lang/translations/de.po +24 -0
- package/lang/translations/el.po +24 -0
- package/lang/translations/en-au.po +24 -0
- package/lang/translations/en-gb.po +24 -0
- package/lang/translations/en.po +24 -0
- package/lang/translations/eo.po +24 -0
- package/lang/translations/es-co.po +24 -0
- package/lang/translations/es.po +24 -0
- package/lang/translations/et.po +24 -0
- package/lang/translations/eu.po +24 -0
- package/lang/translations/fa.po +24 -0
- package/lang/translations/fi.po +24 -0
- package/lang/translations/fr.po +24 -0
- package/lang/translations/gl.po +24 -0
- package/lang/translations/gu.po +24 -0
- package/lang/translations/he.po +24 -0
- package/lang/translations/hi.po +24 -0
- package/lang/translations/hr.po +24 -0
- package/lang/translations/hu.po +24 -0
- package/lang/translations/hy.po +24 -0
- package/lang/translations/id.po +24 -0
- package/lang/translations/it.po +24 -0
- package/lang/translations/ja.po +24 -0
- package/lang/translations/jv.po +24 -0
- package/lang/translations/kk.po +24 -0
- package/lang/translations/km.po +24 -0
- package/lang/translations/kn.po +24 -0
- package/lang/translations/ko.po +24 -0
- package/lang/translations/ku.po +24 -0
- package/lang/translations/lt.po +24 -0
- package/lang/translations/lv.po +24 -0
- package/lang/translations/ms.po +24 -0
- package/lang/translations/nb.po +24 -0
- package/lang/translations/ne.po +24 -0
- package/lang/translations/nl.po +24 -0
- package/lang/translations/no.po +24 -0
- package/lang/translations/oc.po +24 -0
- package/lang/translations/pl.po +24 -0
- package/lang/translations/pt-br.po +24 -0
- package/lang/translations/pt.po +24 -0
- package/lang/translations/ro.po +24 -0
- package/lang/translations/ru.po +24 -0
- package/lang/translations/si.po +24 -0
- package/lang/translations/sk.po +24 -0
- package/lang/translations/sl.po +24 -0
- package/lang/translations/sq.po +24 -0
- package/lang/translations/sr-latn.po +24 -0
- package/lang/translations/sr.po +24 -0
- package/lang/translations/sv.po +24 -0
- package/lang/translations/th.po +24 -0
- package/lang/translations/ti.po +24 -0
- package/lang/translations/tk.po +24 -0
- package/lang/translations/tr.po +24 -0
- package/lang/translations/tt.po +24 -0
- package/lang/translations/ug.po +24 -0
- package/lang/translations/uk.po +24 -0
- package/lang/translations/ur.po +24 -0
- package/lang/translations/uz.po +24 -0
- package/lang/translations/vi.po +24 -0
- package/lang/translations/zh-cn.po +24 -0
- package/lang/translations/zh.po +24 -0
- package/package.json +9 -9
- package/src/augmentation.d.ts +21 -0
- package/src/converters/downcast.d.ts +26 -1
- package/src/converters/downcast.js +129 -3
- package/src/converters/tableproperties.d.ts +46 -2
- package/src/converters/tableproperties.js +218 -1
- package/src/converters/upcasttable.js +147 -36
- package/src/index.d.ts +5 -1
- package/src/index.js +5 -0
- package/src/plaintableoutput.js +0 -91
- package/src/tablecellproperties/tablecellpropertiesediting.js +7 -4
- package/src/tablecellproperties/tablecellpropertiesuiexperimental.d.ts +128 -0
- package/src/tablecellproperties/tablecellpropertiesuiexperimental.js +386 -0
- package/src/tablecellproperties/ui/tablecellpropertiesviewexperimental.d.ts +237 -0
- package/src/tablecellproperties/ui/tablecellpropertiesviewexperimental.js +633 -0
- package/src/tableconfig.d.ts +187 -10
- package/src/tableediting.d.ts +5 -0
- package/src/tableediting.js +28 -1
- package/src/tablelayout/tablelayoutediting.js +8 -2
- package/src/tableproperties/tablepropertiesediting.js +255 -8
- package/src/tableproperties/tablepropertiesuiexperimental.d.ts +136 -0
- package/src/tableproperties/tablepropertiesuiexperimental.js +375 -0
- package/src/tableproperties/ui/tablepropertiesviewexperimental.d.ts +216 -0
- package/src/tableproperties/ui/tablepropertiesviewexperimental.js +544 -0
- package/src/utils/structure.d.ts +5 -1
- package/src/utils/structure.js +10 -0
- package/src/utils/ui/table-propertiesexperimental.d.ts +215 -0
- package/src/utils/ui/table-propertiesexperimental.js +391 -0
- package/theme/formrow-experimental.css +15 -0
- package/theme/table.css +2 -2
- package/theme/tableform-experimental.css +61 -0
- package/theme/tableproperties-experimental.css +78 -0
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
4
4
|
*/
|
|
5
5
|
import { createEmptyTableCell } from '../utils/common.js';
|
|
6
|
+
import { getViewTableFromWrapper } from '../utils/structure.js';
|
|
6
7
|
import { first } from 'ckeditor5/src/utils.js';
|
|
7
8
|
/**
|
|
8
9
|
* Returns a function that converts the table view representation:
|
|
@@ -27,7 +28,7 @@ export function upcastTableFigure() {
|
|
|
27
28
|
return;
|
|
28
29
|
}
|
|
29
30
|
// Find a table element inside the figure element.
|
|
30
|
-
const viewTable =
|
|
31
|
+
const viewTable = getViewTableFromWrapper(data.viewItem);
|
|
31
32
|
// Do not convert if table element is absent or was already converted.
|
|
32
33
|
if (!viewTable || !conversionApi.consumable.test(viewTable, { name: true })) {
|
|
33
34
|
return;
|
|
@@ -152,16 +153,6 @@ export function ensureParagraphInTableCell(elementName) {
|
|
|
152
153
|
}, { priority: 'low' });
|
|
153
154
|
};
|
|
154
155
|
}
|
|
155
|
-
/**
|
|
156
|
-
* Get view `<table>` element from the view widget (`<figure>`).
|
|
157
|
-
*/
|
|
158
|
-
function getViewTableFromFigure(figureView) {
|
|
159
|
-
for (const figureChild of figureView.getChildren()) {
|
|
160
|
-
if (figureChild.is('element', 'table')) {
|
|
161
|
-
return figureChild;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
156
|
/**
|
|
166
157
|
* Scans table rows and extracts required metadata from the table:
|
|
167
158
|
*
|
|
@@ -223,11 +214,6 @@ function scanTable(viewTable) {
|
|
|
223
214
|
}
|
|
224
215
|
else {
|
|
225
216
|
bodyRows.push(tr);
|
|
226
|
-
// For other rows check how many column headings this row has.
|
|
227
|
-
const headingCols = scanRowForHeadingColumns(tr);
|
|
228
|
-
if (!headingColumns || headingCols < headingColumns) {
|
|
229
|
-
headingColumns = headingCols;
|
|
230
|
-
}
|
|
231
217
|
}
|
|
232
218
|
// We use the maximum number of columns to avoid false positives when detecting
|
|
233
219
|
// multiple rows with single column within `rowspan`. Without it the last row of `rowspan=3`
|
|
@@ -235,6 +221,22 @@ function scanTable(viewTable) {
|
|
|
235
221
|
maxPrevColumns = Math.max(maxPrevColumns || 0, trColumns.length);
|
|
236
222
|
}
|
|
237
223
|
}
|
|
224
|
+
// Generate the cell matrix so we can calculate the heading columns.
|
|
225
|
+
const bodyMatrix = generateCellMatrix(bodyRows);
|
|
226
|
+
for (const rowSlots of bodyMatrix) {
|
|
227
|
+
// Look for the first non-`<th>` entry (either a `<td>` or a missing cell).
|
|
228
|
+
let index = 0;
|
|
229
|
+
while (index < rowSlots.length) {
|
|
230
|
+
if (rowSlots[index]?.name !== 'th') {
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
index += 1;
|
|
234
|
+
}
|
|
235
|
+
// Update headingColumns.
|
|
236
|
+
if (!headingColumns || index < headingColumns) {
|
|
237
|
+
headingColumns = index;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
238
240
|
return {
|
|
239
241
|
headingRows,
|
|
240
242
|
headingColumns: headingColumns || 0,
|
|
@@ -242,26 +244,135 @@ function scanTable(viewTable) {
|
|
|
242
244
|
};
|
|
243
245
|
}
|
|
244
246
|
/**
|
|
245
|
-
*
|
|
246
|
-
* -
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
247
|
+
* Takes an array of `<tr>` elements and generates a "matrix" (square
|
|
248
|
+
* two-dimensional array) describing which `<th>`s and `<td>`s fill which
|
|
249
|
+
* "slots", factoring in `rowspan`s and `colspan`s. For example, given
|
|
250
|
+
*
|
|
251
|
+
* ```xml
|
|
252
|
+
* <table>
|
|
253
|
+
* <tr> <td>11</td> <td rowspan="2">12-22</td> <td>13</td> </tr>
|
|
254
|
+
* <tr> <td>21</td> <td>23</td> </tr>
|
|
255
|
+
* <tr> <td colspan="2">31-32</td> <td>33</rd> </tr>
|
|
256
|
+
* </table>
|
|
257
|
+
* ```
|
|
258
|
+
*
|
|
259
|
+
* The result would be (with cell elements' text content in place of the element
|
|
260
|
+
* objects for readability):
|
|
261
|
+
*
|
|
262
|
+
* ```js
|
|
263
|
+
* [
|
|
264
|
+
* [ '11', '12-22', '13' ],
|
|
265
|
+
* [ '21', '12-22', '23' ],
|
|
266
|
+
* [ '31-32', '31-32', '33' ],
|
|
267
|
+
* ]
|
|
268
|
+
* ```
|
|
269
|
+
*
|
|
270
|
+
* This allows for a computation of heading columns that factors in the case
|
|
271
|
+
* where a cell from a previous rows with a `rowspan` attribute effectively adds
|
|
272
|
+
* an additional header cell to a subsequent row.
|
|
273
|
+
*
|
|
274
|
+
* There are also cases where cells are "missing" from a row. A simple one is
|
|
275
|
+
* the case where a row simply has fewer cells than another row in the same
|
|
276
|
+
* table. But another is one where a row has a cell with a `rowspan` that
|
|
277
|
+
* effectively adds a cell to a subsequent row "off the end" of the row. In this
|
|
278
|
+
* case, there will be a `null` value instead of an element object in that
|
|
279
|
+
* position. For example,
|
|
280
|
+
*
|
|
281
|
+
* ```xml
|
|
282
|
+
* <table>
|
|
283
|
+
* <tr> <td>11</td> <td>12</td> <td rowspan="2">13-23</td> </tr>
|
|
284
|
+
* <tr> <td>21</td> </tr>
|
|
285
|
+
* <tr> <td>31</td> </tr>
|
|
286
|
+
* </table>
|
|
287
|
+
* ```
|
|
288
|
+
*
|
|
289
|
+
* would result in
|
|
290
|
+
*
|
|
291
|
+
* ```js
|
|
292
|
+
* [
|
|
293
|
+
* [ '11', '12', '13-23' ],
|
|
294
|
+
* [ '21', null, '13-23' ],
|
|
295
|
+
* [ '31', null, null ]
|
|
296
|
+
* ]
|
|
297
|
+
* ```
|
|
298
|
+
*
|
|
299
|
+
* @param trs the array of `<tr>` elements
|
|
300
|
+
* @returns the cell matrix
|
|
251
301
|
*/
|
|
252
|
-
function
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
302
|
+
function generateCellMatrix(trs) {
|
|
303
|
+
// As we iterate, we keep track of cells with rowspans >1 so later rows can
|
|
304
|
+
// factor them in. This trackes any such cells from previous rows.
|
|
305
|
+
let prevRowspans = new Map();
|
|
306
|
+
// This is the maximum number of columns we've encountered.
|
|
307
|
+
let maxColumns = 0;
|
|
308
|
+
const slots = trs.map(tr => {
|
|
309
|
+
// This will be the slots that are in this row, including cells from
|
|
310
|
+
// previous rows with a big enough "rowspan" to affect this row.
|
|
311
|
+
const curSlots = [];
|
|
312
|
+
// Get the cell elements
|
|
313
|
+
const children = Array.from(tr.getChildren())
|
|
314
|
+
.filter(child => child.name === 'th' || child.name === 'td');
|
|
315
|
+
// This will be any cells in this row that have a rowspan >1, so we can
|
|
316
|
+
// combine it with `prevRowspans` when we're done processing this row.
|
|
317
|
+
const curRowspans = new Map();
|
|
318
|
+
// We need to process all the cells in this row, but also previous rows'
|
|
319
|
+
// cells with rowspans might add additional slots to the end of this row, so
|
|
320
|
+
// we need to iterate until we've both consumed all the children _and_
|
|
321
|
+
// filled out slots to the max number of columns we've encountered so far.
|
|
322
|
+
while (children.length || curSlots.length < maxColumns) {
|
|
323
|
+
const rowSpan = prevRowspans.get(curSlots.length);
|
|
324
|
+
if (rowSpan && rowSpan.remaining > 0) {
|
|
325
|
+
// We have a cell at this index in a previous row whose rowspan extends
|
|
326
|
+
// it into this row, so we insert a copy of it here.
|
|
327
|
+
curSlots.push(rowSpan.cell);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
// See if we have more cells in the row.
|
|
331
|
+
const cell = children.shift();
|
|
332
|
+
if (cell) {
|
|
333
|
+
// We do, so process it
|
|
334
|
+
const colspan = parseInt(cell.getAttribute('colspan') || '1');
|
|
335
|
+
const rowspan = parseInt(cell.getAttribute('rowspan') || '1');
|
|
336
|
+
// Process this cell as many times as needed according to its colspan.
|
|
337
|
+
for (let i = 0; i < colspan; i++) {
|
|
338
|
+
// if we have a >1 rowspan, create a record in the rowSpans map for
|
|
339
|
+
// this column index keeping track of it.
|
|
340
|
+
if (rowspan > 1) {
|
|
341
|
+
curRowspans.set(curSlots.length, { cell, remaining: rowspan - 1 });
|
|
342
|
+
}
|
|
343
|
+
curSlots.push(cell);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
// No remaining children in this row, so no cell in this slot.
|
|
348
|
+
curSlots.push(null);
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
// Now update the row spans. In weird edge cases where colspan and rowspan
|
|
354
|
+
// conflict, we can end up with a cell in a column in this row that
|
|
355
|
+
// "truncates" a row-spanning cell from a previous column, so make sure in
|
|
356
|
+
// those cases, the value in `curRowspans` always "wins". We do this by
|
|
357
|
+
// copying (and decrementing) values from `prevRowspans` into `curRowspans`
|
|
358
|
+
// as long as there is no conflict, and then re-assigning `prevRowspans`.
|
|
359
|
+
for (const [index, entry] of prevRowspans.entries()) {
|
|
360
|
+
entry.remaining -= 1;
|
|
361
|
+
if (entry.remaining > 0 && !curRowspans.has(index)) {
|
|
362
|
+
curRowspans.set(index, entry);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
prevRowspans = curRowspans;
|
|
366
|
+
// Finally, update `maxColumns`.
|
|
367
|
+
maxColumns = Math.max(maxColumns, curSlots.length);
|
|
368
|
+
return curSlots;
|
|
369
|
+
});
|
|
370
|
+
// Now expand any rows that have fewer than `maxColumns` with nulls so we have
|
|
371
|
+
// a proper matrix.
|
|
372
|
+
for (const rowSlots of slots) {
|
|
373
|
+
while (rowSlots.length < maxColumns) {
|
|
374
|
+
rowSlots.push(null);
|
|
375
|
+
}
|
|
265
376
|
}
|
|
266
|
-
return
|
|
377
|
+
return slots;
|
|
267
378
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -34,6 +34,10 @@ export { TableUtils, type TableIndexesObject } from './tableutils.js';
|
|
|
34
34
|
export { TableColumnResize } from './tablecolumnresize.js';
|
|
35
35
|
export { TableColumnResizeEditing } from './tablecolumnresize/tablecolumnresizeediting.js';
|
|
36
36
|
export { TableWidthsCommand, type TableWidthsCommandOptions } from './tablecolumnresize/tablewidthscommand.js';
|
|
37
|
+
export { TablePropertiesUIExperimental } from './tableproperties/tablepropertiesuiexperimental.js';
|
|
38
|
+
export { TablePropertiesViewExperimental, type TablePropertiesViewOptionsExperimental } from './tableproperties/ui/tablepropertiesviewexperimental.js';
|
|
39
|
+
export { TableCellPropertiesUIExperimental } from './tablecellproperties/tablecellpropertiesuiexperimental.js';
|
|
40
|
+
export { TableCellPropertiesViewExperimental, type TableCellPropertiesViewOptionsExperimental } from './tablecellproperties/ui/tablecellpropertiesviewexperimental.js';
|
|
37
41
|
export { InsertColumnCommand } from './commands/insertcolumncommand.js';
|
|
38
42
|
export { InsertRowCommand } from './commands/insertrowcommand.js';
|
|
39
43
|
export { InsertTableCommand } from './commands/inserttablecommand.js';
|
|
@@ -68,7 +72,7 @@ export { TableHeightCommand } from './tableproperties/commands/tableheightcomman
|
|
|
68
72
|
export { TableWidthCommand } from './tableproperties/commands/tablewidthcommand.js';
|
|
69
73
|
export { TablePropertyCommand, type TablePropertyCommandExecuteOptions } from './tableproperties/commands/tablepropertycommand.js';
|
|
70
74
|
export type { ViewDocumentTableMouseMoveEvent, ViewDocumentTableMouseLeaveEvent } from './tablemouse/mouseeventsobserver.js';
|
|
71
|
-
export type { TableConfig, TablePropertiesConfig, TablePropertiesOptions, TableCellPropertiesConfig, TableColorConfig, TableCellPropertiesOptions, TableLayoutConfig, TableCaptionConfig, TableType } from './tableconfig.js';
|
|
75
|
+
export type { TableConfig, TableAlignmentConfig, TablePropertiesConfig, TablePropertiesOptions, TableCellPropertiesConfig, TableColorConfig, TableCellPropertiesOptions, TableLayoutConfig, TableCaptionConfig, TableType } from './tableconfig.js';
|
|
72
76
|
export { downcastTable as _downcastTable, downcastRow as _downcastTableRow, downcastCell as _downcastTableCell, convertParagraphInTableCell as _convertParagraphInTableCell, isSingleParagraphWithoutAttributes as _isSingleTableParagraphWithoutAttributes } from './converters/downcast.js';
|
|
73
77
|
export type { DowncastTableOptions as _DowncastTableOptions } from './converters/downcast.js';
|
|
74
78
|
export { injectTableCaptionPostFixer as _injectTableCaptionPostFixer } from './converters/table-caption-post-fixer.js';
|
package/src/index.js
CHANGED
|
@@ -34,6 +34,11 @@ export { TableUtils } from './tableutils.js';
|
|
|
34
34
|
export { TableColumnResize } from './tablecolumnresize.js';
|
|
35
35
|
export { TableColumnResizeEditing } from './tablecolumnresize/tablecolumnresizeediting.js';
|
|
36
36
|
export { TableWidthsCommand } from './tablecolumnresize/tablewidthscommand.js';
|
|
37
|
+
// [experimental] Remove in the v48.
|
|
38
|
+
export { TablePropertiesUIExperimental } from './tableproperties/tablepropertiesuiexperimental.js';
|
|
39
|
+
export { TablePropertiesViewExperimental } from './tableproperties/ui/tablepropertiesviewexperimental.js';
|
|
40
|
+
export { TableCellPropertiesUIExperimental } from './tablecellproperties/tablecellpropertiesuiexperimental.js';
|
|
41
|
+
export { TableCellPropertiesViewExperimental } from './tablecellproperties/ui/tablecellpropertiesviewexperimental.js';
|
|
37
42
|
export { InsertColumnCommand } from './commands/insertcolumncommand.js';
|
|
38
43
|
export { InsertRowCommand } from './commands/insertrowcommand.js';
|
|
39
44
|
export { InsertTableCommand } from './commands/inserttablecommand.js';
|
package/src/plaintableoutput.js
CHANGED
|
@@ -37,28 +37,6 @@ export class PlainTableOutput extends Plugin {
|
|
|
37
37
|
*/
|
|
38
38
|
init() {
|
|
39
39
|
const editor = this.editor;
|
|
40
|
-
// Override default table data downcast converter.
|
|
41
|
-
editor.conversion.for('dataDowncast').elementToStructure({
|
|
42
|
-
model: 'table',
|
|
43
|
-
view: downcastTableElement,
|
|
44
|
-
converterPriority: 'high'
|
|
45
|
-
});
|
|
46
|
-
// Make sure table <caption> is downcasted into <caption> in the data pipeline when necessary.
|
|
47
|
-
if (editor.plugins.has('TableCaption')) {
|
|
48
|
-
editor.conversion.for('dataDowncast').elementToElement({
|
|
49
|
-
model: 'caption',
|
|
50
|
-
view: (modelElement, { writer }) => {
|
|
51
|
-
if (modelElement.parent.name === 'table') {
|
|
52
|
-
return writer.createContainerElement('caption');
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
converterPriority: 'high'
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
// Handle border-style, border-color, border-width and background-color table attributes.
|
|
59
|
-
if (editor.plugins.has('TableProperties')) {
|
|
60
|
-
downcastTableBorderAndBackgroundAttributes(editor);
|
|
61
|
-
}
|
|
62
40
|
editor.conversion.for('upcast').add(dispatcher => {
|
|
63
41
|
dispatcher.on('element:table', (evt, data, conversionApi) => {
|
|
64
42
|
// It's not necessary to upcast the `table` class. This class was only added in data downcast
|
|
@@ -69,72 +47,3 @@ export class PlainTableOutput extends Plugin {
|
|
|
69
47
|
});
|
|
70
48
|
}
|
|
71
49
|
}
|
|
72
|
-
/**
|
|
73
|
-
* The plain table downcast converter callback.
|
|
74
|
-
*
|
|
75
|
-
* @param table Table model element.
|
|
76
|
-
* @param conversionApi The conversion API object.
|
|
77
|
-
* @returns Created element.
|
|
78
|
-
*/
|
|
79
|
-
function downcastTableElement(table, { writer }) {
|
|
80
|
-
const headingRows = table.getAttribute('headingRows') || 0;
|
|
81
|
-
// Table head rows slot.
|
|
82
|
-
const headRowsSlot = writer.createSlot((element) => element.is('element', 'tableRow') && element.index < headingRows);
|
|
83
|
-
// Table body rows slot.
|
|
84
|
-
const bodyRowsSlot = writer.createSlot((element) => element.is('element', 'tableRow') && element.index >= headingRows);
|
|
85
|
-
// Table children slot.
|
|
86
|
-
const childrenSlot = writer.createSlot((element) => !element.is('element', 'tableRow'));
|
|
87
|
-
// Table <thead> element with all the heading rows.
|
|
88
|
-
const theadElement = writer.createContainerElement('thead', null, headRowsSlot);
|
|
89
|
-
// Table <tbody> element with all the body rows.
|
|
90
|
-
const tbodyElement = writer.createContainerElement('tbody', null, bodyRowsSlot);
|
|
91
|
-
// Table contents element containing <thead> and <tbody> when necessary.
|
|
92
|
-
const tableContentElements = [];
|
|
93
|
-
if (headingRows) {
|
|
94
|
-
tableContentElements.push(theadElement);
|
|
95
|
-
}
|
|
96
|
-
if (headingRows < table.childCount) {
|
|
97
|
-
tableContentElements.push(tbodyElement);
|
|
98
|
-
}
|
|
99
|
-
// Create table structure.
|
|
100
|
-
//
|
|
101
|
-
// <table>
|
|
102
|
-
// {children-slot-like-caption}
|
|
103
|
-
// <thead>
|
|
104
|
-
// {table-head-rows-slot}
|
|
105
|
-
// </thead>
|
|
106
|
-
// <tbody>
|
|
107
|
-
// {table-body-rows-slot}
|
|
108
|
-
// </tbody>
|
|
109
|
-
// </table>
|
|
110
|
-
return writer.createContainerElement('table', { class: 'table' }, [childrenSlot, ...tableContentElements]);
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Register table border and background attributes converters.
|
|
114
|
-
*/
|
|
115
|
-
function downcastTableBorderAndBackgroundAttributes(editor) {
|
|
116
|
-
const modelAttributes = {
|
|
117
|
-
'border-width': 'tableBorderWidth',
|
|
118
|
-
'border-color': 'tableBorderColor',
|
|
119
|
-
'border-style': 'tableBorderStyle',
|
|
120
|
-
'background-color': 'tableBackgroundColor'
|
|
121
|
-
};
|
|
122
|
-
for (const [styleName, modelAttribute] of Object.entries(modelAttributes)) {
|
|
123
|
-
editor.conversion.for('dataDowncast').add(dispatcher => {
|
|
124
|
-
return dispatcher.on(`attribute:${modelAttribute}:table`, (evt, data, conversionApi) => {
|
|
125
|
-
const { item, attributeNewValue } = data;
|
|
126
|
-
const { mapper, writer } = conversionApi;
|
|
127
|
-
if (!conversionApi.consumable.consume(item, evt.name)) {
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
const table = mapper.toViewElement(item);
|
|
131
|
-
if (attributeNewValue) {
|
|
132
|
-
writer.setStyle(styleName, attributeNewValue, table);
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
writer.removeStyle(styleName, table);
|
|
136
|
-
}
|
|
137
|
-
}, { priority: 'high' });
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
}
|
|
@@ -88,7 +88,7 @@ export class TableCellPropertiesEditing extends Plugin {
|
|
|
88
88
|
isRightToLeftContent: editor.locale.contentLanguageDirection === 'rtl'
|
|
89
89
|
});
|
|
90
90
|
editor.data.addStyleProcessorRules(addBorderStylesRules);
|
|
91
|
-
enableBorderProperties(
|
|
91
|
+
enableBorderProperties(editor, {
|
|
92
92
|
color: defaultTableCellProperties.borderColor,
|
|
93
93
|
style: defaultTableCellProperties.borderStyle,
|
|
94
94
|
width: defaultTableCellProperties.borderWidth
|
|
@@ -130,12 +130,15 @@ export class TableCellPropertiesEditing extends Plugin {
|
|
|
130
130
|
/**
|
|
131
131
|
* Enables the `'tableCellBorderStyle'`, `'tableCellBorderColor'` and `'tableCellBorderWidth'` attributes for table cells.
|
|
132
132
|
*
|
|
133
|
+
* @param editor The editor instance.
|
|
133
134
|
* @param defaultBorder The default border values.
|
|
134
135
|
* @param defaultBorder.color The default `tableCellBorderColor` value.
|
|
135
136
|
* @param defaultBorder.style The default `tableCellBorderStyle` value.
|
|
136
137
|
* @param defaultBorder.width The default `tableCellBorderWidth` value.
|
|
137
138
|
*/
|
|
138
|
-
function enableBorderProperties(
|
|
139
|
+
function enableBorderProperties(editor, defaultBorder) {
|
|
140
|
+
const { conversion } = editor;
|
|
141
|
+
const { schema } = editor.model;
|
|
139
142
|
const modelAttributes = {
|
|
140
143
|
width: 'tableCellBorderWidth',
|
|
141
144
|
color: 'tableCellBorderColor',
|
|
@@ -147,8 +150,8 @@ function enableBorderProperties(schema, conversion, defaultBorder) {
|
|
|
147
150
|
for (const modelAttribute of Object.values(modelAttributes)) {
|
|
148
151
|
schema.setAttributeProperties(modelAttribute, { isFormatting: true });
|
|
149
152
|
}
|
|
150
|
-
upcastBorderStyles(
|
|
151
|
-
upcastBorderStyles(
|
|
153
|
+
upcastBorderStyles(editor, 'td', modelAttributes, defaultBorder);
|
|
154
|
+
upcastBorderStyles(editor, 'th', modelAttributes, defaultBorder);
|
|
152
155
|
downcastAttributeToStyle(conversion, { modelElement: 'tableCell', modelAttribute: modelAttributes.style, styleName: 'border-style' });
|
|
153
156
|
downcastAttributeToStyle(conversion, { modelElement: 'tableCell', modelAttribute: modelAttributes.color, styleName: 'border-color' });
|
|
154
157
|
downcastAttributeToStyle(conversion, { modelElement: 'tableCell', modelAttribute: modelAttributes.width, styleName: 'border-width' });
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @module table/tablecellproperties/tablecellpropertiesuiexperimental
|
|
7
|
+
*/
|
|
8
|
+
import { Plugin, type Editor } from 'ckeditor5/src/core.js';
|
|
9
|
+
import { ContextualBalloon } from 'ckeditor5/src/ui.js';
|
|
10
|
+
import { TableCellPropertiesViewExperimental } from './ui/tablecellpropertiesviewexperimental.js';
|
|
11
|
+
/**
|
|
12
|
+
* The table cell properties UI plugin. It introduces the `'tableCellProperties'` button
|
|
13
|
+
* that opens a form allowing to specify the visual styling of a table cell.
|
|
14
|
+
*
|
|
15
|
+
* It uses the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.
|
|
16
|
+
*/
|
|
17
|
+
export declare class TableCellPropertiesUIExperimental extends Plugin {
|
|
18
|
+
/**
|
|
19
|
+
* The default table cell properties.
|
|
20
|
+
*/
|
|
21
|
+
private _defaultContentTableCellProperties;
|
|
22
|
+
/**
|
|
23
|
+
* The default layout table cell properties.
|
|
24
|
+
*/
|
|
25
|
+
private _defaultLayoutTableCellProperties;
|
|
26
|
+
/**
|
|
27
|
+
* The contextual balloon plugin instance.
|
|
28
|
+
*/
|
|
29
|
+
private _balloon?;
|
|
30
|
+
/**
|
|
31
|
+
* The cell properties form view displayed inside the balloon.
|
|
32
|
+
*/
|
|
33
|
+
view?: TableCellPropertiesViewExperimental | null;
|
|
34
|
+
/**
|
|
35
|
+
* The cell properties form view displayed inside the balloon (content table).
|
|
36
|
+
*/
|
|
37
|
+
private _viewWithContentTableDefaults?;
|
|
38
|
+
/**
|
|
39
|
+
* The cell properties form view displayed inside the balloon (layout table).
|
|
40
|
+
*/
|
|
41
|
+
private _viewWithLayoutTableDefaults?;
|
|
42
|
+
/**
|
|
43
|
+
* The batch used to undo all changes made by the form (which are live, as the user types)
|
|
44
|
+
* when "Cancel" was pressed. Each time the view is shown, a new batch is created.
|
|
45
|
+
*/
|
|
46
|
+
private _undoStepBatch?;
|
|
47
|
+
/**
|
|
48
|
+
* Flag used to indicate whether view is ready to execute update commands
|
|
49
|
+
* (it finished loading initial data).
|
|
50
|
+
*/
|
|
51
|
+
private _isReady?;
|
|
52
|
+
/**
|
|
53
|
+
* @inheritDoc
|
|
54
|
+
*/
|
|
55
|
+
static get requires(): readonly [typeof ContextualBalloon];
|
|
56
|
+
/**
|
|
57
|
+
* @inheritDoc
|
|
58
|
+
*/
|
|
59
|
+
static get pluginName(): "TableCellPropertiesUIExperimental";
|
|
60
|
+
/**
|
|
61
|
+
* @inheritDoc
|
|
62
|
+
*/
|
|
63
|
+
static get isOfficialPlugin(): true;
|
|
64
|
+
/**
|
|
65
|
+
* @inheritDoc
|
|
66
|
+
*/
|
|
67
|
+
constructor(editor: Editor);
|
|
68
|
+
/**
|
|
69
|
+
* @inheritDoc
|
|
70
|
+
*/
|
|
71
|
+
init(): void;
|
|
72
|
+
/**
|
|
73
|
+
* @inheritDoc
|
|
74
|
+
*/
|
|
75
|
+
destroy(): void;
|
|
76
|
+
/**
|
|
77
|
+
* Creates the {@link module:table/tablecellproperties/ui/tablecellpropertiesview~TableCellPropertiesView} instance.
|
|
78
|
+
*
|
|
79
|
+
* @returns The cell properties form view instance.
|
|
80
|
+
*/
|
|
81
|
+
private _createPropertiesView;
|
|
82
|
+
/**
|
|
83
|
+
* In this method the "editor data -> UI" binding is happening.
|
|
84
|
+
*
|
|
85
|
+
* When executed, this method obtains selected cell property values from various table commands
|
|
86
|
+
* and passes them to the {@link #view}.
|
|
87
|
+
*
|
|
88
|
+
* This way, the UI stays up–to–date with the editor data.
|
|
89
|
+
*/
|
|
90
|
+
private _fillViewFormFromCommandValues;
|
|
91
|
+
/**
|
|
92
|
+
* Shows the {@link #view} in the {@link #_balloon}.
|
|
93
|
+
*
|
|
94
|
+
* **Note**: Each time a view is shown, a new {@link #_undoStepBatch} is created. It contains
|
|
95
|
+
* all changes made to the document when the view is visible, allowing a single undo step
|
|
96
|
+
* for all of them.
|
|
97
|
+
*/
|
|
98
|
+
protected _showView(): void;
|
|
99
|
+
/**
|
|
100
|
+
* Removes the {@link #view} from the {@link #_balloon}.
|
|
101
|
+
*/
|
|
102
|
+
protected _hideView(): void;
|
|
103
|
+
/**
|
|
104
|
+
* Repositions the {@link #_balloon} or hides the {@link #view} if a table cell is no longer selected.
|
|
105
|
+
*/
|
|
106
|
+
protected _updateView(): void;
|
|
107
|
+
/**
|
|
108
|
+
* Returns `true` when the {@link #view} is visible in the {@link #_balloon}.
|
|
109
|
+
*/
|
|
110
|
+
private get _isViewVisible();
|
|
111
|
+
/**
|
|
112
|
+
* Returns `true` when the {@link #view} is in the {@link #_balloon}.
|
|
113
|
+
*/
|
|
114
|
+
private get _isViewInBalloon();
|
|
115
|
+
/**
|
|
116
|
+
* Creates a callback that when executed upon the {@link #view view's} property change
|
|
117
|
+
* executes a related editor command with the new property value.
|
|
118
|
+
*
|
|
119
|
+
* @param commandName The default value of the command.
|
|
120
|
+
*/
|
|
121
|
+
private _getPropertyChangeCallback;
|
|
122
|
+
/**
|
|
123
|
+
* Creates a callback that when executed upon the {@link #view view's} property change:
|
|
124
|
+
* * Executes a related editor command with the new property value if the value is valid,
|
|
125
|
+
* * Or sets the error text next to the invalid field, if the value did not pass the validation.
|
|
126
|
+
*/
|
|
127
|
+
private _getValidatedPropertyChangeCallback;
|
|
128
|
+
}
|