@ckeditor/ckeditor5-table 29.0.0 → 31.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.
Files changed (73) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +1 -1
  3. package/build/table.js +1 -1
  4. package/build/translations/ar.js +1 -0
  5. package/build/translations/az.js +1 -0
  6. package/build/translations/bg.js +1 -0
  7. package/build/translations/cs.js +1 -0
  8. package/build/translations/da.js +1 -0
  9. package/build/translations/de-ch.js +1 -0
  10. package/build/translations/de.js +1 -0
  11. package/build/translations/en-au.js +1 -0
  12. package/build/translations/en-gb.js +1 -0
  13. package/build/translations/es.js +1 -0
  14. package/build/translations/et.js +1 -0
  15. package/build/translations/fa.js +1 -0
  16. package/build/translations/fi.js +1 -0
  17. package/build/translations/fr.js +1 -0
  18. package/build/translations/gl.js +1 -0
  19. package/build/translations/hi.js +1 -0
  20. package/build/translations/hr.js +1 -0
  21. package/build/translations/hu.js +1 -0
  22. package/build/translations/id.js +1 -0
  23. package/build/translations/it.js +1 -0
  24. package/build/translations/ja.js +1 -0
  25. package/build/translations/ko.js +1 -0
  26. package/build/translations/ku.js +1 -0
  27. package/build/translations/lt.js +1 -0
  28. package/build/translations/lv.js +1 -0
  29. package/build/translations/nb.js +1 -0
  30. package/build/translations/ne.js +1 -0
  31. package/build/translations/nl.js +1 -0
  32. package/build/translations/no.js +1 -0
  33. package/build/translations/pl.js +1 -0
  34. package/build/translations/pt-br.js +1 -0
  35. package/build/translations/ro.js +1 -0
  36. package/build/translations/ru.js +1 -0
  37. package/build/translations/sk.js +1 -0
  38. package/build/translations/sq.js +1 -0
  39. package/build/translations/sr-latn.js +1 -0
  40. package/build/translations/sr.js +1 -0
  41. package/build/translations/sv.js +1 -0
  42. package/build/translations/th.js +1 -0
  43. package/build/translations/tk.js +1 -0
  44. package/build/translations/tr.js +1 -0
  45. package/build/translations/ug.js +1 -0
  46. package/build/translations/uk.js +1 -0
  47. package/build/translations/vi.js +1 -0
  48. package/build/translations/zh-cn.js +1 -0
  49. package/build/translations/zh.js +1 -0
  50. package/ckeditor5-metadata.json +174 -0
  51. package/lang/translations/nl.po +2 -2
  52. package/lang/translations/pl.po +3 -3
  53. package/lang/translations/ru.po +3 -3
  54. package/lang/translations/sr-latn.po +3 -3
  55. package/lang/translations/sr.po +3 -3
  56. package/package.json +25 -23
  57. package/src/commands/inserttablecommand.js +18 -2
  58. package/src/commands/selectcolumncommand.js +10 -0
  59. package/src/commands/selectrowcommand.js +10 -0
  60. package/src/converters/downcast.js +1 -18
  61. package/src/converters/table-heading-rows-refresh-post-fixer.js +23 -6
  62. package/src/converters/upcasttable.js +2 -0
  63. package/src/table.js +17 -0
  64. package/src/tablecellproperties/ui/tablecellpropertiesview.js +0 -1
  65. package/src/tableediting.js +71 -2
  66. package/src/tablekeyboard.js +19 -4
  67. package/src/tableproperties/ui/tablepropertiesview.js +0 -1
  68. package/src/tableutils.js +2 -2
  69. package/src/ui/colorinputview.js +2 -2
  70. package/src/utils/ui/contextualballoon.js +3 -8
  71. package/theme/colorinput.css +3 -0
  72. package/CHANGELOG.md +0 -261
  73. package/build/table.js.map +0 -1
@@ -0,0 +1,174 @@
1
+ {
2
+ "plugins": [
3
+ {
4
+ "name": "Table",
5
+ "className": "Table",
6
+ "description": "Adds table creation and editing tools that help content authors bring tabular data into their documents.",
7
+ "docs": "features/table.html",
8
+ "path": "src/table.js",
9
+ "uiComponents": [
10
+ {
11
+ "type": "SplitButton",
12
+ "name": "insertTable",
13
+ "iconPath": "theme/icons/table.svg"
14
+ },
15
+ {
16
+ "type": "Button",
17
+ "name": "tableColumn",
18
+ "iconPath": "theme/icons/table-column.svg",
19
+ "toolbars": [
20
+ "table.contentToolbar"
21
+ ]
22
+ },
23
+ {
24
+ "type": "Button",
25
+ "name": "tableRow",
26
+ "iconPath": "theme/icons/table-row.svg",
27
+ "toolbars": [
28
+ "table.contentToolbar"
29
+ ]
30
+ },
31
+ {
32
+ "type": "Button",
33
+ "name": "mergeTableCells",
34
+ "iconPath": "theme/icons/table-merge-cell.svg",
35
+ "toolbars": [
36
+ "table.contentToolbar"
37
+ ]
38
+ }
39
+ ],
40
+ "htmlOutput": [
41
+ {
42
+ "elements": "figure",
43
+ "classes": "table"
44
+ },
45
+ {
46
+ "elements": [
47
+ "table",
48
+ "thead",
49
+ "tbody",
50
+ "tr"
51
+ ]
52
+ },
53
+ {
54
+ "elements": [
55
+ "td",
56
+ "th"
57
+ ],
58
+ "attributes": [
59
+ "colspan",
60
+ "rowspan"
61
+ ]
62
+ }
63
+ ]
64
+ },
65
+ {
66
+ "name": "Table cell properties",
67
+ "className": "TableCellProperties",
68
+ "description": "Adds the ability to style individual table cells.",
69
+ "docs": "features/table.html#table-and-cell-styling-tools",
70
+ "path": "src/tablecellproperties",
71
+ "requires": [
72
+ "Table",
73
+ "TableToolbar"
74
+ ],
75
+ "uiComponents": [
76
+ {
77
+ "type": "Button",
78
+ "name": "tableCellProperties",
79
+ "iconPath": "theme/icons/table-cell-properties.svg",
80
+ "toolbars": [
81
+ "table.contentToolbar"
82
+ ]
83
+ }
84
+ ],
85
+ "htmlOutput": [
86
+ {
87
+ "elements": [
88
+ "td",
89
+ "th"
90
+ ],
91
+ "styles": [
92
+ "background-color",
93
+ "border",
94
+ "border-*",
95
+ "height",
96
+ "padding",
97
+ "text-align",
98
+ "vertical-align",
99
+ "width"
100
+ ]
101
+ }
102
+ ]
103
+ },
104
+ {
105
+ "name": "Table properties",
106
+ "className": "TableProperties",
107
+ "description": "Adds the ability to style entire tables.",
108
+ "docs": "features/table.html#table-and-cell-styling-tools",
109
+ "path": "src/tableproperties",
110
+ "requires": [
111
+ "Table",
112
+ "TableToolbar"
113
+ ],
114
+ "uiComponents": [
115
+ {
116
+ "type": "Button",
117
+ "name": "tableProperties",
118
+ "iconPath": "theme/icons/table-properties.svg",
119
+ "toolbars": [
120
+ "table.contentToolbar"
121
+ ]
122
+ }
123
+ ],
124
+ "htmlOutput": [
125
+ {
126
+ "elements": "figure",
127
+ "styles": [
128
+ "float",
129
+ "height",
130
+ "width"
131
+ ]
132
+ },
133
+ {
134
+ "elements": "table",
135
+ "styles": [
136
+ "background-color",
137
+ "border",
138
+ "border-*"
139
+ ]
140
+ }
141
+ ]
142
+ },
143
+ {
144
+ "name": "Table toolbar",
145
+ "className": "TableToolbar",
146
+ "description": "Creates configurable toolbars for both the table feature and table content. They show up when the table widget or the content inside a table cell are selected.",
147
+ "docs": "features/table.html#toolbars",
148
+ "path": "src/tabletoolbar.js",
149
+ "requires": [
150
+ "Table"
151
+ ],
152
+ "registeredToolbars": [
153
+ "table.contentToolbar",
154
+ "table.tableToolbar"
155
+ ]
156
+ },
157
+ {
158
+ "name": "Table caption",
159
+ "className": "TableCaption",
160
+ "description": "Adds support for table captions, which inform the reader about the content of the table. Using captions is also beneficial from the accessibility point of view.",
161
+ "docs": "features/table.html#table-caption",
162
+ "path": "src/tablecaption.js",
163
+ "requires": [
164
+ "Table"
165
+ ],
166
+ "htmlOutput": [
167
+ {
168
+ "elements": "figcaption",
169
+ "attributes": "data-placeholder"
170
+ }
171
+ ]
172
+ }
173
+ ]
174
+ }
@@ -38,7 +38,7 @@ msgstr "Verwijder kolom"
38
38
 
39
39
  msgctxt "Label for the select the entire table column button."
40
40
  msgid "Select column"
41
- msgstr ""
41
+ msgstr "Selecteer kolom"
42
42
 
43
43
  msgctxt "Label for the table column dropdown button."
44
44
  msgid "Column"
@@ -62,7 +62,7 @@ msgstr "Verwijder rij"
62
62
 
63
63
  msgctxt "Label for the select the entire table row button."
64
64
  msgid "Select row"
65
- msgstr ""
65
+ msgstr "Selecteer rij"
66
66
 
67
67
  msgctxt "Label for the table row dropdown button."
68
68
  msgid "Row"
@@ -250,12 +250,12 @@ msgstr "Wybór koloru"
250
250
 
251
251
  msgctxt "The button label for the table toolbar hiding caption attached to the table."
252
252
  msgid "Toggle caption off"
253
- msgstr ""
253
+ msgstr "Ukryj podpis tabeli"
254
254
 
255
255
  msgctxt "The button label for the table toolbar showing caption attached to the table."
256
256
  msgid "Toggle caption on"
257
- msgstr ""
257
+ msgstr "Pokaż podpis tabeli"
258
258
 
259
259
  msgctxt "The placeholder text for the table caption displayed when the caption is empty."
260
260
  msgid "Enter table caption"
261
- msgstr ""
261
+ msgstr "Wprowadź podpis tabeli"
@@ -250,12 +250,12 @@ msgstr "Выбор цвета"
250
250
 
251
251
  msgctxt "The button label for the table toolbar hiding caption attached to the table."
252
252
  msgid "Toggle caption off"
253
- msgstr ""
253
+ msgstr "Выключить описание"
254
254
 
255
255
  msgctxt "The button label for the table toolbar showing caption attached to the table."
256
256
  msgid "Toggle caption on"
257
- msgstr ""
257
+ msgstr "Включить описание"
258
258
 
259
259
  msgctxt "The placeholder text for the table caption displayed when the caption is empty."
260
260
  msgid "Enter table caption"
261
- msgstr ""
261
+ msgstr "Подпись таблицы"
@@ -250,12 +250,12 @@ msgstr "Birač boja"
250
250
 
251
251
  msgctxt "The button label for the table toolbar hiding caption attached to the table."
252
252
  msgid "Toggle caption off"
253
- msgstr ""
253
+ msgstr "Isključivanje natpisa"
254
254
 
255
255
  msgctxt "The button label for the table toolbar showing caption attached to the table."
256
256
  msgid "Toggle caption on"
257
- msgstr ""
257
+ msgstr "Uključite naslov"
258
258
 
259
259
  msgctxt "The placeholder text for the table caption displayed when the caption is empty."
260
260
  msgid "Enter table caption"
261
- msgstr ""
261
+ msgstr "Unesite naslov tabele"
@@ -250,12 +250,12 @@ msgstr "Бирач боја"
250
250
 
251
251
  msgctxt "The button label for the table toolbar hiding caption attached to the table."
252
252
  msgid "Toggle caption off"
253
- msgstr ""
253
+ msgstr "Искључивање натписа "
254
254
 
255
255
  msgctxt "The button label for the table toolbar showing caption attached to the table."
256
256
  msgid "Toggle caption on"
257
- msgstr ""
257
+ msgstr "Укључите наслов "
258
258
 
259
259
  msgctxt "The placeholder text for the table caption displayed when the caption is empty."
260
260
  msgid "Enter table caption"
261
- msgstr ""
261
+ msgstr "Унесите наслов табеле "
package/package.json CHANGED
@@ -1,39 +1,40 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-table",
3
- "version": "29.0.0",
3
+ "version": "31.0.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": "^29.0.0",
15
+ "ckeditor5": "^31.0.0",
15
16
  "lodash-es": "^4.17.15"
16
17
  },
17
18
  "devDependencies": {
18
- "@ckeditor/ckeditor5-alignment": "^29.0.0",
19
- "@ckeditor/ckeditor5-block-quote": "^29.0.0",
20
- "@ckeditor/ckeditor5-clipboard": "^29.0.0",
21
- "@ckeditor/ckeditor5-core": "^29.0.0",
22
- "@ckeditor/ckeditor5-dev-utils": "^25.0.0",
23
- "@ckeditor/ckeditor5-editor-classic": "^29.0.0",
24
- "@ckeditor/ckeditor5-engine": "^29.0.0",
25
- "@ckeditor/ckeditor5-horizontal-line": "^29.0.0",
26
- "@ckeditor/ckeditor5-image": "^29.0.0",
27
- "@ckeditor/ckeditor5-indent": "^29.0.0",
28
- "@ckeditor/ckeditor5-list": "^29.0.0",
29
- "@ckeditor/ckeditor5-media-embed": "^29.0.0",
30
- "@ckeditor/ckeditor5-paragraph": "^29.0.0",
31
- "@ckeditor/ckeditor5-theme-lark": "^29.0.0",
32
- "@ckeditor/ckeditor5-typing": "^29.0.0",
33
- "@ckeditor/ckeditor5-ui": "^29.0.0",
34
- "@ckeditor/ckeditor5-undo": "^29.0.0",
35
- "@ckeditor/ckeditor5-utils": "^29.0.0",
36
- "@ckeditor/ckeditor5-widget": "^29.0.0",
19
+ "@ckeditor/ckeditor5-alignment": "^31.0.0",
20
+ "@ckeditor/ckeditor5-block-quote": "^31.0.0",
21
+ "@ckeditor/ckeditor5-clipboard": "^31.0.0",
22
+ "@ckeditor/ckeditor5-core": "^31.0.0",
23
+ "@ckeditor/ckeditor5-dev-utils": "^25.4.0",
24
+ "@ckeditor/ckeditor5-editor-classic": "^31.0.0",
25
+ "@ckeditor/ckeditor5-engine": "^31.0.0",
26
+ "@ckeditor/ckeditor5-horizontal-line": "^31.0.0",
27
+ "@ckeditor/ckeditor5-image": "^31.0.0",
28
+ "@ckeditor/ckeditor5-indent": "^31.0.0",
29
+ "@ckeditor/ckeditor5-list": "^31.0.0",
30
+ "@ckeditor/ckeditor5-media-embed": "^31.0.0",
31
+ "@ckeditor/ckeditor5-paragraph": "^31.0.0",
32
+ "@ckeditor/ckeditor5-theme-lark": "^31.0.0",
33
+ "@ckeditor/ckeditor5-typing": "^31.0.0",
34
+ "@ckeditor/ckeditor5-ui": "^31.0.0",
35
+ "@ckeditor/ckeditor5-undo": "^31.0.0",
36
+ "@ckeditor/ckeditor5-utils": "^31.0.0",
37
+ "@ckeditor/ckeditor5-widget": "^31.0.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"
@@ -41,17 +41,33 @@ export default class InsertTableCommand extends Command {
41
41
  * @param {Object} options
42
42
  * @param {Number} [options.rows=2] The number of rows to create in the inserted table.
43
43
  * @param {Number} [options.columns=2] The number of columns to create in the inserted table.
44
- * @param {Number} [options.headingRows=0] The number of heading rows.
45
- * @param {Number} [options.headingColumns=0] The number of heading columns.
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.
46
50
  * @fires execute
47
51
  */
48
52
  execute( options = {} ) {
49
53
  const model = this.editor.model;
50
54
  const selection = model.document.selection;
51
55
  const tableUtils = this.editor.plugins.get( 'TableUtils' );
56
+ const config = this.editor.config.get( 'table' );
52
57
 
53
58
  const insertionRange = findOptimalInsertionRange( selection, model );
54
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
+ }
70
+
55
71
  model.change( writer => {
56
72
  const table = tableUtils.createTable( writer, options );
57
73
 
@@ -24,6 +24,16 @@ import { getSelectionAffectedTableCells } from '../utils/selection';
24
24
  * @extends module:core/command~Command
25
25
  */
26
26
  export default class SelectColumnCommand extends Command {
27
+ /**
28
+ * @inheritDoc
29
+ */
30
+ constructor( editor ) {
31
+ super( editor );
32
+
33
+ // It does not affect data so should be enabled in read-only mode.
34
+ this.affectsData = false;
35
+ }
36
+
27
37
  /**
28
38
  * @inheritDoc
29
39
  */
@@ -23,6 +23,16 @@ import { getRowIndexes, getSelectionAffectedTableCells } from '../utils/selectio
23
23
  * @extends module:core/command~Command
24
24
  */
25
25
  export default class SelectRowCommand extends Command {
26
+ /**
27
+ * @inheritDoc
28
+ */
29
+ constructor( editor ) {
30
+ super( editor );
31
+
32
+ // It does not affect data so should be enabled in read-only mode.
33
+ this.affectsData = false;
34
+ }
35
+
26
36
  /**
27
37
  * @inheritDoc
28
38
  */
@@ -8,8 +8,7 @@
8
8
  */
9
9
 
10
10
  import TableWalker from './../tablewalker';
11
- import { setHighlightHandling, toWidget, toWidgetEditable } from 'ckeditor5/src/widget';
12
- import { toArray } from 'ckeditor5/src/utils';
11
+ import { toWidget, toWidgetEditable } from 'ckeditor5/src/widget';
13
12
 
14
13
  /**
15
14
  * Model table element to view table element conversion helper.
@@ -311,13 +310,6 @@ function renameViewTableCell( tableCell, desiredCellElementName, conversionApi )
311
310
  const editable = viewWriter.createEditableElement( desiredCellElementName, viewCell.getAttributes() );
312
311
  const renamedCell = toWidgetEditable( editable, viewWriter );
313
312
 
314
- setHighlightHandling(
315
- renamedCell,
316
- viewWriter,
317
- ( element, descriptor, writer ) => writer.addClass( toArray( descriptor.classes ), element ),
318
- ( element, descriptor, writer ) => writer.removeClass( toArray( descriptor.classes ), element )
319
- );
320
-
321
313
  viewWriter.insert( viewWriter.createPositionAfter( viewCell ), renamedCell );
322
314
  viewWriter.move( viewWriter.createRangeIn( viewCell ), viewWriter.createPositionAt( renamedCell, 0 ) );
323
315
  viewWriter.remove( viewWriter.createRangeOn( viewCell ) );
@@ -359,15 +351,6 @@ function createViewTableCellElement( tableSlot, tableAttributes, insertPosition,
359
351
  toWidgetEditable( conversionApi.writer.createEditableElement( cellElementName ), conversionApi.writer ) :
360
352
  conversionApi.writer.createContainerElement( cellElementName );
361
353
 
362
- if ( asWidget ) {
363
- setHighlightHandling(
364
- cellElement,
365
- conversionApi.writer,
366
- ( element, descriptor, writer ) => writer.addClass( toArray( descriptor.classes ), element ),
367
- ( element, descriptor, writer ) => writer.removeClass( toArray( descriptor.classes ), element )
368
- );
369
- }
370
-
371
354
  const tableCell = tableSlot.cell;
372
355
 
373
356
  const firstChild = tableCell.getChild( 0 );
@@ -29,14 +29,31 @@ function tableHeadingRowsRefreshPostFixer( model ) {
29
29
  const tablesToRefresh = new Set();
30
30
 
31
31
  for ( const change of differ.getChanges() ) {
32
- if ( change.type != 'attribute' ) {
33
- continue;
34
- }
32
+ if ( change.type === 'attribute' ) {
33
+ const element = change.range.start.nodeAfter;
34
+
35
+ if ( element && element.is( 'element', 'table' ) && change.attributeKey === 'headingRows' ) {
36
+ tablesToRefresh.add( element );
37
+ }
38
+ } else {
39
+ /* istanbul ignore else */
40
+ if ( change.type === 'insert' || change.type === 'remove' ) {
41
+ if ( change.name === 'tableRow' ) {
42
+ const table = change.position.findAncestor( 'table' );
43
+ const headingRows = table.getAttribute( 'headingRows' ) || 0;
35
44
 
36
- const element = change.range.start.nodeAfter;
45
+ if ( change.position.offset < headingRows ) {
46
+ tablesToRefresh.add( table );
47
+ }
48
+ } else if ( change.name === 'tableCell' ) {
49
+ const table = change.position.findAncestor( 'table' );
50
+ const headingColumns = table.getAttribute( 'headingColumns' ) || 0;
37
51
 
38
- if ( element && element.is( 'element', 'table' ) && change.attributeKey == 'headingRows' ) {
39
- tablesToRefresh.add( element );
52
+ if ( change.position.offset < headingColumns ) {
53
+ tablesToRefresh.add( table );
54
+ }
55
+ }
56
+ }
40
57
  }
41
58
  }
42
59
 
@@ -48,6 +48,8 @@ export function upcastTableFigure() {
48
48
  return;
49
49
  }
50
50
 
51
+ conversionApi.consumable.consume( data.viewItem, { name: true, classes: 'table' } );
52
+
51
53
  conversionApi.convertChildren( data.viewItem, conversionApi.writer.createPositionAt( modelTable, 'end' ) );
52
54
  conversionApi.updateConversionResult( modelTable, data );
53
55
  } );
package/src/table.js CHANGED
@@ -74,6 +74,23 @@ export default class Table extends Plugin {
74
74
  * @member {module:table/table~TableConfig} module:core/editor/editorconfig~EditorConfig#table
75
75
  */
76
76
 
77
+ /**
78
+ * Number of rows and columns to render by default as table heading when inserting new tables.
79
+ *
80
+ * You can configure it like this:
81
+ *
82
+ * const tableConfig = {
83
+ * defaultHeadings: {
84
+ * rows: 1,
85
+ * columns: 1
86
+ * }
87
+ * };
88
+ *
89
+ * Both rows and columns properties are optional defaulting to 0 (no heading).
90
+ *
91
+ * @member {Object} module:table/table~TableConfig#defaultHeadings
92
+ */
93
+
77
94
  /**
78
95
  * An array of color definitions (either strings or objects).
79
96
  *
@@ -799,7 +799,6 @@ export default class TableCellPropertiesView extends View {
799
799
  label: t( 'Cancel' ),
800
800
  icon: icons.cancel,
801
801
  class: 'ck-button-cancel',
802
- type: 'cancel',
803
802
  withText: true
804
803
  } );
805
804
 
@@ -114,12 +114,30 @@ export default class TableEditing extends Plugin {
114
114
  } );
115
115
 
116
116
  // Table attributes conversion.
117
- conversion.attributeToAttribute( { model: 'colspan', view: 'colspan' } );
118
- conversion.attributeToAttribute( { model: 'rowspan', view: 'rowspan' } );
117
+ conversion.for( 'downcast' ).attributeToAttribute( { model: 'colspan', view: 'colspan' } );
118
+ conversion.for( 'upcast' ).attributeToAttribute( {
119
+ model: { key: 'colspan', value: upcastCellSpan( 'colspan' ) },
120
+ view: 'colspan'
121
+ } );
122
+
123
+ conversion.for( 'downcast' ).attributeToAttribute( { model: 'rowspan', view: 'rowspan' } );
124
+ conversion.for( 'upcast' ).attributeToAttribute( {
125
+ model: { key: 'rowspan', value: upcastCellSpan( 'rowspan' ) },
126
+ view: 'rowspan'
127
+ } );
119
128
 
120
129
  // Table heading columns conversion (a change of heading rows requires a reconversion of the whole table).
121
130
  conversion.for( 'editingDowncast' ).add( downcastTableHeadingColumnsChange() );
122
131
 
132
+ // Manually adjust model position mappings in a special case, when a table cell contains a paragraph, which is bound
133
+ // to its parent (to the table cell). This custom model-to-view position mapping is necessary in data pipeline only,
134
+ // because only during this conversion a paragraph can be bound to its parent.
135
+ editor.data.mapper.on( 'modelToViewPosition', mapTableCellModelPositionToView() );
136
+
137
+ // Define the config.
138
+ editor.config.define( 'table.defaultHeadings.rows', 0 );
139
+ editor.config.define( 'table.defaultHeadings.columns', 0 );
140
+
123
141
  // Define all the commands.
124
142
  editor.commands.add( 'insertTable', new InsertTableCommand( editor ) );
125
143
  editor.commands.add( 'insertTableRowAbove', new InsertRowCommand( editor, { order: 'above' } ) );
@@ -159,3 +177,54 @@ export default class TableEditing extends Plugin {
159
177
  return [ TableUtils ];
160
178
  }
161
179
  }
180
+
181
+ // Creates a mapper callback to adjust model position mappings in a table cell containing a paragraph, which is bound to its parent
182
+ // (to the table cell). Only positions after this paragraph have to be adjusted, because after binding this paragraph to the table cell,
183
+ // elements located after this paragraph would point either to a non-existent offset inside `tableCell` (if paragraph is empty), or after
184
+ // the first character of the paragraph's text. See https://github.com/ckeditor/ckeditor5/issues/10116.
185
+ //
186
+ // <tableCell><paragraph></paragraph>^</tableCell> -> <td>^&nbsp;</td>
187
+ //
188
+ // <tableCell><paragraph>foobar</paragraph>^</tableCell> -> <td>foobar^</td>
189
+ //
190
+ // @returns {Function}
191
+ function mapTableCellModelPositionToView() {
192
+ return ( evt, data ) => {
193
+ const modelParent = data.modelPosition.parent;
194
+ const modelNodeBefore = data.modelPosition.nodeBefore;
195
+
196
+ if ( !modelParent.is( 'element', 'tableCell' ) ) {
197
+ return;
198
+ }
199
+
200
+ if ( !modelNodeBefore || !modelNodeBefore.is( 'element', 'paragraph' ) ) {
201
+ return;
202
+ }
203
+
204
+ const viewNodeBefore = data.mapper.toViewElement( modelNodeBefore );
205
+ const viewParent = data.mapper.toViewElement( modelParent );
206
+
207
+ if ( viewNodeBefore === viewParent ) {
208
+ // Since the paragraph has already been bound to its parent, update the current position in the model with paragraph's
209
+ // max offset, so it points to the place which should normally (in all other cases) be the end position of this paragraph.
210
+ data.viewPosition = data.mapper.findPositionIn( viewParent, modelNodeBefore.maxOffset );
211
+ }
212
+ };
213
+ }
214
+
215
+ // Returns fixed colspan and rowspan attrbutes values.
216
+ //
217
+ // @private
218
+ // @param {String} type colspan or rowspan.
219
+ // @returns {Function} conversion value function.
220
+ function upcastCellSpan( type ) {
221
+ return cell => {
222
+ const span = parseInt( cell.getAttribute( type ) );
223
+
224
+ if ( Number.isNaN( span ) || span <= 0 ) {
225
+ return null;
226
+ }
227
+
228
+ return span;
229
+ };
230
+ }
@@ -218,10 +218,25 @@ export default class TableKeyboard extends Plugin {
218
218
  return false;
219
219
  }
220
220
 
221
- // Navigation is in the opposite direction than the selection direction so this is shrinking of the selection.
222
- // Selection for sure will not approach cell edge.
223
- if ( expandSelection && !selection.isCollapsed && selection.isBackward == isForward ) {
224
- return false;
221
+ // When the selection is not collapsed.
222
+ if ( !selection.isCollapsed ) {
223
+ if ( expandSelection ) {
224
+ // Navigation is in the opposite direction than the selection direction so this is shrinking of the selection.
225
+ // Selection for sure will not approach cell edge.
226
+ //
227
+ // With a special case when all cell content is selected - then selection should expand to the other cell.
228
+ // Note: When the entire cell gets selected using CTRL+A, the selection is always forward.
229
+ if ( selection.isBackward == isForward && !selection.containsEntireContent( tableCell ) ) {
230
+ return false;
231
+ }
232
+ } else {
233
+ const selectedElement = selection.getSelectedElement();
234
+
235
+ // It will collapse for non-object selected so it's not going to move to other cell.
236
+ if ( !selectedElement || !model.schema.isObject( selectedElement ) ) {
237
+ return false;
238
+ }
239
+ }
225
240
  }
226
241
 
227
242
  // Let's check if the selection is at the beginning/end of the cell.
@@ -690,7 +690,6 @@ export default class TablePropertiesView extends View {
690
690
  label: t( 'Cancel' ),
691
691
  icon: icons.cancel,
692
692
  class: 'ck-button-cancel',
693
- type: 'cancel',
694
693
  withText: true
695
694
  } );
696
695
 
package/src/tableutils.js CHANGED
@@ -106,11 +106,11 @@ export default class TableUtils extends Plugin {
106
106
  createEmptyRows( writer, table, 0, rows, columns );
107
107
 
108
108
  if ( options.headingRows ) {
109
- updateNumericAttribute( 'headingRows', options.headingRows, table, writer, 0 );
109
+ updateNumericAttribute( 'headingRows', Math.min( options.headingRows, rows ), table, writer, 0 );
110
110
  }
111
111
 
112
112
  if ( options.headingColumns ) {
113
- updateNumericAttribute( 'headingColumns', options.headingColumns, table, writer, 0 );
113
+ updateNumericAttribute( 'headingColumns', Math.min( options.headingColumns, columns ), table, writer, 0 );
114
114
  }
115
115
 
116
116
  return table;