@ckeditor/ckeditor5-table 39.0.1 → 40.0.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 +1 -1
- package/README.md +3 -3
- package/build/table.js +1 -1
- package/build/table.js.map +1 -0
- package/build/translations/hy.js +1 -0
- package/lang/translations/ar.po +1 -0
- package/lang/translations/az.po +1 -0
- package/lang/translations/bg.po +1 -0
- package/lang/translations/bn.po +1 -0
- package/lang/translations/ca.po +1 -0
- package/lang/translations/cs.po +1 -0
- package/lang/translations/da.po +1 -0
- package/lang/translations/de-ch.po +1 -0
- package/lang/translations/de.po +1 -0
- package/lang/translations/el.po +1 -0
- package/lang/translations/en-au.po +1 -0
- package/lang/translations/en-gb.po +1 -0
- package/lang/translations/en.po +1 -0
- package/lang/translations/es.po +1 -0
- package/lang/translations/et.po +1 -0
- package/lang/translations/fa.po +1 -0
- package/lang/translations/fi.po +1 -0
- package/lang/translations/fr.po +1 -0
- package/lang/translations/gl.po +1 -0
- package/lang/translations/he.po +1 -0
- package/lang/translations/hi.po +1 -0
- package/lang/translations/hr.po +1 -0
- package/lang/translations/hu.po +1 -0
- package/lang/translations/hy.po +262 -0
- package/lang/translations/id.po +1 -0
- package/lang/translations/it.po +1 -0
- package/lang/translations/ja.po +1 -0
- package/lang/translations/ko.po +1 -0
- package/lang/translations/ku.po +1 -0
- package/lang/translations/lt.po +1 -0
- package/lang/translations/lv.po +1 -0
- package/lang/translations/ms.po +1 -0
- package/lang/translations/nb.po +1 -0
- package/lang/translations/ne.po +1 -0
- package/lang/translations/nl.po +1 -0
- package/lang/translations/no.po +1 -0
- package/lang/translations/pl.po +1 -0
- package/lang/translations/pt-br.po +1 -0
- package/lang/translations/pt.po +1 -0
- package/lang/translations/ro.po +1 -0
- package/lang/translations/ru.po +1 -0
- package/lang/translations/sk.po +1 -0
- package/lang/translations/sl.po +1 -0
- package/lang/translations/sq.po +1 -0
- package/lang/translations/sr-latn.po +1 -0
- package/lang/translations/sr.po +1 -0
- package/lang/translations/sv.po +1 -0
- package/lang/translations/th.po +1 -0
- package/lang/translations/tk.po +1 -0
- package/lang/translations/tr.po +1 -0
- package/lang/translations/tt.po +1 -0
- package/lang/translations/ug.po +1 -0
- package/lang/translations/uk.po +1 -0
- package/lang/translations/ur.po +1 -0
- package/lang/translations/uz.po +1 -0
- package/lang/translations/vi.po +1 -0
- package/lang/translations/zh-cn.po +1 -0
- package/lang/translations/zh.po +1 -0
- package/package.json +2 -6
- package/src/augmentation.d.ts +76 -76
- package/src/augmentation.js +5 -5
- package/src/commands/insertcolumncommand.d.ts +55 -55
- package/src/commands/insertcolumncommand.js +67 -67
- package/src/commands/insertrowcommand.d.ts +54 -54
- package/src/commands/insertrowcommand.js +66 -66
- package/src/commands/inserttablecommand.d.ts +44 -44
- package/src/commands/inserttablecommand.js +69 -69
- package/src/commands/mergecellcommand.d.ts +68 -68
- package/src/commands/mergecellcommand.js +198 -198
- package/src/commands/mergecellscommand.d.ts +28 -28
- package/src/commands/mergecellscommand.js +94 -94
- package/src/commands/removecolumncommand.d.ts +29 -29
- package/src/commands/removecolumncommand.js +109 -109
- package/src/commands/removerowcommand.d.ts +29 -29
- package/src/commands/removerowcommand.js +82 -82
- package/src/commands/selectcolumncommand.d.ts +33 -33
- package/src/commands/selectcolumncommand.js +60 -60
- package/src/commands/selectrowcommand.d.ts +33 -33
- package/src/commands/selectrowcommand.js +56 -56
- package/src/commands/setheadercolumncommand.d.ts +50 -50
- package/src/commands/setheadercolumncommand.js +71 -71
- package/src/commands/setheaderrowcommand.d.ts +53 -53
- package/src/commands/setheaderrowcommand.js +79 -79
- package/src/commands/splitcellcommand.d.ts +43 -43
- package/src/commands/splitcellcommand.js +54 -54
- package/src/converters/downcast.d.ts +63 -63
- package/src/converters/downcast.js +146 -146
- package/src/converters/table-caption-post-fixer.d.ts +20 -20
- package/src/converters/table-caption-post-fixer.js +53 -53
- package/src/converters/table-cell-paragraph-post-fixer.d.ts +32 -32
- package/src/converters/table-cell-paragraph-post-fixer.js +107 -107
- package/src/converters/table-cell-refresh-handler.d.ts +18 -18
- package/src/converters/table-cell-refresh-handler.js +45 -45
- package/src/converters/table-headings-refresh-handler.d.ts +17 -17
- package/src/converters/table-headings-refresh-handler.js +49 -49
- package/src/converters/table-layout-post-fixer.d.ts +226 -226
- package/src/converters/table-layout-post-fixer.js +367 -367
- package/src/converters/tableproperties.d.ts +54 -54
- package/src/converters/tableproperties.js +159 -159
- package/src/converters/upcasttable.d.ts +49 -49
- package/src/converters/upcasttable.js +243 -243
- package/src/index.d.ts +60 -60
- package/src/index.js +30 -30
- package/src/plaintableoutput.d.ts +26 -26
- package/src/plaintableoutput.js +123 -123
- package/src/table.d.ts +40 -40
- package/src/table.js +44 -44
- package/src/tablecaption/tablecaptionediting.d.ts +63 -63
- package/src/tablecaption/tablecaptionediting.js +122 -122
- package/src/tablecaption/tablecaptionui.d.ts +21 -21
- package/src/tablecaption/tablecaptionui.js +57 -57
- package/src/tablecaption/toggletablecaptioncommand.d.ts +68 -68
- package/src/tablecaption/toggletablecaptioncommand.js +104 -104
- package/src/tablecaption/utils.d.ts +42 -42
- package/src/tablecaption/utils.js +67 -67
- package/src/tablecaption.d.ts +24 -24
- package/src/tablecaption.js +28 -28
- package/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.d.ts +32 -32
- package/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.js +30 -30
- package/src/tablecellproperties/commands/tablecellbordercolorcommand.d.ts +37 -37
- package/src/tablecellproperties/commands/tablecellbordercolorcommand.js +44 -44
- package/src/tablecellproperties/commands/tablecellborderstylecommand.d.ts +37 -37
- package/src/tablecellproperties/commands/tablecellborderstylecommand.js +44 -44
- package/src/tablecellproperties/commands/tablecellborderwidthcommand.d.ts +51 -51
- package/src/tablecellproperties/commands/tablecellborderwidthcommand.js +64 -64
- package/src/tablecellproperties/commands/tablecellheightcommand.d.ts +46 -46
- package/src/tablecellproperties/commands/tablecellheightcommand.js +51 -51
- package/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.d.ts +32 -32
- package/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js +30 -30
- package/src/tablecellproperties/commands/tablecellpaddingcommand.d.ts +51 -51
- package/src/tablecellproperties/commands/tablecellpaddingcommand.js +64 -64
- package/src/tablecellproperties/commands/tablecellpropertycommand.d.ts +62 -62
- package/src/tablecellproperties/commands/tablecellpropertycommand.js +92 -92
- package/src/tablecellproperties/commands/tablecellverticalalignmentcommand.d.ts +40 -40
- package/src/tablecellproperties/commands/tablecellverticalalignmentcommand.js +38 -38
- package/src/tablecellproperties/tablecellpropertiesediting.d.ts +43 -43
- package/src/tablecellproperties/tablecellpropertiesediting.js +241 -241
- package/src/tablecellproperties/tablecellpropertiesui.d.ts +112 -112
- package/src/tablecellproperties/tablecellpropertiesui.js +330 -330
- package/src/tablecellproperties/ui/tablecellpropertiesview.d.ts +228 -228
- package/src/tablecellproperties/ui/tablecellpropertiesview.js +548 -539
- package/src/tablecellproperties.d.ts +30 -30
- package/src/tablecellproperties.js +34 -34
- package/src/tablecellwidth/commands/tablecellwidthcommand.d.ts +46 -46
- package/src/tablecellwidth/commands/tablecellwidthcommand.js +51 -51
- package/src/tablecellwidth/tablecellwidthediting.d.ts +29 -29
- package/src/tablecellwidth/tablecellwidthediting.js +45 -45
- package/src/tableclipboard.d.ts +65 -65
- package/src/tableclipboard.js +450 -450
- package/src/tablecolumnresize/constants.d.ts +20 -20
- package/src/tablecolumnresize/constants.js +20 -20
- package/src/tablecolumnresize/converters.d.ts +18 -18
- package/src/tablecolumnresize/converters.js +46 -45
- package/src/tablecolumnresize/tablecolumnresizeediting.d.ts +139 -139
- package/src/tablecolumnresize/tablecolumnresizeediting.js +583 -571
- package/src/tablecolumnresize/tablewidthscommand.d.ts +38 -38
- package/src/tablecolumnresize/tablewidthscommand.js +61 -61
- package/src/tablecolumnresize/utils.d.ts +148 -141
- package/src/tablecolumnresize/utils.js +358 -330
- package/src/tablecolumnresize.d.ts +26 -26
- package/src/tablecolumnresize.js +30 -30
- package/src/tableconfig.d.ts +343 -343
- package/src/tableconfig.js +5 -5
- package/src/tableediting.d.ts +98 -98
- package/src/tableediting.js +191 -191
- package/src/tablekeyboard.d.ts +68 -68
- package/src/tablekeyboard.js +279 -279
- package/src/tablemouse/mouseeventsobserver.d.ts +62 -62
- package/src/tablemouse/mouseeventsobserver.js +35 -35
- package/src/tablemouse.d.ts +48 -48
- package/src/tablemouse.js +172 -172
- package/src/tableproperties/commands/tablealignmentcommand.d.ts +32 -32
- package/src/tableproperties/commands/tablealignmentcommand.js +30 -30
- package/src/tableproperties/commands/tablebackgroundcolorcommand.d.ts +32 -32
- package/src/tableproperties/commands/tablebackgroundcolorcommand.js +30 -30
- package/src/tableproperties/commands/tablebordercolorcommand.d.ts +37 -37
- package/src/tableproperties/commands/tablebordercolorcommand.js +44 -44
- package/src/tableproperties/commands/tableborderstylecommand.d.ts +37 -37
- package/src/tableproperties/commands/tableborderstylecommand.js +44 -44
- package/src/tableproperties/commands/tableborderwidthcommand.d.ts +51 -51
- package/src/tableproperties/commands/tableborderwidthcommand.js +64 -64
- package/src/tableproperties/commands/tableheightcommand.d.ts +46 -46
- package/src/tableproperties/commands/tableheightcommand.js +54 -54
- package/src/tableproperties/commands/tablepropertycommand.d.ts +61 -61
- package/src/tableproperties/commands/tablepropertycommand.js +80 -80
- package/src/tableproperties/commands/tablewidthcommand.d.ts +46 -46
- package/src/tableproperties/commands/tablewidthcommand.js +54 -54
- package/src/tableproperties/tablepropertiesediting.d.ts +40 -40
- package/src/tableproperties/tablepropertiesediting.js +206 -206
- package/src/tableproperties/tablepropertiesui.d.ts +114 -114
- package/src/tableproperties/tablepropertiesui.js +321 -321
- package/src/tableproperties/ui/tablepropertiesview.d.ts +207 -207
- package/src/tableproperties/ui/tablepropertiesview.js +466 -457
- package/src/tableproperties.d.ts +30 -30
- package/src/tableproperties.js +34 -34
- package/src/tableselection.d.ts +107 -107
- package/src/tableselection.js +297 -297
- package/src/tabletoolbar.d.ts +32 -32
- package/src/tabletoolbar.js +57 -57
- package/src/tableui.d.ts +53 -53
- package/src/tableui.js +309 -309
- package/src/tableutils.d.ts +448 -448
- package/src/tableutils.js +1055 -1041
- package/src/tablewalker.d.ts +362 -323
- package/src/tablewalker.js +393 -333
- package/src/ui/colorinputview.d.ts +140 -140
- package/src/ui/colorinputview.js +271 -265
- package/src/ui/formrowview.d.ts +61 -61
- package/src/ui/formrowview.js +57 -57
- package/src/ui/inserttableview.d.ts +77 -77
- package/src/ui/inserttableview.js +169 -169
- package/src/utils/common.d.ts +42 -42
- package/src/utils/common.js +57 -57
- package/src/utils/structure.d.ts +245 -245
- package/src/utils/structure.js +426 -426
- package/src/utils/table-properties.d.ts +67 -67
- package/src/utils/table-properties.js +86 -86
- package/src/utils/ui/contextualballoon.d.ts +34 -34
- package/src/utils/ui/contextualballoon.js +106 -106
- package/src/utils/ui/table-properties.d.ts +195 -195
- package/src/utils/ui/table-properties.js +362 -362
- package/src/utils/ui/widget.d.ts +16 -16
- package/src/utils/ui/widget.js +38 -38
- package/theme/tablecolumnresize.css +8 -6
|
@@ -1,330 +1,358 @@
|
|
|
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
|
-
import { global } from 'ckeditor5/src/utils';
|
|
6
|
-
import { COLUMN_WIDTH_PRECISION, COLUMN_MIN_WIDTH_AS_PERCENTAGE, COLUMN_MIN_WIDTH_IN_PIXELS } from './constants';
|
|
7
|
-
/**
|
|
8
|
-
* Returns all the inserted or changed table model elements in a given change set. Only the tables
|
|
9
|
-
* with 'columnsWidth' attribute are taken into account. The returned set may be empty.
|
|
10
|
-
*
|
|
11
|
-
* Most notably if an entire table is removed it will not be included in returned set.
|
|
12
|
-
*
|
|
13
|
-
* @param model The model to collect the affected elements from.
|
|
14
|
-
* @returns A set of table model elements.
|
|
15
|
-
*/
|
|
16
|
-
export function getChangedResizedTables(model) {
|
|
17
|
-
const affectedTables = new Set();
|
|
18
|
-
for (const change of model.document.differ.getChanges()) {
|
|
19
|
-
let referencePosition = null;
|
|
20
|
-
// Checks if the particular change from the differ is:
|
|
21
|
-
// - an insertion or removal of a table, a row or a cell,
|
|
22
|
-
// - an attribute change on a table, a row or a cell.
|
|
23
|
-
switch (change.type) {
|
|
24
|
-
case 'insert':
|
|
25
|
-
referencePosition = ['table', 'tableRow', 'tableCell'].includes(change.name) ?
|
|
26
|
-
change.position :
|
|
27
|
-
null;
|
|
28
|
-
break;
|
|
29
|
-
case 'remove':
|
|
30
|
-
// If the whole table is removed, there's no need to update its column widths (#12201).
|
|
31
|
-
referencePosition = ['tableRow', 'tableCell'].includes(change.name) ?
|
|
32
|
-
change.position :
|
|
33
|
-
null;
|
|
34
|
-
break;
|
|
35
|
-
case 'attribute':
|
|
36
|
-
if (change.range.start.nodeAfter) {
|
|
37
|
-
referencePosition = ['table', 'tableRow', 'tableCell'].includes(change.range.start.nodeAfter.name) ?
|
|
38
|
-
change.range.start :
|
|
39
|
-
null;
|
|
40
|
-
}
|
|
41
|
-
break;
|
|
42
|
-
}
|
|
43
|
-
if (!referencePosition) {
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
const tableNode = (referencePosition.nodeAfter && referencePosition.nodeAfter.is('element', 'table')) ?
|
|
47
|
-
referencePosition.nodeAfter : referencePosition.findAncestor('table');
|
|
48
|
-
// We iterate over the whole table looking for the nested tables that are also affected.
|
|
49
|
-
for (const node of model.createRangeOn(tableNode).getItems()) {
|
|
50
|
-
if (!node.is('element', 'table')) {
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
if (!getColumnGroupElement(node)) {
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
affectedTables.add(node);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return affectedTables;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Calculates the percentage of the minimum column width given in pixels for a given table.
|
|
63
|
-
*
|
|
64
|
-
* @param modelTable A table model element.
|
|
65
|
-
* @param editor The editor instance.
|
|
66
|
-
* @returns The minimal column width in percentage.
|
|
67
|
-
*/
|
|
68
|
-
export function getColumnMinWidthAsPercentage(modelTable, editor) {
|
|
69
|
-
return COLUMN_MIN_WIDTH_IN_PIXELS * 100 / getTableWidthInPixels(modelTable, editor);
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Calculates the table width in pixels.
|
|
73
|
-
*
|
|
74
|
-
* @param modelTable A table model element.
|
|
75
|
-
* @param editor The editor instance.
|
|
76
|
-
* @returns The width of the table in pixels.
|
|
77
|
-
*/
|
|
78
|
-
export function getTableWidthInPixels(modelTable, editor) {
|
|
79
|
-
// It is possible for a table to not have a <tbody> element - see #11878.
|
|
80
|
-
const referenceElement = getChildrenViewElement(modelTable, 'tbody', editor) || getChildrenViewElement(modelTable, 'thead', editor);
|
|
81
|
-
const domReferenceElement = editor.editing.view.domConverter.mapViewToDom(referenceElement);
|
|
82
|
-
return getElementWidthInPixels(domReferenceElement);
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Returns the a view element with a given name that is nested directly in a `<table>` element
|
|
86
|
-
* related to a given `modelTable`.
|
|
87
|
-
*
|
|
88
|
-
* @param elementName Name of a view to be looked for, e.g. `'colgroup`', `'thead`'.
|
|
89
|
-
* @returns Matched view or `undefined` otherwise.
|
|
90
|
-
*/
|
|
91
|
-
function getChildrenViewElement(modelTable, elementName, editor) {
|
|
92
|
-
const viewFigure = editor.editing.mapper.toViewElement(modelTable);
|
|
93
|
-
const viewTable = [...viewFigure.getChildren()]
|
|
94
|
-
.find((node) => node.is('element', 'table'));
|
|
95
|
-
return [...viewTable.getChildren()]
|
|
96
|
-
.find((node) => node.is('element', elementName));
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Returns the computed width (in pixels) of the DOM element without padding and borders.
|
|
100
|
-
*
|
|
101
|
-
* @param domElement A DOM element.
|
|
102
|
-
* @returns The width of the DOM element in pixels.
|
|
103
|
-
*/
|
|
104
|
-
export function getElementWidthInPixels(domElement) {
|
|
105
|
-
const styles = global.window.getComputedStyle(domElement);
|
|
106
|
-
// In the 'border-box' box sizing algorithm, the element's width
|
|
107
|
-
// already includes the padding and border width (#12335).
|
|
108
|
-
if (styles.boxSizing === 'border-box') {
|
|
109
|
-
return parseFloat(styles.width) -
|
|
110
|
-
parseFloat(styles.paddingLeft) -
|
|
111
|
-
parseFloat(styles.paddingRight) -
|
|
112
|
-
parseFloat(styles.borderLeftWidth) -
|
|
113
|
-
parseFloat(styles.borderRightWidth);
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
return parseFloat(styles.width);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Returns the column indexes on the left and right edges of a cell. They differ if the cell spans
|
|
121
|
-
* across multiple columns.
|
|
122
|
-
*
|
|
123
|
-
* @param cell A table cell model element.
|
|
124
|
-
* @param tableUtils The Table Utils plugin instance.
|
|
125
|
-
* @returns An object containing the indexes of the left and right edges of the cell.
|
|
126
|
-
*/
|
|
127
|
-
export function getColumnEdgesIndexes(cell, tableUtils) {
|
|
128
|
-
const cellColumnIndex = tableUtils.getCellLocation(cell).column;
|
|
129
|
-
const cellWidth = cell.getAttribute('colspan') || 1;
|
|
130
|
-
return {
|
|
131
|
-
leftEdge: cellColumnIndex,
|
|
132
|
-
rightEdge: cellColumnIndex + cellWidth - 1
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Rounds the provided value to a fixed-point number with defined number of digits after the decimal point.
|
|
137
|
-
*
|
|
138
|
-
* @param value A number to be rounded.
|
|
139
|
-
* @returns The rounded number.
|
|
140
|
-
*/
|
|
141
|
-
export function toPrecision(value) {
|
|
142
|
-
const multiplier = Math.pow(10, COLUMN_WIDTH_PRECISION);
|
|
143
|
-
const number = typeof value === 'number' ? value : parseFloat(value);
|
|
144
|
-
return Math.round(number * multiplier) / multiplier;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Clamps the number within the inclusive lower (min) and upper (max) bounds. Returned number is rounded using the
|
|
148
|
-
* {@link ~toPrecision `toPrecision()`} function.
|
|
149
|
-
*
|
|
150
|
-
* @param number A number to be clamped.
|
|
151
|
-
* @param min A lower bound.
|
|
152
|
-
* @param max An upper bound.
|
|
153
|
-
* @returns The clamped number.
|
|
154
|
-
*/
|
|
155
|
-
export function clamp(number, min, max) {
|
|
156
|
-
if (number <= min) {
|
|
157
|
-
return toPrecision(min);
|
|
158
|
-
}
|
|
159
|
-
if (number >= max) {
|
|
160
|
-
return toPrecision(max);
|
|
161
|
-
}
|
|
162
|
-
return toPrecision(number);
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Creates an array with defined length and fills all elements with defined value.
|
|
166
|
-
*
|
|
167
|
-
* @param length The length of the array.
|
|
168
|
-
* @param value The value to fill the array with.
|
|
169
|
-
* @returns An array with defined length and filled with defined value.
|
|
170
|
-
*/
|
|
171
|
-
export function createFilledArray(length, value) {
|
|
172
|
-
return Array(length).fill(value);
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Sums all array values that can be parsed to a float.
|
|
176
|
-
*
|
|
177
|
-
* @param array An array of numbers.
|
|
178
|
-
* @returns The sum of all array values.
|
|
179
|
-
*/
|
|
180
|
-
export function sumArray(array) {
|
|
181
|
-
return array
|
|
182
|
-
.map(value => typeof value === 'number' ? value : parseFloat(value))
|
|
183
|
-
.filter(value => !Number.isNaN(value))
|
|
184
|
-
.reduce((result, item) => result + item, 0);
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Makes sure that the sum of the widths from all columns is 100%. If the sum of all the widths is not equal 100%, all the widths are
|
|
188
|
-
* changed proportionally so that they all sum back to 100%. If there are columns without specified width, the amount remaining
|
|
189
|
-
* after assigning the known widths will be distributed equally between them.
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
//
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
return
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
* @param
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
* @
|
|
326
|
-
* @
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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
|
+
import { global } from 'ckeditor5/src/utils';
|
|
6
|
+
import { COLUMN_WIDTH_PRECISION, COLUMN_MIN_WIDTH_AS_PERCENTAGE, COLUMN_MIN_WIDTH_IN_PIXELS } from './constants';
|
|
7
|
+
/**
|
|
8
|
+
* Returns all the inserted or changed table model elements in a given change set. Only the tables
|
|
9
|
+
* with 'columnsWidth' attribute are taken into account. The returned set may be empty.
|
|
10
|
+
*
|
|
11
|
+
* Most notably if an entire table is removed it will not be included in returned set.
|
|
12
|
+
*
|
|
13
|
+
* @param model The model to collect the affected elements from.
|
|
14
|
+
* @returns A set of table model elements.
|
|
15
|
+
*/
|
|
16
|
+
export function getChangedResizedTables(model) {
|
|
17
|
+
const affectedTables = new Set();
|
|
18
|
+
for (const change of model.document.differ.getChanges()) {
|
|
19
|
+
let referencePosition = null;
|
|
20
|
+
// Checks if the particular change from the differ is:
|
|
21
|
+
// - an insertion or removal of a table, a row or a cell,
|
|
22
|
+
// - an attribute change on a table, a row or a cell.
|
|
23
|
+
switch (change.type) {
|
|
24
|
+
case 'insert':
|
|
25
|
+
referencePosition = ['table', 'tableRow', 'tableCell'].includes(change.name) ?
|
|
26
|
+
change.position :
|
|
27
|
+
null;
|
|
28
|
+
break;
|
|
29
|
+
case 'remove':
|
|
30
|
+
// If the whole table is removed, there's no need to update its column widths (#12201).
|
|
31
|
+
referencePosition = ['tableRow', 'tableCell'].includes(change.name) ?
|
|
32
|
+
change.position :
|
|
33
|
+
null;
|
|
34
|
+
break;
|
|
35
|
+
case 'attribute':
|
|
36
|
+
if (change.range.start.nodeAfter) {
|
|
37
|
+
referencePosition = ['table', 'tableRow', 'tableCell'].includes(change.range.start.nodeAfter.name) ?
|
|
38
|
+
change.range.start :
|
|
39
|
+
null;
|
|
40
|
+
}
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
if (!referencePosition) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const tableNode = (referencePosition.nodeAfter && referencePosition.nodeAfter.is('element', 'table')) ?
|
|
47
|
+
referencePosition.nodeAfter : referencePosition.findAncestor('table');
|
|
48
|
+
// We iterate over the whole table looking for the nested tables that are also affected.
|
|
49
|
+
for (const node of model.createRangeOn(tableNode).getItems()) {
|
|
50
|
+
if (!node.is('element', 'table')) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (!getColumnGroupElement(node)) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
affectedTables.add(node);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return affectedTables;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Calculates the percentage of the minimum column width given in pixels for a given table.
|
|
63
|
+
*
|
|
64
|
+
* @param modelTable A table model element.
|
|
65
|
+
* @param editor The editor instance.
|
|
66
|
+
* @returns The minimal column width in percentage.
|
|
67
|
+
*/
|
|
68
|
+
export function getColumnMinWidthAsPercentage(modelTable, editor) {
|
|
69
|
+
return COLUMN_MIN_WIDTH_IN_PIXELS * 100 / getTableWidthInPixels(modelTable, editor);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Calculates the table width in pixels.
|
|
73
|
+
*
|
|
74
|
+
* @param modelTable A table model element.
|
|
75
|
+
* @param editor The editor instance.
|
|
76
|
+
* @returns The width of the table in pixels.
|
|
77
|
+
*/
|
|
78
|
+
export function getTableWidthInPixels(modelTable, editor) {
|
|
79
|
+
// It is possible for a table to not have a <tbody> element - see #11878.
|
|
80
|
+
const referenceElement = getChildrenViewElement(modelTable, 'tbody', editor) || getChildrenViewElement(modelTable, 'thead', editor);
|
|
81
|
+
const domReferenceElement = editor.editing.view.domConverter.mapViewToDom(referenceElement);
|
|
82
|
+
return getElementWidthInPixels(domReferenceElement);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Returns the a view element with a given name that is nested directly in a `<table>` element
|
|
86
|
+
* related to a given `modelTable`.
|
|
87
|
+
*
|
|
88
|
+
* @param elementName Name of a view to be looked for, e.g. `'colgroup`', `'thead`'.
|
|
89
|
+
* @returns Matched view or `undefined` otherwise.
|
|
90
|
+
*/
|
|
91
|
+
function getChildrenViewElement(modelTable, elementName, editor) {
|
|
92
|
+
const viewFigure = editor.editing.mapper.toViewElement(modelTable);
|
|
93
|
+
const viewTable = [...viewFigure.getChildren()]
|
|
94
|
+
.find((node) => node.is('element', 'table'));
|
|
95
|
+
return [...viewTable.getChildren()]
|
|
96
|
+
.find((node) => node.is('element', elementName));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Returns the computed width (in pixels) of the DOM element without padding and borders.
|
|
100
|
+
*
|
|
101
|
+
* @param domElement A DOM element.
|
|
102
|
+
* @returns The width of the DOM element in pixels.
|
|
103
|
+
*/
|
|
104
|
+
export function getElementWidthInPixels(domElement) {
|
|
105
|
+
const styles = global.window.getComputedStyle(domElement);
|
|
106
|
+
// In the 'border-box' box sizing algorithm, the element's width
|
|
107
|
+
// already includes the padding and border width (#12335).
|
|
108
|
+
if (styles.boxSizing === 'border-box') {
|
|
109
|
+
return parseFloat(styles.width) -
|
|
110
|
+
parseFloat(styles.paddingLeft) -
|
|
111
|
+
parseFloat(styles.paddingRight) -
|
|
112
|
+
parseFloat(styles.borderLeftWidth) -
|
|
113
|
+
parseFloat(styles.borderRightWidth);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
return parseFloat(styles.width);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Returns the column indexes on the left and right edges of a cell. They differ if the cell spans
|
|
121
|
+
* across multiple columns.
|
|
122
|
+
*
|
|
123
|
+
* @param cell A table cell model element.
|
|
124
|
+
* @param tableUtils The Table Utils plugin instance.
|
|
125
|
+
* @returns An object containing the indexes of the left and right edges of the cell.
|
|
126
|
+
*/
|
|
127
|
+
export function getColumnEdgesIndexes(cell, tableUtils) {
|
|
128
|
+
const cellColumnIndex = tableUtils.getCellLocation(cell).column;
|
|
129
|
+
const cellWidth = cell.getAttribute('colspan') || 1;
|
|
130
|
+
return {
|
|
131
|
+
leftEdge: cellColumnIndex,
|
|
132
|
+
rightEdge: cellColumnIndex + cellWidth - 1
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Rounds the provided value to a fixed-point number with defined number of digits after the decimal point.
|
|
137
|
+
*
|
|
138
|
+
* @param value A number to be rounded.
|
|
139
|
+
* @returns The rounded number.
|
|
140
|
+
*/
|
|
141
|
+
export function toPrecision(value) {
|
|
142
|
+
const multiplier = Math.pow(10, COLUMN_WIDTH_PRECISION);
|
|
143
|
+
const number = typeof value === 'number' ? value : parseFloat(value);
|
|
144
|
+
return Math.round(number * multiplier) / multiplier;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Clamps the number within the inclusive lower (min) and upper (max) bounds. Returned number is rounded using the
|
|
148
|
+
* {@link ~toPrecision `toPrecision()`} function.
|
|
149
|
+
*
|
|
150
|
+
* @param number A number to be clamped.
|
|
151
|
+
* @param min A lower bound.
|
|
152
|
+
* @param max An upper bound.
|
|
153
|
+
* @returns The clamped number.
|
|
154
|
+
*/
|
|
155
|
+
export function clamp(number, min, max) {
|
|
156
|
+
if (number <= min) {
|
|
157
|
+
return toPrecision(min);
|
|
158
|
+
}
|
|
159
|
+
if (number >= max) {
|
|
160
|
+
return toPrecision(max);
|
|
161
|
+
}
|
|
162
|
+
return toPrecision(number);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Creates an array with defined length and fills all elements with defined value.
|
|
166
|
+
*
|
|
167
|
+
* @param length The length of the array.
|
|
168
|
+
* @param value The value to fill the array with.
|
|
169
|
+
* @returns An array with defined length and filled with defined value.
|
|
170
|
+
*/
|
|
171
|
+
export function createFilledArray(length, value) {
|
|
172
|
+
return Array(length).fill(value);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Sums all array values that can be parsed to a float.
|
|
176
|
+
*
|
|
177
|
+
* @param array An array of numbers.
|
|
178
|
+
* @returns The sum of all array values.
|
|
179
|
+
*/
|
|
180
|
+
export function sumArray(array) {
|
|
181
|
+
return array
|
|
182
|
+
.map(value => typeof value === 'number' ? value : parseFloat(value))
|
|
183
|
+
.filter(value => !Number.isNaN(value))
|
|
184
|
+
.reduce((result, item) => result + item, 0);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Makes sure that the sum of the widths from all columns is 100%. If the sum of all the widths is not equal 100%, all the widths are
|
|
188
|
+
* changed proportionally so that they all sum back to 100%. If there are columns without specified width, the amount remaining
|
|
189
|
+
* after assigning the known widths will be distributed equally between them.
|
|
190
|
+
*
|
|
191
|
+
* @param columnWidths An array of column widths.
|
|
192
|
+
* @returns An array of column widths guaranteed to sum up to 100%.
|
|
193
|
+
*/
|
|
194
|
+
export function normalizeColumnWidths(columnWidths) {
|
|
195
|
+
const widths = columnWidths.map(width => {
|
|
196
|
+
if (width === 'auto') {
|
|
197
|
+
return width;
|
|
198
|
+
}
|
|
199
|
+
return parseFloat(width.replace('%', ''));
|
|
200
|
+
});
|
|
201
|
+
let normalizedWidths = calculateMissingColumnWidths(widths);
|
|
202
|
+
const totalWidth = sumArray(normalizedWidths);
|
|
203
|
+
if (totalWidth !== 100) {
|
|
204
|
+
normalizedWidths = normalizedWidths
|
|
205
|
+
// Adjust all the columns proportionally.
|
|
206
|
+
.map(width => toPrecision(width * 100 / totalWidth))
|
|
207
|
+
// Due to rounding of numbers it may happen that the sum of the widths of all columns will not be exactly 100%.
|
|
208
|
+
// Therefore, the width of the last column is explicitly adjusted (narrowed or expanded), since all the columns
|
|
209
|
+
// have been proportionally changed already.
|
|
210
|
+
.map((columnWidth, columnIndex, width) => {
|
|
211
|
+
const isLastColumn = columnIndex === width.length - 1;
|
|
212
|
+
if (!isLastColumn) {
|
|
213
|
+
return columnWidth;
|
|
214
|
+
}
|
|
215
|
+
const totalWidth = sumArray(width);
|
|
216
|
+
return toPrecision(columnWidth + 100 - totalWidth);
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
return normalizedWidths.map(width => width + '%');
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Initializes the column widths by parsing the attribute value and calculating the uninitialized column widths. The special value 'auto'
|
|
223
|
+
* indicates that width for the column must be calculated. The width of such uninitialized column is calculated as follows:
|
|
224
|
+
* - If there is enough free space in the table for all uninitialized columns to have at least the minimum allowed width for all of them,
|
|
225
|
+
* then set this width equally for all uninitialized columns.
|
|
226
|
+
* - Otherwise, just set the minimum allowed width for all uninitialized columns. The sum of all column widths will be greater than 100%,
|
|
227
|
+
* but then it will be adjusted proportionally to 100% in {@link #normalizeColumnWidths `normalizeColumnWidths()`}.
|
|
228
|
+
*
|
|
229
|
+
* @param columnWidths An array of column widths.
|
|
230
|
+
* @returns An array with 'auto' values replaced with calculated widths.
|
|
231
|
+
*/
|
|
232
|
+
function calculateMissingColumnWidths(columnWidths) {
|
|
233
|
+
const numberOfUninitializedColumns = columnWidths.filter(columnWidth => columnWidth === 'auto').length;
|
|
234
|
+
if (numberOfUninitializedColumns === 0) {
|
|
235
|
+
return columnWidths.map(columnWidth => toPrecision(columnWidth));
|
|
236
|
+
}
|
|
237
|
+
const totalWidthOfInitializedColumns = sumArray(columnWidths);
|
|
238
|
+
const widthForUninitializedColumn = Math.max((100 - totalWidthOfInitializedColumns) / numberOfUninitializedColumns, COLUMN_MIN_WIDTH_AS_PERCENTAGE);
|
|
239
|
+
return columnWidths
|
|
240
|
+
.map(columnWidth => columnWidth === 'auto' ? widthForUninitializedColumn : columnWidth)
|
|
241
|
+
.map(columnWidth => toPrecision(columnWidth));
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Calculates the total horizontal space taken by the cell. That includes:
|
|
245
|
+
* * width,
|
|
246
|
+
* * left and red padding,
|
|
247
|
+
* * border width.
|
|
248
|
+
*
|
|
249
|
+
* @param domCell A DOM cell element.
|
|
250
|
+
* @returns Width in pixels without `px` at the end.
|
|
251
|
+
*/
|
|
252
|
+
export function getDomCellOuterWidth(domCell) {
|
|
253
|
+
const styles = global.window.getComputedStyle(domCell);
|
|
254
|
+
// In the 'border-box' box sizing algorithm, the element's width
|
|
255
|
+
// already includes the padding and border width (#12335).
|
|
256
|
+
if (styles.boxSizing === 'border-box') {
|
|
257
|
+
return parseInt(styles.width);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
return parseFloat(styles.width) +
|
|
261
|
+
parseFloat(styles.paddingLeft) +
|
|
262
|
+
parseFloat(styles.paddingRight) +
|
|
263
|
+
parseFloat(styles.borderWidth);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Updates column elements to match columns widths.
|
|
268
|
+
*
|
|
269
|
+
* @param columns
|
|
270
|
+
* @param tableColumnGroup
|
|
271
|
+
* @param normalizedWidths
|
|
272
|
+
* @param writer
|
|
273
|
+
*/
|
|
274
|
+
export function updateColumnElements(columns, tableColumnGroup, normalizedWidths, writer) {
|
|
275
|
+
for (let i = 0; i < Math.max(normalizedWidths.length, columns.length); i++) {
|
|
276
|
+
const column = columns[i];
|
|
277
|
+
const columnWidth = normalizedWidths[i];
|
|
278
|
+
if (!columnWidth) {
|
|
279
|
+
// Number of `<tableColumn>` elements exceeds actual number of columns.
|
|
280
|
+
writer.remove(column);
|
|
281
|
+
}
|
|
282
|
+
else if (!column) {
|
|
283
|
+
// There is fewer `<tableColumn>` elements than actual columns.
|
|
284
|
+
writer.appendElement('tableColumn', { columnWidth }, tableColumnGroup);
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
// Update column width.
|
|
288
|
+
writer.setAttribute('columnWidth', columnWidth, column);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Returns a 'tableColumnGroup' element from the 'table'.
|
|
294
|
+
*
|
|
295
|
+
* @internal
|
|
296
|
+
* @param element A 'table' or 'tableColumnGroup' element.
|
|
297
|
+
* @returns A 'tableColumnGroup' element.
|
|
298
|
+
*/
|
|
299
|
+
export function getColumnGroupElement(element) {
|
|
300
|
+
if (element.is('element', 'tableColumnGroup')) {
|
|
301
|
+
return element;
|
|
302
|
+
}
|
|
303
|
+
const children = element.getChildren();
|
|
304
|
+
return Array
|
|
305
|
+
.from(children)
|
|
306
|
+
.find(element => element.is('element', 'tableColumnGroup'));
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Returns an array of 'tableColumn' elements. It may be empty if there's no `tableColumnGroup` element.
|
|
310
|
+
*
|
|
311
|
+
* @internal
|
|
312
|
+
* @param element A 'table' or 'tableColumnGroup' element.
|
|
313
|
+
* @returns An array of 'tableColumn' elements.
|
|
314
|
+
*/
|
|
315
|
+
export function getTableColumnElements(element) {
|
|
316
|
+
const columnGroupElement = getColumnGroupElement(element);
|
|
317
|
+
if (!columnGroupElement) {
|
|
318
|
+
return [];
|
|
319
|
+
}
|
|
320
|
+
return Array.from(columnGroupElement.getChildren());
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Returns an array of table column widths.
|
|
324
|
+
*
|
|
325
|
+
* @internal
|
|
326
|
+
* @param element A 'table' or 'tableColumnGroup' element.
|
|
327
|
+
* @returns An array of table column widths.
|
|
328
|
+
*/
|
|
329
|
+
export function getTableColumnsWidths(element) {
|
|
330
|
+
return getTableColumnElements(element).map(column => column.getAttribute('columnWidth'));
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Translates the `colSpan` model attribute into additional column widths and returns the resulting array.
|
|
334
|
+
*
|
|
335
|
+
* @internal
|
|
336
|
+
* @param element A 'table' or 'tableColumnGroup' element.
|
|
337
|
+
* @param writer A writer instance.
|
|
338
|
+
* @returns An array of table column widths.
|
|
339
|
+
*/
|
|
340
|
+
export function translateColSpanAttribute(element, writer) {
|
|
341
|
+
const tableColumnElements = getTableColumnElements(element);
|
|
342
|
+
return tableColumnElements.reduce((acc, element) => {
|
|
343
|
+
const columnWidth = element.getAttribute('columnWidth');
|
|
344
|
+
const colSpan = element.getAttribute('colSpan');
|
|
345
|
+
if (!colSpan) {
|
|
346
|
+
acc.push(columnWidth);
|
|
347
|
+
return acc;
|
|
348
|
+
}
|
|
349
|
+
// Translate the `colSpan` model attribute on to the proper number of column widths
|
|
350
|
+
// and remove it from the element.
|
|
351
|
+
// See https://github.com/ckeditor/ckeditor5/issues/14521#issuecomment-1662102889 for more details.
|
|
352
|
+
for (let i = 0; i < colSpan; i++) {
|
|
353
|
+
acc.push(columnWidth);
|
|
354
|
+
}
|
|
355
|
+
writer.removeAttribute('colSpan', element);
|
|
356
|
+
return acc;
|
|
357
|
+
}, []);
|
|
358
|
+
}
|