@ckeditor/ckeditor5-table 27.1.0 → 29.2.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/translations/ar.js +1 -0
- package/build/translations/az.js +1 -0
- package/build/translations/bg.js +1 -0
- package/build/translations/cs.js +1 -0
- package/build/translations/da.js +1 -0
- package/build/translations/de-ch.js +1 -0
- package/build/translations/de.js +1 -0
- package/build/translations/en-au.js +1 -0
- package/build/translations/en-gb.js +1 -0
- package/build/translations/es.js +1 -0
- package/build/translations/et.js +1 -0
- package/build/translations/fa.js +1 -0
- package/build/translations/fi.js +1 -0
- package/build/translations/fr.js +1 -0
- package/build/translations/gl.js +1 -0
- package/build/translations/hi.js +1 -0
- package/build/translations/hr.js +1 -0
- package/build/translations/hu.js +1 -0
- package/build/translations/id.js +1 -0
- package/build/translations/it.js +1 -0
- package/build/translations/ja.js +1 -0
- package/build/translations/ko.js +1 -0
- package/build/translations/ku.js +1 -0
- package/build/translations/lt.js +1 -0
- package/build/translations/lv.js +1 -0
- package/build/translations/nb.js +1 -0
- package/build/translations/ne.js +1 -0
- package/build/translations/nl.js +1 -0
- package/build/translations/no.js +1 -0
- package/build/translations/pl.js +1 -0
- package/build/translations/pt-br.js +1 -0
- package/build/translations/ro.js +1 -0
- package/build/translations/ru.js +1 -0
- package/build/translations/sk.js +1 -0
- package/build/translations/sq.js +1 -0
- package/build/translations/sr-latn.js +1 -0
- package/build/translations/sr.js +1 -0
- package/build/translations/sv.js +1 -0
- package/build/translations/th.js +1 -0
- package/build/translations/tk.js +1 -0
- package/build/translations/tr.js +1 -0
- package/build/translations/ug.js +1 -0
- package/build/translations/uk.js +1 -0
- package/build/translations/vi.js +1 -0
- package/build/translations/zh-cn.js +1 -0
- package/build/translations/zh.js +1 -0
- package/ckeditor5-metadata.json +174 -0
- package/lang/contexts.json +4 -1
- package/lang/translations/ar.po +12 -0
- package/lang/translations/az.po +12 -0
- package/lang/translations/bg.po +12 -0
- package/lang/translations/cs.po +12 -0
- package/lang/translations/da.po +12 -0
- package/lang/translations/de-ch.po +12 -0
- package/lang/translations/de.po +12 -0
- package/lang/translations/en-au.po +12 -0
- package/lang/translations/en-gb.po +12 -0
- package/lang/translations/en.po +12 -0
- package/lang/translations/es.po +12 -0
- package/lang/translations/et.po +12 -0
- package/lang/translations/fa.po +12 -0
- package/lang/translations/fi.po +12 -0
- package/lang/translations/fr.po +12 -0
- package/lang/translations/gl.po +12 -0
- package/lang/translations/hi.po +12 -0
- package/lang/translations/hr.po +12 -0
- package/lang/translations/hu.po +23 -11
- package/lang/translations/id.po +23 -11
- package/lang/translations/it.po +12 -0
- package/lang/translations/ja.po +12 -0
- package/lang/translations/ko.po +12 -0
- package/lang/translations/ku.po +12 -0
- package/lang/translations/lt.po +12 -0
- package/lang/translations/lv.po +12 -0
- package/lang/translations/nb.po +12 -0
- package/lang/translations/ne.po +12 -0
- package/lang/translations/nl.po +12 -0
- package/lang/translations/no.po +12 -0
- package/lang/translations/pl.po +12 -0
- package/lang/translations/pt-br.po +12 -0
- package/lang/translations/ro.po +51 -39
- package/lang/translations/ru.po +12 -0
- package/lang/translations/sk.po +12 -0
- package/lang/translations/sq.po +12 -0
- package/lang/translations/sr-latn.po +12 -0
- package/lang/translations/sr.po +12 -0
- package/lang/translations/sv.po +12 -0
- package/lang/translations/th.po +12 -0
- package/lang/translations/tk.po +12 -0
- package/lang/translations/tr.po +12 -0
- package/lang/translations/ug.po +12 -0
- package/lang/translations/uk.po +12 -0
- package/lang/translations/vi.po +12 -0
- package/lang/translations/zh-cn.po +12 -0
- package/lang/translations/zh.po +12 -0
- package/package.json +25 -23
- package/src/commands/insertcolumncommand.js +2 -3
- package/src/commands/insertrowcommand.js +2 -3
- package/src/commands/inserttablecommand.js +22 -7
- package/src/commands/mergecellcommand.js +5 -3
- package/src/commands/removerowcommand.js +8 -5
- package/src/converters/downcast.js +4 -5
- package/src/converters/table-caption-post-fixer.js +69 -0
- package/src/converters/table-cell-paragraph-post-fixer.js +3 -1
- package/src/converters/table-layout-post-fixer.js +13 -8
- package/src/converters/tableproperties.js +82 -23
- package/src/converters/upcasttable.js +63 -0
- package/src/index.js +18 -33
- package/src/table.js +17 -0
- package/src/tablecaption/tablecaptionediting.js +153 -0
- package/src/tablecaption/tablecaptionui.js +71 -0
- package/src/tablecaption/toggletablecaptioncommand.js +120 -0
- package/src/tablecaption/utils.js +93 -0
- package/src/tablecaption.js +35 -0
- package/src/tablecellproperties/commands/tablecellbackgroundcolorcommand.js +3 -2
- package/src/tablecellproperties/commands/tablecellbordercolorcommand.js +10 -3
- package/src/tablecellproperties/commands/tablecellborderstylecommand.js +10 -3
- package/src/tablecellproperties/commands/tablecellborderwidthcommand.js +17 -4
- package/src/tablecellproperties/commands/tablecellheightcommand.js +10 -3
- package/src/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js +3 -2
- package/src/tablecellproperties/commands/tablecellpaddingcommand.js +17 -4
- package/src/tablecellproperties/commands/tablecellpropertycommand.js +28 -2
- package/src/tablecellproperties/commands/tablecellverticalalignmentcommand.js +3 -2
- package/src/tablecellproperties/commands/tablecellwidthcommand.js +10 -3
- package/src/tablecellproperties/tablecellpropertiesediting.js +164 -65
- package/src/tablecellproperties/tablecellpropertiesui.js +76 -16
- package/src/tablecellproperties/ui/tablecellpropertiesview.js +39 -13
- package/src/tablecellproperties.js +42 -2
- package/src/tableediting.js +76 -6
- package/src/tablekeyboard.js +3 -2
- package/src/tableproperties/commands/tablealignmentcommand.js +3 -2
- package/src/tableproperties/commands/tablebackgroundcolorcommand.js +3 -2
- package/src/tableproperties/commands/tablebordercolorcommand.js +10 -3
- package/src/tableproperties/commands/tableborderstylecommand.js +10 -3
- package/src/tableproperties/commands/tableborderwidthcommand.js +17 -4
- package/src/tableproperties/commands/tableheightcommand.js +10 -3
- package/src/tableproperties/commands/tablepropertycommand.js +28 -2
- package/src/tableproperties/commands/tablewidthcommand.js +10 -3
- package/src/tableproperties/tablepropertiesediting.js +104 -47
- package/src/tableproperties/tablepropertiesui.js +68 -15
- package/src/tableproperties/ui/tablepropertiesview.js +26 -11
- package/src/tableproperties.js +38 -2
- package/src/tableui.js +10 -1
- package/src/tableutils.js +41 -5
- package/src/tablewalker.js +36 -1
- package/src/ui/colorinputview.js +11 -7
- package/src/utils/structure.js +4 -3
- package/src/utils/table-properties.js +41 -0
- package/src/utils/ui/table-properties.js +29 -7
- package/src/utils/ui/widget.js +7 -15
- package/theme/table.css +17 -1
- package/theme/tablecaption.css +53 -0
- package/build/table.js.map +0 -1
package/lang/translations/zh.po
CHANGED
|
@@ -247,3 +247,15 @@ msgstr "尺寸代碼錯誤。試試看 \"10px\" 或 \"2em\" 或簡單寫 \"2\"
|
|
|
247
247
|
msgctxt "The label used by assistive technologies describing a button that opens a color picker, where user can choose a configured color for a certain properties (eg.: background color, color, border-color etc.)."
|
|
248
248
|
msgid "Color picker"
|
|
249
249
|
msgstr "顏色選擇"
|
|
250
|
+
|
|
251
|
+
msgctxt "The button label for the table toolbar hiding caption attached to the table."
|
|
252
|
+
msgid "Toggle caption off"
|
|
253
|
+
msgstr ""
|
|
254
|
+
|
|
255
|
+
msgctxt "The button label for the table toolbar showing caption attached to the table."
|
|
256
|
+
msgid "Toggle caption on"
|
|
257
|
+
msgstr ""
|
|
258
|
+
|
|
259
|
+
msgctxt "The placeholder text for the table caption displayed when the caption is empty."
|
|
260
|
+
msgid "Enter table caption"
|
|
261
|
+
msgstr ""
|
package/package.json
CHANGED
|
@@ -1,39 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ckeditor/ckeditor5-table",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "29.2.0",
|
|
4
4
|
"description": "Table feature for CKEditor 5.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ckeditor",
|
|
7
7
|
"ckeditor5",
|
|
8
8
|
"ckeditor 5",
|
|
9
9
|
"ckeditor5-feature",
|
|
10
|
-
"ckeditor5-plugin"
|
|
10
|
+
"ckeditor5-plugin",
|
|
11
|
+
"ckeditor5-dll"
|
|
11
12
|
],
|
|
12
13
|
"main": "src/index.js",
|
|
13
14
|
"dependencies": {
|
|
14
|
-
"ckeditor5": "^
|
|
15
|
+
"ckeditor5": "^29.2.0",
|
|
15
16
|
"lodash-es": "^4.17.15"
|
|
16
17
|
},
|
|
17
18
|
"devDependencies": {
|
|
18
|
-
"@ckeditor/ckeditor5-alignment": "^
|
|
19
|
-
"@ckeditor/ckeditor5-block-quote": "^
|
|
20
|
-
"@ckeditor/ckeditor5-clipboard": "^
|
|
21
|
-
"@ckeditor/ckeditor5-core": "^
|
|
22
|
-
"@ckeditor/ckeditor5-dev-utils": "^
|
|
23
|
-
"@ckeditor/ckeditor5-editor-classic": "^
|
|
24
|
-
"@ckeditor/ckeditor5-engine": "^
|
|
25
|
-
"@ckeditor/ckeditor5-horizontal-line": "^
|
|
26
|
-
"@ckeditor/ckeditor5-image": "^
|
|
27
|
-
"@ckeditor/ckeditor5-indent": "^
|
|
28
|
-
"@ckeditor/ckeditor5-list": "^
|
|
29
|
-
"@ckeditor/ckeditor5-media-embed": "^
|
|
30
|
-
"@ckeditor/ckeditor5-paragraph": "^
|
|
31
|
-
"@ckeditor/ckeditor5-theme-lark": "^
|
|
32
|
-
"@ckeditor/ckeditor5-typing": "^
|
|
33
|
-
"@ckeditor/ckeditor5-ui": "^
|
|
34
|
-
"@ckeditor/ckeditor5-undo": "^
|
|
35
|
-
"@ckeditor/ckeditor5-utils": "^
|
|
36
|
-
"@ckeditor/ckeditor5-widget": "^
|
|
19
|
+
"@ckeditor/ckeditor5-alignment": "^29.2.0",
|
|
20
|
+
"@ckeditor/ckeditor5-block-quote": "^29.2.0",
|
|
21
|
+
"@ckeditor/ckeditor5-clipboard": "^29.2.0",
|
|
22
|
+
"@ckeditor/ckeditor5-core": "^29.2.0",
|
|
23
|
+
"@ckeditor/ckeditor5-dev-utils": "^25.4.0",
|
|
24
|
+
"@ckeditor/ckeditor5-editor-classic": "^29.2.0",
|
|
25
|
+
"@ckeditor/ckeditor5-engine": "^29.2.0",
|
|
26
|
+
"@ckeditor/ckeditor5-horizontal-line": "^29.2.0",
|
|
27
|
+
"@ckeditor/ckeditor5-image": "^29.2.0",
|
|
28
|
+
"@ckeditor/ckeditor5-indent": "^29.2.0",
|
|
29
|
+
"@ckeditor/ckeditor5-list": "^29.2.0",
|
|
30
|
+
"@ckeditor/ckeditor5-media-embed": "^29.2.0",
|
|
31
|
+
"@ckeditor/ckeditor5-paragraph": "^29.2.0",
|
|
32
|
+
"@ckeditor/ckeditor5-theme-lark": "^29.2.0",
|
|
33
|
+
"@ckeditor/ckeditor5-typing": "^29.2.0",
|
|
34
|
+
"@ckeditor/ckeditor5-ui": "^29.2.0",
|
|
35
|
+
"@ckeditor/ckeditor5-undo": "^29.2.0",
|
|
36
|
+
"@ckeditor/ckeditor5-utils": "^29.2.0",
|
|
37
|
+
"@ckeditor/ckeditor5-widget": "^29.2.0",
|
|
37
38
|
"json-diff": "^0.5.4",
|
|
38
39
|
"webpack": "^4.43.0",
|
|
39
40
|
"webpack-cli": "^3.3.11"
|
|
@@ -55,7 +56,8 @@
|
|
|
55
56
|
"lang",
|
|
56
57
|
"src",
|
|
57
58
|
"theme",
|
|
58
|
-
"build"
|
|
59
|
+
"build",
|
|
60
|
+
"ckeditor5-metadata.json"
|
|
59
61
|
],
|
|
60
62
|
"scripts": {
|
|
61
63
|
"dll:build": "webpack"
|
|
@@ -52,10 +52,9 @@ export default class InsertColumnCommand extends Command {
|
|
|
52
52
|
*/
|
|
53
53
|
refresh() {
|
|
54
54
|
const selection = this.editor.model.document.selection;
|
|
55
|
+
const isAnyCellSelected = !!getSelectionAffectedTableCells( selection ).length;
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
this.isEnabled = !!tableParent;
|
|
57
|
+
this.isEnabled = isAnyCellSelected;
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
/**
|
|
@@ -52,10 +52,9 @@ export default class InsertRowCommand extends Command {
|
|
|
52
52
|
*/
|
|
53
53
|
refresh() {
|
|
54
54
|
const selection = this.editor.model.document.selection;
|
|
55
|
+
const isAnyCellSelected = !!getSelectionAffectedTableCells( selection ).length;
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
this.isEnabled = !!tableParent;
|
|
57
|
+
this.isEnabled = isAnyCellSelected;
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
/**
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Command } from 'ckeditor5/src/core';
|
|
11
|
-
import {
|
|
11
|
+
import { findOptimalInsertionRange } from 'ckeditor5/src/widget';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* The insert table command.
|
|
@@ -30,8 +30,7 @@ export default class InsertTableCommand extends Command {
|
|
|
30
30
|
const selection = model.document.selection;
|
|
31
31
|
const schema = model.schema;
|
|
32
32
|
|
|
33
|
-
this.isEnabled = isAllowedInParent( selection, schema )
|
|
34
|
-
!checkSelectionOnObject( selection, schema );
|
|
33
|
+
this.isEnabled = isAllowedInParent( selection, schema );
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
/**
|
|
@@ -42,21 +41,37 @@ export default class InsertTableCommand extends Command {
|
|
|
42
41
|
* @param {Object} options
|
|
43
42
|
* @param {Number} [options.rows=2] The number of rows to create in the inserted table.
|
|
44
43
|
* @param {Number} [options.columns=2] The number of columns to create in the inserted table.
|
|
45
|
-
* @param {Number} [options.headingRows
|
|
46
|
-
*
|
|
44
|
+
* @param {Number} [options.headingRows] The number of heading rows.
|
|
45
|
+
* If not provided it will default to {@link module:table/table~TableConfig#defaultHeadings `config.table.defaultHeadings.rows`}
|
|
46
|
+
* table config.
|
|
47
|
+
* @param {Number} [options.headingColumns] The number of heading columns.
|
|
48
|
+
* If not provided it will default to {@link module:table/table~TableConfig#defaultHeadings `config.table.defaultHeadings.columns`}
|
|
49
|
+
* table config.
|
|
47
50
|
* @fires execute
|
|
48
51
|
*/
|
|
49
52
|
execute( options = {} ) {
|
|
50
53
|
const model = this.editor.model;
|
|
51
54
|
const selection = model.document.selection;
|
|
52
55
|
const tableUtils = this.editor.plugins.get( 'TableUtils' );
|
|
56
|
+
const config = this.editor.config.get( 'table' );
|
|
53
57
|
|
|
54
|
-
const
|
|
58
|
+
const insertionRange = findOptimalInsertionRange( selection, model );
|
|
59
|
+
|
|
60
|
+
const defaultRows = config.defaultHeadings.rows;
|
|
61
|
+
const defaultColumns = config.defaultHeadings.columns;
|
|
62
|
+
|
|
63
|
+
if ( options.headingRows === undefined && defaultRows ) {
|
|
64
|
+
options.headingRows = defaultRows;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if ( options.headingColumns === undefined && defaultColumns ) {
|
|
68
|
+
options.headingColumns = defaultColumns;
|
|
69
|
+
}
|
|
55
70
|
|
|
56
71
|
model.change( writer => {
|
|
57
72
|
const table = tableUtils.createTable( writer, options );
|
|
58
73
|
|
|
59
|
-
model.insertContent( table,
|
|
74
|
+
model.insertContent( table, insertionRange );
|
|
60
75
|
|
|
61
76
|
writer.setSelection( writer.createPositionAt( table.getNodeByPath( [ 0, 0, 0 ] ), 0 ) );
|
|
62
77
|
} );
|
|
@@ -133,7 +133,7 @@ export default class MergeCellCommand extends Command {
|
|
|
133
133
|
// First get the cell on proper direction.
|
|
134
134
|
const cellToMerge = this.isHorizontal ?
|
|
135
135
|
getHorizontalCell( tableCell, this.direction, tableUtils ) :
|
|
136
|
-
getVerticalCell( tableCell, this.direction );
|
|
136
|
+
getVerticalCell( tableCell, this.direction, tableUtils );
|
|
137
137
|
|
|
138
138
|
if ( !cellToMerge ) {
|
|
139
139
|
return;
|
|
@@ -155,6 +155,7 @@ export default class MergeCellCommand extends Command {
|
|
|
155
155
|
//
|
|
156
156
|
// @param {module:engine/model/element~Element} tableCell
|
|
157
157
|
// @param {String} direction
|
|
158
|
+
// @param {module:table/tableutils~TableUtils} tableUtils
|
|
158
159
|
// @returns {module:engine/model/node~Node|null}
|
|
159
160
|
function getHorizontalCell( tableCell, direction, tableUtils ) {
|
|
160
161
|
const tableRow = tableCell.parent;
|
|
@@ -195,15 +196,16 @@ function getHorizontalCell( tableCell, direction, tableUtils ) {
|
|
|
195
196
|
//
|
|
196
197
|
// @param {module:engine/model/element~Element} tableCell
|
|
197
198
|
// @param {String} direction
|
|
199
|
+
// @param {module:table/tableutils~TableUtils} tableUtils
|
|
198
200
|
// @returns {module:engine/model/node~Node|null}
|
|
199
|
-
function getVerticalCell( tableCell, direction ) {
|
|
201
|
+
function getVerticalCell( tableCell, direction, tableUtils ) {
|
|
200
202
|
const tableRow = tableCell.parent;
|
|
201
203
|
const table = tableRow.parent;
|
|
202
204
|
|
|
203
205
|
const rowIndex = table.getChildIndex( tableRow );
|
|
204
206
|
|
|
205
207
|
// Don't search for mergeable cell if direction points out of the table.
|
|
206
|
-
if ( ( direction == 'down' && rowIndex ===
|
|
208
|
+
if ( ( direction == 'down' && rowIndex === tableUtils.getRows( table ) - 1 ) || ( direction == 'up' && rowIndex === 0 ) ) {
|
|
207
209
|
return;
|
|
208
210
|
}
|
|
209
211
|
|
|
@@ -51,23 +51,25 @@ export default class RemoveRowCommand extends Command {
|
|
|
51
51
|
*/
|
|
52
52
|
execute() {
|
|
53
53
|
const model = this.editor.model;
|
|
54
|
+
const tableUtils = this.editor.plugins.get( 'TableUtils' );
|
|
55
|
+
|
|
54
56
|
const referenceCells = getSelectionAffectedTableCells( model.document.selection );
|
|
55
57
|
const removedRowIndexes = getRowIndexes( referenceCells );
|
|
56
58
|
|
|
57
59
|
const firstCell = referenceCells[ 0 ];
|
|
58
60
|
const table = firstCell.findAncestor( 'table' );
|
|
59
61
|
|
|
60
|
-
const columnIndexToFocus =
|
|
62
|
+
const columnIndexToFocus = tableUtils.getCellLocation( firstCell ).column;
|
|
61
63
|
|
|
62
64
|
model.change( writer => {
|
|
63
65
|
const rowsToRemove = removedRowIndexes.last - removedRowIndexes.first + 1;
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
tableUtils.removeRows( table, {
|
|
66
68
|
at: removedRowIndexes.first,
|
|
67
69
|
rows: rowsToRemove
|
|
68
70
|
} );
|
|
69
71
|
|
|
70
|
-
const cellToFocus = getCellToFocus( table, removedRowIndexes.first, columnIndexToFocus );
|
|
72
|
+
const cellToFocus = getCellToFocus( table, removedRowIndexes.first, columnIndexToFocus, tableUtils.getRows( table ) );
|
|
71
73
|
|
|
72
74
|
writer.setSelection( writer.createPositionAt( cellToFocus, 0 ) );
|
|
73
75
|
} );
|
|
@@ -77,8 +79,9 @@ export default class RemoveRowCommand extends Command {
|
|
|
77
79
|
// Returns a cell that should be focused before removing the row, belonging to the same column as the currently focused cell.
|
|
78
80
|
// * If the row was not the last one, the cell to focus will be in the row that followed it (before removal).
|
|
79
81
|
// * If the row was the last one, the cell to focus will be in the row that preceded it (before removal).
|
|
80
|
-
function getCellToFocus( table, removedRowIndex, columnToFocus ) {
|
|
81
|
-
|
|
82
|
+
function getCellToFocus( table, removedRowIndex, columnToFocus, tableRowCount ) {
|
|
83
|
+
// Don't go beyond last row's index.
|
|
84
|
+
const row = table.getChild( Math.min( removedRowIndex, tableRowCount - 1 ) );
|
|
82
85
|
|
|
83
86
|
// Default to first table cell.
|
|
84
87
|
let cellToFocus = row.getChild( 0 );
|
|
@@ -74,7 +74,8 @@ export function downcastInsertTable( options = {} ) {
|
|
|
74
74
|
for ( const tableRow of table.getChildren() ) {
|
|
75
75
|
const rowIndex = tableRow.index;
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
// Make sure that this is a table row and not some other element (i.e., caption).
|
|
78
|
+
if ( tableRow.is( 'element', 'tableRow' ) && !viewRows.has( rowIndex ) ) {
|
|
78
79
|
viewRows.set( rowIndex, createTr( tableElement, tableRow, rowIndex, tableAttributes, conversionApi ) );
|
|
79
80
|
}
|
|
80
81
|
}
|
|
@@ -257,9 +258,7 @@ export function convertParagraphInTableCell( modelElement, conversionApi ) {
|
|
|
257
258
|
}
|
|
258
259
|
|
|
259
260
|
if ( isSingleParagraphWithoutAttributes( modelElement ) ) {
|
|
260
|
-
|
|
261
|
-
// See #6062.
|
|
262
|
-
return writer.createContainerElement( 'span', { style: 'display:inline-block' } );
|
|
261
|
+
return writer.createContainerElement( 'span', { class: 'ck-table-bogus-paragraph' } );
|
|
263
262
|
} else {
|
|
264
263
|
return writer.createContainerElement( 'p' );
|
|
265
264
|
}
|
|
@@ -270,7 +269,7 @@ export function convertParagraphInTableCell( modelElement, conversionApi ) {
|
|
|
270
269
|
*
|
|
271
270
|
* The paragraph should be converted in the editing view to:
|
|
272
271
|
*
|
|
273
|
-
* * If returned `true` - to a `<span
|
|
272
|
+
* * If returned `true` - to a `<span class="ck-table-bogus-paragraph">`
|
|
274
273
|
* * If returned `false` - to a `<p>`
|
|
275
274
|
*
|
|
276
275
|
* @param {module:engine/model/element~Element} modelElement
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @module table/converters/table-caption-post-fixer
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Injects a table caption post-fixer into the model.
|
|
12
|
+
*
|
|
13
|
+
* The role of the table caption post-fixer is to ensure that the table with caption have the correct structure
|
|
14
|
+
* after a {@link module:engine/model/model~Model#change `change()`} block was executed.
|
|
15
|
+
*
|
|
16
|
+
* The correct structure means that:
|
|
17
|
+
*
|
|
18
|
+
* * If there are many caption model element, they are merged into one model.
|
|
19
|
+
* * A final, merged caption model is placed at the end of the table.
|
|
20
|
+
*
|
|
21
|
+
* @param {module:engine/model/model~Model} model
|
|
22
|
+
*/
|
|
23
|
+
export default function injectTableCaptionPostFixer( model ) {
|
|
24
|
+
model.document.registerPostFixer( writer => tableCaptionPostFixer( writer, model ) );
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// The table caption post-fixer.
|
|
28
|
+
//
|
|
29
|
+
// @param {module:engine/model/writer~Writer} writer
|
|
30
|
+
// @param {module:engine/model/model~Model} model
|
|
31
|
+
function tableCaptionPostFixer( writer, model ) {
|
|
32
|
+
const changes = model.document.differ.getChanges();
|
|
33
|
+
let wasFixed = false;
|
|
34
|
+
|
|
35
|
+
for ( const entry of changes ) {
|
|
36
|
+
if ( entry.type != 'insert' ) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const positionParent = entry.position.parent;
|
|
41
|
+
|
|
42
|
+
if ( positionParent.is( 'element', 'table' ) || entry.name == 'table' ) {
|
|
43
|
+
const table = entry.name == 'table' ? entry.position.nodeAfter : entry.position.parent;
|
|
44
|
+
const captionsToMerge = Array.from( table.getChildren() ).filter( child => child.is( 'element', 'caption' ) );
|
|
45
|
+
const firstCaption = captionsToMerge.shift();
|
|
46
|
+
|
|
47
|
+
if ( !firstCaption ) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Move all the contents of the captions to the first one.
|
|
52
|
+
for ( const caption of captionsToMerge ) {
|
|
53
|
+
writer.move( writer.createRangeIn( caption ), firstCaption, 'end' );
|
|
54
|
+
writer.remove( caption );
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Make sure the final caption is at the end of the table.
|
|
58
|
+
if ( firstCaption.nextSibling ) {
|
|
59
|
+
writer.move( writer.createRangeOn( firstCaption ), table, 'end' );
|
|
60
|
+
wasFixed = true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Do we merged captions and/or moved the single caption to the end of the table?
|
|
64
|
+
wasFixed = !!captionsToMerge.length || wasFixed;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return wasFixed;
|
|
69
|
+
}
|
|
@@ -70,7 +70,9 @@ function fixTable( table, writer ) {
|
|
|
70
70
|
let wasFixed = false;
|
|
71
71
|
|
|
72
72
|
for ( const row of table.getChildren() ) {
|
|
73
|
-
|
|
73
|
+
if ( row.is( 'element', 'tableRow' ) ) {
|
|
74
|
+
wasFixed = fixTableRow( row, writer ) || wasFixed;
|
|
75
|
+
}
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
return wasFixed;
|
|
@@ -291,12 +291,13 @@ function fixTableCellsRowspan( table, writer ) {
|
|
|
291
291
|
function fixTableRowsSizes( table, writer ) {
|
|
292
292
|
let wasFixed = false;
|
|
293
293
|
|
|
294
|
-
const
|
|
294
|
+
const childrenLengths = getChildrenLengths( table );
|
|
295
295
|
const rowsToRemove = [];
|
|
296
296
|
|
|
297
297
|
// Find empty rows.
|
|
298
|
-
for ( const [ rowIndex, size ] of
|
|
299
|
-
|
|
298
|
+
for ( const [ rowIndex, size ] of childrenLengths.entries() ) {
|
|
299
|
+
// Ignore all non-row models.
|
|
300
|
+
if ( !size && table.getChild( rowIndex ).is( 'element', 'tableRow' ) ) {
|
|
300
301
|
rowsToRemove.push( rowIndex );
|
|
301
302
|
}
|
|
302
303
|
}
|
|
@@ -309,10 +310,13 @@ function fixTableRowsSizes( table, writer ) {
|
|
|
309
310
|
|
|
310
311
|
for ( const rowIndex of rowsToRemove.reverse() ) {
|
|
311
312
|
writer.remove( table.getChild( rowIndex ) );
|
|
312
|
-
|
|
313
|
+
childrenLengths.splice( rowIndex, 1 );
|
|
313
314
|
}
|
|
314
315
|
}
|
|
315
316
|
|
|
317
|
+
// Filter out everything that's not a table row.
|
|
318
|
+
const rowsLengths = childrenLengths.filter( ( row, rowIndex ) => table.getChild( rowIndex ).is( 'element', 'tableRow' ) );
|
|
319
|
+
|
|
316
320
|
// Verify if all the rows have the same number of columns.
|
|
317
321
|
const tableSize = rowsLengths[ 0 ];
|
|
318
322
|
const isValid = rowsLengths.every( length => length === tableSize );
|
|
@@ -346,7 +350,8 @@ function fixTableRowsSizes( table, writer ) {
|
|
|
346
350
|
// @returns {Array.<{{cell, rowspan}}>}
|
|
347
351
|
function findCellsToTrim( table ) {
|
|
348
352
|
const headingRows = parseInt( table.getAttribute( 'headingRows' ) || 0 );
|
|
349
|
-
const maxRows = table.
|
|
353
|
+
const maxRows = Array.from( table.getChildren() )
|
|
354
|
+
.reduce( ( count, row ) => row.is( 'element', 'tableRow' ) ? count + 1 : count, 0 );
|
|
350
355
|
|
|
351
356
|
const cellsToTrim = [];
|
|
352
357
|
|
|
@@ -376,12 +381,12 @@ function findCellsToTrim( table ) {
|
|
|
376
381
|
//
|
|
377
382
|
// @param {module:engine/model/element~Element} table
|
|
378
383
|
// @returns {Array.<Number>}
|
|
379
|
-
function
|
|
384
|
+
function getChildrenLengths( table ) {
|
|
380
385
|
// TableWalker will not provide items for the empty rows, we need to pre-fill this array.
|
|
381
386
|
const lengths = new Array( table.childCount ).fill( 0 );
|
|
382
387
|
|
|
383
|
-
for ( const {
|
|
384
|
-
lengths[
|
|
388
|
+
for ( const { rowIndex } of new TableWalker( table, { includeAllSlots: true } ) ) {
|
|
389
|
+
lengths[ rowIndex ]++;
|
|
385
390
|
}
|
|
386
391
|
|
|
387
392
|
return lengths;
|
|
@@ -11,21 +11,33 @@
|
|
|
11
11
|
* Conversion helper for upcasting attributes using normalized styles.
|
|
12
12
|
*
|
|
13
13
|
* @param {module:engine/conversion/conversion~Conversion} conversion
|
|
14
|
-
* @param {
|
|
15
|
-
* @param {String} modelAttribute
|
|
16
|
-
* @param {String} styleName
|
|
14
|
+
* @param {Object} options
|
|
15
|
+
* @param {String} options.modelAttribute The attribute to set.
|
|
16
|
+
* @param {String} options.styleName The style name to convert.
|
|
17
|
+
* @param {String} options.viewElement The view element name that should be converted.
|
|
18
|
+
* @param {String} options.defaultValue The default value for the specified `modelAttribute`.
|
|
19
|
+
* @param {Boolean} [options.reduceBoxSides=false]
|
|
17
20
|
*/
|
|
18
|
-
export function upcastStyleToAttribute( conversion,
|
|
21
|
+
export function upcastStyleToAttribute( conversion, options ) {
|
|
22
|
+
const { viewElement, defaultValue, modelAttribute, styleName, reduceBoxSides = false } = options;
|
|
23
|
+
|
|
19
24
|
conversion.for( 'upcast' ).attributeToAttribute( {
|
|
20
25
|
view: {
|
|
26
|
+
name: viewElement,
|
|
21
27
|
styles: {
|
|
22
28
|
[ styleName ]: /[\s\S]+/
|
|
23
29
|
}
|
|
24
30
|
},
|
|
25
31
|
model: {
|
|
26
|
-
name: modelElement,
|
|
27
32
|
key: modelAttribute,
|
|
28
|
-
value: viewElement =>
|
|
33
|
+
value: viewElement => {
|
|
34
|
+
const normalized = viewElement.getNormalizedStyle( styleName );
|
|
35
|
+
const value = reduceBoxSides ? reduceBoxSidesValue( normalized ) : normalized;
|
|
36
|
+
|
|
37
|
+
if ( defaultValue !== value ) {
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
29
41
|
}
|
|
30
42
|
} );
|
|
31
43
|
}
|
|
@@ -35,8 +47,12 @@ export function upcastStyleToAttribute( conversion, modelElement, modelAttribute
|
|
|
35
47
|
*
|
|
36
48
|
* @param {module:engine/conversion/conversion~Conversion} conversion
|
|
37
49
|
* @param {String} viewElementName
|
|
50
|
+
* @param {Object} defaultBorder The default border values.
|
|
51
|
+
* @param {String} defaultBorder.color The default `borderColor` value.
|
|
52
|
+
* @param {String} defaultBorder.style The default `borderStyle` value.
|
|
53
|
+
* @param {String} defaultBorder.width The default `borderWidth` value.
|
|
38
54
|
*/
|
|
39
|
-
export function upcastBorderStyles( conversion, viewElementName ) {
|
|
55
|
+
export function upcastBorderStyles( conversion, viewElementName, defaultBorder ) {
|
|
40
56
|
conversion.for( 'upcast' ).add( dispatcher => dispatcher.on( 'element:' + viewElementName, ( evt, data, conversionApi ) => {
|
|
41
57
|
// If the element was not converted by element-to-element converter,
|
|
42
58
|
// we should not try to convert the style. See #8393.
|
|
@@ -44,13 +60,21 @@ export function upcastBorderStyles( conversion, viewElementName ) {
|
|
|
44
60
|
return;
|
|
45
61
|
}
|
|
46
62
|
|
|
47
|
-
//
|
|
48
|
-
//
|
|
63
|
+
// Check the most detailed properties. These will be always set directly or
|
|
64
|
+
// when using the "group" properties like: `border-(top|right|bottom|left)` or `border`.
|
|
49
65
|
const stylesToConsume = [
|
|
50
|
-
'border-top',
|
|
51
|
-
'border-
|
|
52
|
-
'border-
|
|
53
|
-
'border-
|
|
66
|
+
'border-top-width',
|
|
67
|
+
'border-top-color',
|
|
68
|
+
'border-top-style',
|
|
69
|
+
'border-bottom-width',
|
|
70
|
+
'border-bottom-color',
|
|
71
|
+
'border-bottom-style',
|
|
72
|
+
'border-right-width',
|
|
73
|
+
'border-right-color',
|
|
74
|
+
'border-right-style',
|
|
75
|
+
'border-left-width',
|
|
76
|
+
'border-left-color',
|
|
77
|
+
'border-left-style'
|
|
54
78
|
].filter( styleName => data.viewItem.hasStyle( styleName ) );
|
|
55
79
|
|
|
56
80
|
if ( !stylesToConsume.length ) {
|
|
@@ -70,9 +94,29 @@ export function upcastBorderStyles( conversion, viewElementName ) {
|
|
|
70
94
|
|
|
71
95
|
conversionApi.consumable.consume( data.viewItem, matcherPattern );
|
|
72
96
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
97
|
+
const normalizedBorder = {
|
|
98
|
+
style: data.viewItem.getNormalizedStyle( 'border-style' ),
|
|
99
|
+
color: data.viewItem.getNormalizedStyle( 'border-color' ),
|
|
100
|
+
width: data.viewItem.getNormalizedStyle( 'border-width' )
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const reducedBorder = {
|
|
104
|
+
style: reduceBoxSidesValue( normalizedBorder.style ),
|
|
105
|
+
color: reduceBoxSidesValue( normalizedBorder.color ),
|
|
106
|
+
width: reduceBoxSidesValue( normalizedBorder.width )
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
if ( reducedBorder.style !== defaultBorder.style ) {
|
|
110
|
+
conversionApi.writer.setAttribute( 'borderStyle', reducedBorder.style, modelElement );
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if ( reducedBorder.color !== defaultBorder.color ) {
|
|
114
|
+
conversionApi.writer.setAttribute( 'borderColor', reducedBorder.color, modelElement );
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if ( reducedBorder.width !== defaultBorder.width ) {
|
|
118
|
+
conversionApi.writer.setAttribute( 'borderWidth', reducedBorder.width, modelElement );
|
|
119
|
+
}
|
|
76
120
|
} ) );
|
|
77
121
|
}
|
|
78
122
|
|
|
@@ -80,11 +124,12 @@ export function upcastBorderStyles( conversion, viewElementName ) {
|
|
|
80
124
|
* Conversion helper for downcasting an attribute to a style.
|
|
81
125
|
*
|
|
82
126
|
* @param {module:engine/conversion/conversion~Conversion} conversion
|
|
83
|
-
* @param {
|
|
84
|
-
* @param {String}
|
|
85
|
-
* @param {String}
|
|
127
|
+
* @param {Object} options
|
|
128
|
+
* @param {String} options.modelElement
|
|
129
|
+
* @param {String} options.modelAttribute
|
|
130
|
+
* @param {String} options.styleName
|
|
86
131
|
*/
|
|
87
|
-
export function downcastAttributeToStyle( conversion, modelElement, modelAttribute, styleName ) {
|
|
132
|
+
export function downcastAttributeToStyle( conversion, { modelElement, modelAttribute, styleName } ) {
|
|
88
133
|
conversion.for( 'downcast' ).attributeToAttribute( {
|
|
89
134
|
model: {
|
|
90
135
|
name: modelElement,
|
|
@@ -103,10 +148,11 @@ export function downcastAttributeToStyle( conversion, modelElement, modelAttribu
|
|
|
103
148
|
* Conversion helper for downcasting attributes from the model table to a view table (not to `<figure>`).
|
|
104
149
|
*
|
|
105
150
|
* @param {module:engine/conversion/conversion~Conversion} conversion
|
|
106
|
-
* @param {
|
|
107
|
-
* @param {String}
|
|
151
|
+
* @param {Object} options
|
|
152
|
+
* @param {String} options.modelAttribute
|
|
153
|
+
* @param {String} options.styleName
|
|
108
154
|
*/
|
|
109
|
-
export function downcastTableAttribute( conversion, modelAttribute, styleName ) {
|
|
155
|
+
export function downcastTableAttribute( conversion, { modelAttribute, styleName } ) {
|
|
110
156
|
conversion.for( 'downcast' ).add( dispatcher => dispatcher.on( `attribute:${ modelAttribute }:table`, ( evt, data, conversionApi ) => {
|
|
111
157
|
const { item, attributeNewValue } = data;
|
|
112
158
|
const { mapper, writer } = conversionApi;
|
|
@@ -124,3 +170,16 @@ export function downcastTableAttribute( conversion, modelAttribute, styleName )
|
|
|
124
170
|
}
|
|
125
171
|
} ) );
|
|
126
172
|
}
|
|
173
|
+
|
|
174
|
+
// Reduces the full top, right, bottom, left object to a single string if all sides are equal.
|
|
175
|
+
function reduceBoxSidesValue( style ) {
|
|
176
|
+
if ( !style ) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const commonValue = [ 'top', 'right', 'bottom', 'left' ]
|
|
181
|
+
.map( side => style[ side ] )
|
|
182
|
+
.reduce( ( result, side ) => result == side ? result : null );
|
|
183
|
+
|
|
184
|
+
return commonValue || style;
|
|
185
|
+
}
|