@pie-lib/editable-html 9.5.13 → 10.0.0-beta.1

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 (144) hide show
  1. package/CHANGELOG.md +0 -302
  2. package/lib/components.js +116 -0
  3. package/lib/components.js.map +1 -0
  4. package/lib/editor.js +418 -103
  5. package/lib/editor.js.map +1 -1
  6. package/lib/index.js +101 -155
  7. package/lib/index.js.map +1 -1
  8. package/lib/new-serialization.js +320 -0
  9. package/lib/new-serialization.js.map +1 -0
  10. package/lib/old-serialization.js +330 -0
  11. package/lib/parse-html.js +1 -1
  12. package/lib/parse-html.js.map +1 -1
  13. package/lib/plugins/characters/custom-popper.js +1 -1
  14. package/lib/plugins/characters/custom-popper.js.map +1 -1
  15. package/lib/plugins/characters/index.js +21 -19
  16. package/lib/plugins/characters/index.js.map +1 -1
  17. package/lib/plugins/characters/utils.js +1 -1
  18. package/lib/plugins/characters/utils.js.map +1 -1
  19. package/lib/plugins/hotKeys/index.js +67 -0
  20. package/lib/plugins/hotKeys/index.js.map +1 -0
  21. package/lib/plugins/image/alt-dialog.js +1 -6
  22. package/lib/plugins/image/alt-dialog.js.map +1 -1
  23. package/lib/plugins/image/component.js +70 -53
  24. package/lib/plugins/image/component.js.map +1 -1
  25. package/lib/plugins/image/image-toolbar.js +7 -9
  26. package/lib/plugins/image/image-toolbar.js.map +1 -1
  27. package/lib/plugins/image/index.js +83 -27
  28. package/lib/plugins/image/index.js.map +1 -1
  29. package/lib/plugins/image/insert-image-handler.js +72 -33
  30. package/lib/plugins/image/insert-image-handler.js.map +1 -1
  31. package/lib/plugins/index.js +23 -41
  32. package/lib/plugins/index.js.map +1 -1
  33. package/lib/plugins/list/index.js +64 -100
  34. package/lib/plugins/list/index.js.map +1 -1
  35. package/lib/plugins/math/index.js +86 -60
  36. package/lib/plugins/math/index.js.map +1 -1
  37. package/lib/plugins/media/index.js +202 -132
  38. package/lib/plugins/media/index.js.map +1 -1
  39. package/lib/plugins/media/media-dialog.js +17 -16
  40. package/lib/plugins/media/media-dialog.js.map +1 -1
  41. package/lib/plugins/media/media-toolbar.js +3 -3
  42. package/lib/plugins/media/media-toolbar.js.map +1 -1
  43. package/lib/plugins/media/media-wrapper.js +21 -58
  44. package/lib/plugins/media/media-wrapper.js.map +1 -1
  45. package/lib/plugins/respArea/drag-in-the-blank/choice.js +3 -3
  46. package/lib/plugins/respArea/drag-in-the-blank/choice.js.map +1 -1
  47. package/lib/plugins/respArea/drag-in-the-blank/index.js +3 -2
  48. package/lib/plugins/respArea/drag-in-the-blank/index.js.map +1 -1
  49. package/lib/plugins/respArea/explicit-constructed-response/index.js +3 -2
  50. package/lib/plugins/respArea/explicit-constructed-response/index.js.map +1 -1
  51. package/lib/plugins/respArea/icons/index.js +13 -15
  52. package/lib/plugins/respArea/icons/index.js.map +1 -1
  53. package/lib/plugins/respArea/index.js +87 -53
  54. package/lib/plugins/respArea/index.js.map +1 -1
  55. package/lib/plugins/respArea/inline-dropdown/index.js +4 -3
  56. package/lib/plugins/respArea/inline-dropdown/index.js.map +1 -1
  57. package/lib/plugins/respArea/utils.js +17 -20
  58. package/lib/plugins/respArea/utils.js.map +1 -1
  59. package/lib/plugins/table/icons/index.js +1 -1
  60. package/lib/plugins/table/icons/index.js.map +1 -1
  61. package/lib/plugins/table/index.js +381 -212
  62. package/lib/plugins/table/index.js.map +1 -1
  63. package/lib/plugins/table/table-toolbar.js +5 -6
  64. package/lib/plugins/table/table-toolbar.js.map +1 -1
  65. package/lib/plugins/toolbar/default-toolbar.js +55 -11
  66. package/lib/plugins/toolbar/default-toolbar.js.map +1 -1
  67. package/lib/plugins/toolbar/done-button.js +1 -1
  68. package/lib/plugins/toolbar/done-button.js.map +1 -1
  69. package/lib/plugins/toolbar/editor-and-toolbar.js +186 -232
  70. package/lib/plugins/toolbar/editor-and-toolbar.js.map +1 -1
  71. package/lib/plugins/toolbar/index.js +1 -2
  72. package/lib/plugins/toolbar/index.js.map +1 -1
  73. package/lib/plugins/toolbar/toolbar-buttons.js +1 -1
  74. package/lib/plugins/toolbar/toolbar-buttons.js.map +1 -1
  75. package/lib/plugins/toolbar/toolbar.js +253 -239
  76. package/lib/plugins/toolbar/toolbar.js.map +1 -1
  77. package/lib/plugins/utils.js +27 -2
  78. package/lib/plugins/utils.js.map +1 -1
  79. package/lib/serialization.js +1 -1
  80. package/lib/serialization.js.map +1 -1
  81. package/lib/slate-editor.js +302 -0
  82. package/lib/test-serializer.js +189 -0
  83. package/lib/test-serializer.js.map +1 -0
  84. package/lib/theme.js +1 -1
  85. package/lib/theme.js.map +1 -1
  86. package/package.json +18 -14
  87. package/playground/image/data.js +20 -20
  88. package/playground/image/index.html +22 -20
  89. package/playground/image/index.jsx +12 -10
  90. package/playground/index.html +25 -23
  91. package/playground/mathquill/index.html +23 -20
  92. package/playground/mathquill/index.jsx +18 -22
  93. package/playground/prod-test/index.html +24 -20
  94. package/playground/prod-test/index.jsx +5 -3
  95. package/playground/schema-override/data.js +10 -10
  96. package/playground/schema-override/image-plugin.jsx +3 -4
  97. package/playground/schema-override/index.html +21 -19
  98. package/playground/schema-override/index.jsx +13 -14
  99. package/playground/serialization/data.js +10 -10
  100. package/playground/serialization/image-plugin.jsx +3 -4
  101. package/playground/serialization/index.html +22 -20
  102. package/playground/table-examples.html +5 -8
  103. package/playground/webpack.config.js +10 -10
  104. package/src/components.js +135 -0
  105. package/src/editor.jsx +478 -141
  106. package/src/index.jsx +71 -95
  107. package/src/new-serialization.jsx +291 -0
  108. package/src/parse-html.js +1 -1
  109. package/src/plugins/characters/custom-popper.js +7 -7
  110. package/src/plugins/characters/index.jsx +33 -34
  111. package/src/plugins/characters/utils.js +81 -81
  112. package/src/plugins/hotKeys/index.js +54 -0
  113. package/src/plugins/image/alt-dialog.jsx +4 -5
  114. package/src/plugins/image/component.jsx +106 -89
  115. package/src/plugins/image/image-toolbar.jsx +27 -19
  116. package/src/plugins/image/index.jsx +75 -43
  117. package/src/plugins/image/insert-image-handler.js +62 -27
  118. package/src/plugins/index.jsx +23 -41
  119. package/src/plugins/list/index.jsx +70 -95
  120. package/src/plugins/math/index.jsx +102 -82
  121. package/src/plugins/media/index.jsx +159 -124
  122. package/src/plugins/media/media-dialog.js +98 -71
  123. package/src/plugins/media/media-toolbar.jsx +8 -8
  124. package/src/plugins/media/media-wrapper.jsx +29 -30
  125. package/src/plugins/respArea/drag-in-the-blank/choice.jsx +21 -19
  126. package/src/plugins/respArea/drag-in-the-blank/index.jsx +14 -11
  127. package/src/plugins/respArea/explicit-constructed-response/index.jsx +7 -6
  128. package/src/plugins/respArea/icons/index.jsx +11 -14
  129. package/src/plugins/respArea/index.jsx +92 -52
  130. package/src/plugins/respArea/inline-dropdown/index.jsx +9 -8
  131. package/src/plugins/respArea/utils.jsx +26 -35
  132. package/src/plugins/table/icons/index.jsx +17 -11
  133. package/src/plugins/table/index.jsx +288 -231
  134. package/src/plugins/table/table-toolbar.jsx +15 -11
  135. package/src/plugins/toolbar/default-toolbar.jsx +65 -19
  136. package/src/plugins/toolbar/done-button.jsx +4 -4
  137. package/src/plugins/toolbar/editor-and-toolbar.jsx +150 -145
  138. package/src/plugins/toolbar/index.jsx +2 -3
  139. package/src/plugins/toolbar/toolbar-buttons.jsx +11 -11
  140. package/src/plugins/toolbar/toolbar.jsx +244 -221
  141. package/src/plugins/utils.js +21 -4
  142. package/src/serialization.jsx +32 -32
  143. package/src/test-serializer.js +139 -0
  144. package/src/test-serializer.js.rej +20 -0
@@ -1,68 +1,81 @@
1
1
  import React from 'react';
2
- import EditTable from 'slate-edit-table';
3
- import { Block } from 'slate';
2
+ import { Node as SlateNode, Editor, Transforms } from 'slate';
4
3
  import debug from 'debug';
5
4
  import GridOn from '@material-ui/icons/GridOn';
6
5
  import TableToolbar from './table-toolbar';
7
6
  import PropTypes from 'prop-types';
8
- import SlatePropTypes from 'slate-prop-types';
9
- import { withStyles } from '@material-ui/core/styles';
7
+ import { jsx } from 'slate-hyperscript';
8
+ import { makeStyles } from '@material-ui/styles';
10
9
  import convert from 'react-attr-converter';
11
10
  import { object as toStyleObject } from 'to-style';
11
+ import get from 'lodash/get';
12
+ import omit from 'lodash/omit';
13
+ import reduce from 'lodash/reduce';
12
14
 
13
15
  const log = debug('@pie-lib:editable-html:plugins:table');
14
16
 
15
- const Table = withStyles(() => ({
16
- table: {},
17
- }))((props) => {
18
- const nodeAttributes = dataToAttributes(props.node.data);
17
+ const Table = React.forwardRef(props => {
18
+ const nodeAttributes = omit(dataToAttributes(props.element.data), 'newTable');
19
+ const attrs = omit(props.attributes, 'newTable');
19
20
 
20
21
  return (
21
- <table
22
- className={props.classes.table}
23
- {...props.attributes}
24
- {...nodeAttributes}
25
- onFocus={props.onFocus}
26
- onBlur={props.onBlur}
27
- >
28
- <tbody>{props.children}</tbody>
22
+ <table {...attrs} {...nodeAttributes} onFocus={props.onFocus} onBlur={props.onBlur}>
23
+ {props.children}
29
24
  </table>
30
25
  );
31
26
  });
32
27
 
33
28
  Table.propTypes = {
34
29
  attributes: PropTypes.object,
30
+ element: PropTypes.object,
35
31
  onFocus: PropTypes.func,
36
32
  onBlur: PropTypes.func,
37
- node: SlatePropTypes.node,
38
- children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
33
+ node: PropTypes.shape({
34
+ type: PropTypes.string,
35
+ children: PropTypes.array,
36
+ data: PropTypes.object
37
+ }),
38
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired
39
39
  };
40
40
 
41
- const TableRow = (props) => <tr {...props.attributes}>{props.children}</tr>;
41
+ const TableRow = React.forwardRef(props => <tr {...props.attributes}>{props.children}</tr>);
42
42
 
43
43
  TableRow.propTypes = {
44
44
  attributes: PropTypes.object,
45
45
  onFocus: PropTypes.func,
46
46
  onBlur: PropTypes.func,
47
- children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
47
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired
48
+ };
49
+
50
+ const TableBody = React.forwardRef(props => <tbody {...props.attributes}>{props.children}</tbody>);
51
+
52
+ TableBody.propTypes = {
53
+ attributes: PropTypes.object,
54
+ onFocus: PropTypes.func,
55
+ onBlur: PropTypes.func,
56
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired
48
57
  };
49
58
 
50
- const TableCell = withStyles(() => ({
59
+ const useCellStyles = makeStyles({
51
60
  td: {
52
- minWidth: '25px',
53
- },
54
- }))((props) => {
55
- const Tag = props.node.data.get('header') ? 'th' : 'td';
61
+ minWidth: '25px'
62
+ }
63
+ });
64
+
65
+ const TableCell = React.forwardRef(props => {
66
+ const classes = useCellStyles();
67
+ const { node } = props;
68
+ const Tag = get(node, 'data.header') ? 'th' : 'td';
56
69
 
57
- const nodeAttributes = dataToAttributes(props.node.data);
70
+ const nodeAttributes = dataToAttributes(props.element.data);
58
71
  delete nodeAttributes.header;
59
72
 
60
73
  return (
61
74
  <Tag
62
75
  {...props.attributes}
63
76
  {...nodeAttributes}
64
- colSpan={props.node.data.get('colspan')}
65
- className={props.classes[Tag]}
77
+ colSpan={get(node, 'data.colspan')}
78
+ className={classes[Tag]}
66
79
  onFocus={props.onFocus}
67
80
  onBlur={props.onBlur}
68
81
  >
@@ -72,134 +85,234 @@ const TableCell = withStyles(() => ({
72
85
  });
73
86
 
74
87
  TableCell.propTypes = {
88
+ node: PropTypes.object,
89
+ element: PropTypes.object,
75
90
  attributes: PropTypes.object,
76
91
  onFocus: PropTypes.func,
77
92
  onBlur: PropTypes.func,
78
- children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
93
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired
79
94
  };
80
95
 
81
- export const moveFocusToBeginningOfTable = (change) => {
82
- const addedTable = change.value.document.findDescendant((d) => !!d.data && !!d.data.get('newTable'));
83
-
84
- if (!addedTable) {
85
- return;
96
+ const getAncestorByType = (editor, type) => {
97
+ if (!editor || !type) {
98
+ return null;
86
99
  }
87
100
 
88
- change.collapseToStartOf(addedTable);
101
+ const ancestors = SlateNode.ancestors(editor, Editor.path(editor, editor.selection), {
102
+ reverse: true
103
+ });
89
104
 
90
- const update = addedTable.data.remove('newTable');
105
+ for (const [ancestor, ancestorPath] of ancestors) {
106
+ if (ancestor.type === type) {
107
+ return [ancestor, ancestorPath];
108
+ }
109
+ }
91
110
 
92
- change.setNodeByKey(addedTable.key, { data: update });
111
+ return null;
93
112
  };
94
113
 
95
- export default (opts, toolbarPlugins /* : {toolbar: {}}[] */) => {
96
- const core = EditTable({
97
- typeContent: 'div',
98
- });
114
+ const moveToBeginningOfTable = editor => {
115
+ const [tableBlock, tablePath] = getAncestorByType(editor, 'table');
116
+ let firstTdPath;
99
117
 
100
- // fix outdated schema
118
+ for (const [descendant, descendantPath] of SlateNode.descendants(tableBlock, { reverse: true })) {
119
+ if (descendant.type === 'td') {
120
+ firstTdPath = descendantPath;
121
+ }
122
+ }
101
123
 
102
- if (core.schema && core.schema.blocks) {
103
- Object.keys(core.schema.blocks).forEach((key) => {
104
- const block = core.schema.blocks[key];
124
+ Transforms.select(editor, [...tablePath, ...firstTdPath]);
125
+ };
105
126
 
106
- if (block.parent) {
107
- if (block.nodes[0].types) {
108
- block.nodes[0] = {
109
- type: block.nodes[0].types[0],
110
- };
111
- }
127
+ const TABLE_TYPES = ['tbody', 'tr', 'td', 'table'];
112
128
 
113
- if (block.nodes[0].objects) {
114
- block.nodes[0] = {
115
- object: block.nodes[0].objects[0],
116
- };
117
- }
129
+ export default (opts, toolbarPlugins /* : {toolbar: {}}[] */) => {
130
+ const core = {
131
+ utils: {}
132
+ };
118
133
 
119
- block.parent = {
120
- type: block.parent.types[0],
121
- };
122
- } else {
123
- block.nodes[0] = { type: block.nodes[0].types[0] };
134
+ core.utils.createTable = (row = 2, columns = 2) => {
135
+ const tableRows = [];
136
+ const rowLength = new Array(row).fill(0).length;
137
+ const columnsLength = new Array(columns).fill(0).length;
138
+
139
+ for (let i = 0; i < rowLength; i++) {
140
+ const tableRow = { type: 'tr', children: [] };
141
+
142
+ for (let j = 0; j < columnsLength; j++) {
143
+ tableRow.children.push({
144
+ type: 'td',
145
+ children: [
146
+ {
147
+ text: ''
148
+ }
149
+ ]
150
+ });
124
151
  }
125
- });
126
- }
127
152
 
128
- core.utils.getTableBlock = (containerNode, key) => {
129
- const node = containerNode.getDescendant(key);
130
- const ancestors = containerNode.getAncestors(key).push(node);
131
- return ancestors.findLast((p) => p.type === 'table');
153
+ tableRows.push(tableRow);
154
+ }
155
+
156
+ return {
157
+ type: 'table',
158
+ children: [
159
+ {
160
+ type: 'tbody',
161
+ children: tableRows
162
+ }
163
+ ]
164
+ };
132
165
  };
133
166
 
167
+ core.utils.getTableBlock = editor => getAncestorByType(editor, 'table');
168
+
169
+ core.utils.isSelectionInTable = editor => !!core.utils.getTableBlock(editor);
170
+
134
171
  core.utils.createTableWithOptions = (row, columns, extra) => {
135
172
  const createdTable = core.utils.createTable(row, columns);
136
- const newTable = Block.create({
137
- ...createdTable.toJSON(),
138
- ...extra,
139
- });
173
+ const newTable = { ...createdTable, ...extra };
140
174
 
141
175
  return newTable;
142
176
  };
143
177
 
144
178
  core.toolbar = {
145
179
  icon: <GridOn />,
146
- onClick: (value, onChange) => {
180
+ onClick: editor => {
147
181
  log('insert table');
148
- const change = value.change();
149
182
  const newTable = core.utils.createTableWithOptions(2, 2, {
150
183
  data: {
151
184
  border: '1',
152
- newTable: true,
153
- },
185
+ newTable: true
186
+ }
154
187
  });
155
188
 
156
- change.insertBlock(newTable);
157
-
158
- moveFocusToBeginningOfTable(change);
159
- onChange(change);
189
+ editor.insertNode(newTable);
190
+ moveToBeginningOfTable(editor, newTable);
160
191
  },
161
- supports: (node, value) => node && node.object === 'block' && core.utils.isSelectionInTable(value),
162
192
  /**
163
193
  * Note - the node may not be a table node - it may be a node inside a table.
164
194
  */
165
- customToolbar: (node, value, onToolbarDone) => {
195
+ customToolbar: (node, value, editor, onToolbarDone) => {
166
196
  log('[customToolbar] node.data: ', node.data);
167
197
 
168
- const tableBlock = core.utils.getTableBlock(value.document, node?.key);
198
+ const [tableBlock] = core.utils.getTableBlock(editor);
169
199
  log('[customToolbar] tableBlock: ', tableBlock);
170
200
 
171
- const hasBorder = () => tableBlock.data.get('border') && tableBlock.data.get('border') !== '0';
201
+ const hasBorder = () => get(tableBlock, 'data.border') !== '0';
172
202
  const addRow = () => {
173
- const change = core.changes.insertRow(value.change());
174
- onToolbarDone(change, false);
175
- };
203
+ const [trNode, trPath] = getAncestorByType(editor, 'tr');
204
+
205
+ log('[addRow]');
206
+
207
+ if (trNode) {
208
+ const newTr = { type: 'tr', children: [] };
209
+ const columnsLength = trNode.children.length;
210
+
211
+ for (let i = 0; i < columnsLength; i++) {
212
+ newTr.children.push({
213
+ type: 'td',
214
+ children: [
215
+ {
216
+ text: ''
217
+ }
218
+ ]
219
+ });
220
+ }
176
221
 
177
- const addColumn = () => {
178
- const change = core.changes.insertColumn(value.change());
179
- onToolbarDone(change, false);
222
+ Transforms.insertNodes(editor, [newTr], { at: trPath });
223
+ }
180
224
  };
181
225
 
182
226
  const removeRow = () => {
183
- const change = core.changes.removeRow(value.change());
184
- onToolbarDone(change, false);
227
+ const [tBodyNode, tBodyPath] = getAncestorByType(editor, 'tbody');
228
+
229
+ log('[removeRow]');
230
+
231
+ if (tBodyPath) {
232
+ if (tBodyNode.children.length > 1) {
233
+ const [, trPath] = getAncestorByType(editor, 'tr');
234
+
235
+ log('[removeRow]');
236
+
237
+ if (trPath) {
238
+ Transforms.removeNodes(editor, { at: trPath });
239
+ }
240
+ }
241
+ }
242
+ };
243
+
244
+ const addColumn = () => {
245
+ const [tBodyNode, tBodyPath] = getAncestorByType(editor, 'tbody');
246
+
247
+ log('[addColumn]');
248
+
249
+ if (tBodyNode) {
250
+ const emptyTd = {
251
+ type: 'td',
252
+ children: [{ text: '' }]
253
+ };
254
+ const trElements = Editor.nodes(editor, {
255
+ at: tBodyPath, // Path of Editor
256
+ match: node => 'tr' === node.type
257
+ });
258
+
259
+ for (const [trNode, nodePath] of trElements) {
260
+ Transforms.insertNodes(editor, [emptyTd], {
261
+ at: [...nodePath, trNode.children.length]
262
+ });
263
+ }
264
+ }
185
265
  };
186
266
 
187
267
  const removeColumn = () => {
188
- const change = core.changes.removeColumn(value.change());
189
- onToolbarDone(change, false);
268
+ const [tBodyNode, tBodyPath] = getAncestorByType(editor, 'tbody');
269
+
270
+ log('[addColumn]');
271
+
272
+ if (tBodyNode) {
273
+ const currentPath = Editor.path(editor, editor.selection);
274
+ const columnIndex = currentPath[currentPath.length - 2];
275
+ const trElements = Editor.nodes(editor, {
276
+ at: tBodyPath, // Path of Editor
277
+ match: node => 'tr' === node.type
278
+ });
279
+
280
+ for (const [trNode, nodePath] of trElements) {
281
+ if (trNode.children.length > 1) {
282
+ Transforms.removeNodes(editor, { at: [...nodePath, columnIndex] });
283
+ }
284
+ }
285
+ }
190
286
  };
191
287
 
192
288
  const removeTable = () => {
193
- const change = core.changes.removeTable(value.change());
194
- onToolbarDone(change, false);
289
+ const [tableNode, tablePath] = getAncestorByType(editor, 'table');
290
+
291
+ editor.apply({
292
+ type: 'remove_node',
293
+ path: tablePath,
294
+ node: tableNode
295
+ });
195
296
  };
196
297
 
197
298
  const toggleBorder = () => {
198
299
  const { data } = tableBlock;
199
- const update = data.set('border', hasBorder() ? '0' : '1');
300
+ const update = {
301
+ ...data,
302
+ border: hasBorder() ? '0' : '1'
303
+ };
304
+ const [, tablePath] = getAncestorByType(editor, 'table');
305
+
200
306
  log('[toggleBorder] update: ', update);
201
- const change = value.change().setNodeByKey(tableBlock.key, { data: update });
202
- onToolbarDone(change, false);
307
+
308
+ editor.apply({
309
+ type: 'set_node',
310
+ path: tablePath,
311
+ properties: {
312
+ data: node.data
313
+ },
314
+ newProperties: { data: update }
315
+ });
203
316
  };
204
317
 
205
318
  const onDone = () => {
@@ -209,9 +322,9 @@ export default (opts, toolbarPlugins /* : {toolbar: {}}[] */) => {
209
322
 
210
323
  const Tb = () => (
211
324
  <TableToolbar
325
+ editor={editor}
212
326
  plugins={toolbarPlugins}
213
- onChange={(c) => onToolbarDone(c, false)}
214
- value={value}
327
+ onChange={c => onToolbarDone(c, false)}
215
328
  onAddRow={addRow}
216
329
  onRemoveRow={removeRow}
217
330
  onAddColumn={addColumn}
@@ -223,91 +336,27 @@ export default (opts, toolbarPlugins /* : {toolbar: {}}[] */) => {
223
336
  />
224
337
  );
225
338
  return Tb;
226
- },
339
+ }
227
340
  };
228
341
 
229
- const Node = (props) => {
342
+ core.supports = (node, editor) => TABLE_TYPES.includes(node.type);
343
+
344
+ const Node = props => {
230
345
  switch (props.node.type) {
231
346
  case 'table':
232
347
  return <Table {...props} onFocus={opts.onFocus} onBlur={opts.onBlur} />;
233
- case 'table_row':
348
+ case 'tbody':
349
+ return <TableBody {...props} onFocus={opts.onFocus} onBlur={opts.onBlur} />;
350
+ case 'tr':
234
351
  return <TableRow {...props} />;
235
- case 'table_cell':
352
+ case 'td':
236
353
  return <TableCell {...props} onFocus={opts.onFocus} onBlur={opts.onBlur} />;
237
354
  default:
238
355
  return null;
239
356
  }
240
357
  };
241
358
  Node.propTypes = {
242
- node: PropTypes.object,
243
- };
244
-
245
- core.normalizeNode = (node) => {
246
- if (node.object !== 'document') {
247
- return;
248
- }
249
-
250
- const tableAdded = node.findDescendant((d) => d.data && d.data.get('newTable'));
251
-
252
- if (!tableAdded) {
253
- return;
254
- }
255
-
256
- const nodeToSearch = node.getParent(tableAdded.key) || node;
257
- let shouldAddTextAfterNode = false;
258
- const indexToNotHaveTableOn = nodeToSearch.nodes.size - 1;
259
- const indexOfLastTable = nodeToSearch.nodes.findLastIndex((d) => d.type === 'table');
260
-
261
- // if the last table in the document is of type table, we need to do the change
262
- if (indexOfLastTable === indexToNotHaveTableOn) {
263
- shouldAddTextAfterNode = true;
264
- }
265
-
266
- if (!shouldAddTextAfterNode) {
267
- return;
268
- }
269
-
270
- return (change) => {
271
- if (shouldAddTextAfterNode) {
272
- const tableJSON = tableAdded.toJSON();
273
-
274
- // we remove the table node because otherwise we can't add the empty block after it
275
- // we need a block that contains text in order to do it
276
- change.removeNodeByKey(tableAdded.key);
277
-
278
- const newBlock = Block.create({
279
- object: 'block',
280
- type: 'div',
281
- });
282
-
283
- // we add an empty block but that it's going to be normalized
284
- // because it will add the empty text to it like it should
285
- change.insertBlock(newBlock);
286
-
287
- change.withoutNormalization(() => {
288
- // we do these changes without normalization
289
-
290
- // we get the text previous to the new block added
291
- const prevText = change.value.document.getPreviousText(newBlock.key);
292
-
293
- if (prevText) {
294
- // we move focus to the previous text
295
- change.moveFocusTo(prevText.key, prevText.text?.length).moveAnchorTo(prevText.key, prevText.text?.length);
296
- }
297
-
298
- // we insert the table block between the first block with text and the last block with text
299
- change.insertBlock({
300
- ...tableJSON,
301
- data: {
302
- ...tableJSON.data,
303
- newTable: true,
304
- },
305
- });
306
-
307
- moveFocusToBeginningOfTable(change);
308
- });
309
- }
310
- };
359
+ node: PropTypes.object
311
360
  };
312
361
 
313
362
  core.renderNode = Node;
@@ -315,7 +364,7 @@ export default (opts, toolbarPlugins /* : {toolbar: {}}[] */) => {
315
364
  return core;
316
365
  };
317
366
 
318
- export const parseStyleString = (s) => {
367
+ export const parseStyleString = s => {
319
368
  const regex = /([\w-]*)\s*:\s*([^;]*)/g;
320
369
  let match;
321
370
  const result = {};
@@ -325,9 +374,9 @@ export const parseStyleString = (s) => {
325
374
  return result;
326
375
  };
327
376
 
328
- export const reactAttributes = (o) => toStyleObject(o, { camelize: true, addUnits: false });
377
+ export const reactAttributes = o => toStyleObject(o, { camelize: true, addUnits: false });
329
378
 
330
- const attributesToMap = (el) => (acc, attribute) => {
379
+ const attributesToMap = el => (acc, attribute) => {
331
380
  const value = el.getAttribute(attribute);
332
381
  if (value) {
333
382
  if (attribute === 'style') {
@@ -341,17 +390,17 @@ const attributesToMap = (el) => (acc, attribute) => {
341
390
  return acc;
342
391
  };
343
392
 
344
- const dataToAttributes = (data) => {
345
- if (!data || !data.get) {
346
- return {};
347
- }
348
-
349
- return data.reduce((acc, v, name) => {
350
- if (v) {
351
- acc[convert(name)] = v;
352
- }
353
- return acc;
354
- }, {});
393
+ const dataToAttributes = data => {
394
+ return reduce(
395
+ data,
396
+ (acc, v, name) => {
397
+ if (v) {
398
+ acc[convert(name)] = v;
399
+ }
400
+ return acc;
401
+ },
402
+ {}
403
+ );
355
404
  };
356
405
 
357
406
  const attributes = ['border', 'cellpadding', 'cellspacing', 'class', 'style'];
@@ -370,71 +419,79 @@ export const serialization = {
370
419
  : el.children;
371
420
  const c = Array.from(children);
372
421
 
373
- return {
374
- object: 'block',
375
- type: 'table',
376
- nodes: next(c),
377
- data: attributes.reduce(attributesToMap(el), {}),
378
- };
422
+ return jsx(
423
+ 'element',
424
+ {
425
+ type: 'table',
426
+ data: attributes.reduce(attributesToMap(el), {})
427
+ },
428
+ next(c)
429
+ );
430
+ }
431
+ case 'tbody': {
432
+ return jsx(
433
+ 'element',
434
+ {
435
+ type: 'tbody'
436
+ },
437
+ next(el.childNodes)
438
+ );
379
439
  }
380
-
381
440
  case 'th': {
382
- return {
383
- object: 'block',
384
- type: 'table_cell',
385
- nodes: next(el.childNodes),
386
- data: cellAttributes.reduce(attributesToMap(el), { header: true }),
387
- };
441
+ return jsx(
442
+ 'element',
443
+ {
444
+ type: 'th',
445
+ data: cellAttributes.reduce(attributesToMap(el), { header: true })
446
+ },
447
+ next(el.childNodes)
448
+ );
388
449
  }
389
-
390
450
  case 'tr': {
391
- return {
392
- object: 'block',
393
- type: 'table_row',
394
- nodes: next(Array.from(el.children)),
395
- };
451
+ return jsx(
452
+ 'element',
453
+ {
454
+ type: 'tr'
455
+ },
456
+ next(Array.from(el.children))
457
+ );
396
458
  }
397
-
398
459
  case 'td': {
399
- return {
400
- object: 'block',
401
- type: 'table_cell',
402
- nodes: next(Array.from(el.childNodes)),
403
- data: cellAttributes.reduce(attributesToMap(el), { header: false }),
404
- };
460
+ return jsx(
461
+ 'element',
462
+ {
463
+ type: 'td',
464
+ data: cellAttributes.reduce(attributesToMap(el), { header: true })
465
+ },
466
+ next(el.childNodes)
467
+ );
405
468
  }
406
469
  }
407
470
  },
408
471
  serialize(object, children) {
409
- if (object.object !== 'block') {
410
- return;
411
- }
412
-
413
472
  switch (object.type) {
414
473
  case 'table': {
415
474
  const attributes = dataToAttributes(object.data);
416
-
417
475
  return (
418
476
  <table {...attributes}>
419
- <tbody>{children}</tbody>
477
+ {children}
420
478
  </table>
421
479
  );
422
480
  }
423
-
424
- case 'table_row': {
481
+ case 'tbody': {
482
+ return <tbody>{children}</tbody>;
483
+ }
484
+ case 'tr': {
425
485
  return <tr>{children}</tr>;
426
486
  }
427
-
428
- case 'table_cell': {
487
+ case 'td': {
429
488
  const attributes = dataToAttributes(object.data);
430
- delete attributes.header;
431
-
432
- if (object.data.get('header')) {
433
- return <th {...attributes}>{children}</th>;
434
- } else {
435
- return <td {...attributes}>{children}</td>;
436
- }
489
+ return <td {...attributes}>{children}</td>;
490
+ }
491
+ case 'th': {
492
+ const attributes = dataToAttributes(object.data);
493
+ return <th {...attributes}>{children}</th>;
437
494
  }
438
495
  }
439
- },
496
+ }
440
497
  };