@pie-lib/editable-html 11.1.1 → 11.3.0-beta.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 (194) hide show
  1. package/CHANGELOG.md +8 -4
  2. package/NEXT.CHANGELOG.json +1 -0
  3. package/lib/__tests__/editor.test.js +470 -0
  4. package/lib/__tests__/serialization.test.js +246 -0
  5. package/lib/__tests__/utils.js +106 -0
  6. package/lib/block-tags.js +25 -0
  7. package/lib/constants.js +16 -0
  8. package/lib/editor.js +349 -88
  9. package/lib/index.js +26 -10
  10. package/lib/parse-html.js +1 -1
  11. package/lib/plugins/characters/custom-popper.js +1 -1
  12. package/lib/plugins/characters/index.js +9 -4
  13. package/lib/plugins/characters/utils.js +13 -13
  14. package/lib/plugins/css/icons/index.js +37 -0
  15. package/lib/plugins/css/index.js +397 -0
  16. package/lib/plugins/customPlugin/index.js +114 -0
  17. package/lib/plugins/html/icons/index.js +1 -1
  18. package/lib/plugins/html/index.js +12 -8
  19. package/lib/plugins/image/__tests__/component.test.js +51 -0
  20. package/lib/plugins/image/__tests__/image-toolbar-logic.test.js +56 -0
  21. package/lib/plugins/image/__tests__/image-toolbar.test.js +26 -0
  22. package/lib/plugins/image/__tests__/index.test.js +98 -0
  23. package/lib/plugins/image/__tests__/insert-image-handler.test.js +125 -0
  24. package/lib/plugins/image/__tests__/mock-change.js +25 -0
  25. package/lib/plugins/image/alt-dialog.js +1 -1
  26. package/lib/plugins/image/component.js +1 -1
  27. package/lib/plugins/image/image-toolbar.js +1 -1
  28. package/lib/plugins/image/index.js +3 -2
  29. package/lib/plugins/image/insert-image-handler.js +14 -5
  30. package/lib/plugins/index.js +271 -12
  31. package/lib/plugins/list/__tests__/index.test.js +79 -0
  32. package/lib/plugins/list/index.js +131 -1
  33. package/lib/plugins/math/__tests__/index.test.js +300 -0
  34. package/lib/plugins/math/index.js +92 -57
  35. package/lib/plugins/media/__tests__/index.test.js +71 -0
  36. package/lib/plugins/media/index.js +6 -3
  37. package/lib/plugins/media/media-dialog.js +99 -58
  38. package/lib/plugins/media/media-toolbar.js +1 -1
  39. package/lib/plugins/media/media-wrapper.js +1 -1
  40. package/lib/plugins/rendering/index.js +46 -0
  41. package/lib/plugins/respArea/drag-in-the-blank/choice.js +6 -3
  42. package/lib/plugins/respArea/drag-in-the-blank/index.js +1 -1
  43. package/lib/plugins/respArea/explicit-constructed-response/index.js +12 -10
  44. package/lib/plugins/respArea/icons/index.js +1 -1
  45. package/lib/plugins/respArea/index.js +70 -22
  46. package/lib/plugins/respArea/inline-dropdown/index.js +11 -6
  47. package/lib/plugins/respArea/math-templated/index.js +130 -0
  48. package/lib/plugins/respArea/utils.js +17 -2
  49. package/lib/plugins/table/CustomTablePlugin.js +133 -0
  50. package/lib/plugins/table/__tests__/index.test.js +442 -0
  51. package/lib/plugins/table/__tests__/table-toolbar.test.js +54 -0
  52. package/lib/plugins/table/icons/index.js +1 -1
  53. package/lib/plugins/table/index.js +44 -60
  54. package/lib/plugins/table/table-toolbar.js +34 -5
  55. package/lib/plugins/textAlign/icons/index.js +226 -0
  56. package/lib/plugins/textAlign/index.js +34 -0
  57. package/lib/plugins/toolbar/__tests__/default-toolbar.test.js +128 -0
  58. package/lib/plugins/toolbar/__tests__/editor-and-toolbar.test.js +51 -0
  59. package/lib/plugins/toolbar/__tests__/toolbar-buttons.test.js +54 -0
  60. package/lib/plugins/toolbar/__tests__/toolbar.test.js +120 -0
  61. package/lib/plugins/toolbar/default-toolbar.js +83 -28
  62. package/lib/plugins/toolbar/done-button.js +6 -3
  63. package/lib/plugins/toolbar/editor-and-toolbar.js +19 -20
  64. package/lib/plugins/toolbar/index.js +1 -1
  65. package/lib/plugins/toolbar/toolbar-buttons.js +45 -12
  66. package/lib/plugins/toolbar/toolbar.js +36 -12
  67. package/lib/plugins/utils.js +1 -1
  68. package/lib/serialization.js +234 -45
  69. package/lib/theme.js +1 -1
  70. package/package.json +6 -6
  71. package/src/__tests__/editor.test.jsx +363 -0
  72. package/src/__tests__/serialization.test.js +291 -0
  73. package/src/__tests__/utils.js +36 -0
  74. package/src/block-tags.js +17 -0
  75. package/src/constants.js +7 -0
  76. package/src/editor.jsx +303 -49
  77. package/src/index.jsx +19 -10
  78. package/src/plugins/characters/index.jsx +11 -3
  79. package/src/plugins/characters/utils.js +12 -12
  80. package/src/plugins/css/icons/index.jsx +17 -0
  81. package/src/plugins/css/index.jsx +346 -0
  82. package/src/plugins/customPlugin/index.jsx +85 -0
  83. package/src/plugins/html/index.jsx +9 -6
  84. package/src/plugins/image/__tests__/__snapshots__/component.test.jsx.snap +51 -0
  85. package/src/plugins/image/__tests__/__snapshots__/image-toolbar-logic.test.jsx.snap +27 -0
  86. package/src/plugins/image/__tests__/__snapshots__/image-toolbar.test.jsx.snap +44 -0
  87. package/src/plugins/image/__tests__/component.test.jsx +41 -0
  88. package/src/plugins/image/__tests__/image-toolbar-logic.test.jsx +42 -0
  89. package/src/plugins/image/__tests__/image-toolbar.test.jsx +11 -0
  90. package/src/plugins/image/__tests__/index.test.js +95 -0
  91. package/src/plugins/image/__tests__/insert-image-handler.test.js +113 -0
  92. package/src/plugins/image/__tests__/mock-change.js +15 -0
  93. package/src/plugins/image/index.jsx +2 -1
  94. package/src/plugins/image/insert-image-handler.js +13 -6
  95. package/src/plugins/index.jsx +248 -5
  96. package/src/plugins/list/__tests__/index.test.js +54 -0
  97. package/src/plugins/list/index.jsx +130 -0
  98. package/src/plugins/math/__tests__/__snapshots__/index.test.jsx.snap +48 -0
  99. package/src/plugins/math/__tests__/index.test.jsx +245 -0
  100. package/src/plugins/math/index.jsx +87 -56
  101. package/src/plugins/media/__tests__/index.test.js +75 -0
  102. package/src/plugins/media/index.jsx +3 -2
  103. package/src/plugins/media/media-dialog.js +106 -57
  104. package/src/plugins/rendering/index.js +31 -0
  105. package/src/plugins/respArea/drag-in-the-blank/choice.jsx +4 -1
  106. package/src/plugins/respArea/explicit-constructed-response/index.jsx +10 -8
  107. package/src/plugins/respArea/index.jsx +53 -7
  108. package/src/plugins/respArea/inline-dropdown/index.jsx +13 -6
  109. package/src/plugins/respArea/math-templated/index.jsx +104 -0
  110. package/src/plugins/respArea/utils.jsx +11 -0
  111. package/src/plugins/table/CustomTablePlugin.js +113 -0
  112. package/src/plugins/table/__tests__/__snapshots__/table-toolbar.test.jsx.snap +44 -0
  113. package/src/plugins/table/__tests__/index.test.jsx +401 -0
  114. package/src/plugins/table/__tests__/table-toolbar.test.jsx +42 -0
  115. package/src/plugins/table/index.jsx +46 -59
  116. package/src/plugins/table/table-toolbar.jsx +39 -2
  117. package/src/plugins/textAlign/icons/index.jsx +139 -0
  118. package/src/plugins/textAlign/index.jsx +23 -0
  119. package/src/plugins/toolbar/__tests__/__snapshots__/default-toolbar.test.jsx.snap +923 -0
  120. package/src/plugins/toolbar/__tests__/__snapshots__/editor-and-toolbar.test.jsx.snap +20 -0
  121. package/src/plugins/toolbar/__tests__/__snapshots__/toolbar-buttons.test.jsx.snap +36 -0
  122. package/src/plugins/toolbar/__tests__/__snapshots__/toolbar.test.jsx.snap +46 -0
  123. package/src/plugins/toolbar/__tests__/default-toolbar.test.jsx +94 -0
  124. package/src/plugins/toolbar/__tests__/editor-and-toolbar.test.jsx +37 -0
  125. package/src/plugins/toolbar/__tests__/toolbar-buttons.test.jsx +51 -0
  126. package/src/plugins/toolbar/__tests__/toolbar.test.jsx +106 -0
  127. package/src/plugins/toolbar/default-toolbar.jsx +80 -20
  128. package/src/plugins/toolbar/done-button.jsx +3 -1
  129. package/src/plugins/toolbar/editor-and-toolbar.jsx +18 -13
  130. package/src/plugins/toolbar/toolbar-buttons.jsx +52 -11
  131. package/src/plugins/toolbar/toolbar.jsx +31 -8
  132. package/src/serialization.jsx +213 -38
  133. package/README.md +0 -45
  134. package/deploy.sh +0 -16
  135. package/lib/editor.js.map +0 -1
  136. package/lib/index.js.map +0 -1
  137. package/lib/parse-html.js.map +0 -1
  138. package/lib/plugins/characters/custom-popper.js.map +0 -1
  139. package/lib/plugins/characters/index.js.map +0 -1
  140. package/lib/plugins/characters/utils.js.map +0 -1
  141. package/lib/plugins/html/icons/index.js.map +0 -1
  142. package/lib/plugins/html/index.js.map +0 -1
  143. package/lib/plugins/image/alt-dialog.js.map +0 -1
  144. package/lib/plugins/image/component.js.map +0 -1
  145. package/lib/plugins/image/image-toolbar.js.map +0 -1
  146. package/lib/plugins/image/index.js.map +0 -1
  147. package/lib/plugins/image/insert-image-handler.js.map +0 -1
  148. package/lib/plugins/index.js.map +0 -1
  149. package/lib/plugins/list/index.js.map +0 -1
  150. package/lib/plugins/math/index.js.map +0 -1
  151. package/lib/plugins/media/index.js.map +0 -1
  152. package/lib/plugins/media/media-dialog.js.map +0 -1
  153. package/lib/plugins/media/media-toolbar.js.map +0 -1
  154. package/lib/plugins/media/media-wrapper.js.map +0 -1
  155. package/lib/plugins/respArea/drag-in-the-blank/choice.js.map +0 -1
  156. package/lib/plugins/respArea/drag-in-the-blank/index.js.map +0 -1
  157. package/lib/plugins/respArea/explicit-constructed-response/index.js.map +0 -1
  158. package/lib/plugins/respArea/icons/index.js.map +0 -1
  159. package/lib/plugins/respArea/index.js.map +0 -1
  160. package/lib/plugins/respArea/inline-dropdown/index.js.map +0 -1
  161. package/lib/plugins/respArea/utils.js.map +0 -1
  162. package/lib/plugins/table/icons/index.js.map +0 -1
  163. package/lib/plugins/table/index.js.map +0 -1
  164. package/lib/plugins/table/table-toolbar.js.map +0 -1
  165. package/lib/plugins/toolbar/default-toolbar.js.map +0 -1
  166. package/lib/plugins/toolbar/done-button.js.map +0 -1
  167. package/lib/plugins/toolbar/editor-and-toolbar.js.map +0 -1
  168. package/lib/plugins/toolbar/index.js.map +0 -1
  169. package/lib/plugins/toolbar/toolbar-buttons.js.map +0 -1
  170. package/lib/plugins/toolbar/toolbar.js.map +0 -1
  171. package/lib/plugins/utils.js.map +0 -1
  172. package/lib/serialization.js.map +0 -1
  173. package/lib/theme.js.map +0 -1
  174. package/playground/image/data.js +0 -59
  175. package/playground/image/index.html +0 -22
  176. package/playground/image/index.jsx +0 -81
  177. package/playground/index.html +0 -25
  178. package/playground/mathquill/index.html +0 -22
  179. package/playground/mathquill/index.jsx +0 -155
  180. package/playground/package.json +0 -15
  181. package/playground/prod-test/index.html +0 -22
  182. package/playground/prod-test/index.jsx +0 -28
  183. package/playground/schema-override/data.js +0 -29
  184. package/playground/schema-override/image-plugin.jsx +0 -41
  185. package/playground/schema-override/index.html +0 -21
  186. package/playground/schema-override/index.jsx +0 -97
  187. package/playground/serialization/data.js +0 -29
  188. package/playground/serialization/image-plugin.jsx +0 -41
  189. package/playground/serialization/index.html +0 -22
  190. package/playground/serialization/index.jsx +0 -12
  191. package/playground/static.json +0 -3
  192. package/playground/table-examples.html +0 -70
  193. package/playground/webpack.config.js +0 -42
  194. package/static.json +0 -1
@@ -0,0 +1,113 @@
1
+ import EditTable from 'slate-edit-table';
2
+ import { isSelectionInTable } from 'slate-edit-table/dist/utils';
3
+ import { onEnter, onModEnter, onTab, onUpDown } from 'slate-edit-table/dist/handlers';
4
+ import TableOptions from 'slate-edit-table/dist/options';
5
+ import { clearCell } from 'slate-edit-table/dist/changes';
6
+
7
+ function onBackspace(event, change, editor, opts) {
8
+ const { value } = change;
9
+ const { startBlock, endBlock, selection, document } = value;
10
+
11
+ const startCell = document.getClosest(startBlock.key, opts.isCell);
12
+ const endCell = document.getClosest(endBlock.key, opts.isCell);
13
+
14
+ const startBlockIndex = startCell?.nodes?.findIndex((block) => block.key == startBlock.key);
15
+
16
+ // If a cursor is collapsed at the start of the first block, do nothing
17
+ if (startBlockIndex === 0 && selection.isAtStartOf(startBlock)) {
18
+ if (startBlock.isVoid) {
19
+ // Delete the block normally if it is a void block
20
+ return undefined;
21
+ }
22
+
23
+ event.preventDefault();
24
+ return change;
25
+ }
26
+
27
+ // If "normal" deletion, we continue
28
+ if (startCell === endCell) {
29
+ return undefined;
30
+ }
31
+
32
+ // If cursor is between multiple blocks,
33
+ // we clear the content of the cells.
34
+ event.preventDefault();
35
+
36
+ const { blocks } = value;
37
+
38
+ // Get all cells that contains the selection
39
+ const cells = blocks
40
+ .map((node) =>
41
+ node.type === opts.typeCell ? node : document.getClosest(node.key, (a) => a.type === opts.typeCell),
42
+ )
43
+ .toSet();
44
+
45
+ // If the cursor is at the very end of the first cell, ignore it.
46
+ // If the cursor is at the very start of the last cell, ignore it.
47
+ // This behavior is to compensate hanging selection behaviors:
48
+ // https://github.com/ianstormtaylor/slate/pull/1605
49
+ const ignoreFirstCell = value.selection.collapseToStart().isAtEndOf(cells.first());
50
+ const ignoreLastCell = value.selection.collapseToEnd().isAtStartOf(cells.last());
51
+
52
+ let cellsToClear = cells;
53
+ if (ignoreFirstCell) {
54
+ cellsToClear = cellsToClear.rest();
55
+ }
56
+ if (ignoreLastCell) {
57
+ cellsToClear = cellsToClear.butLast();
58
+ }
59
+
60
+ // Clear all the selection
61
+ cellsToClear.forEach((cell) => clearCell(opts, change, cell));
62
+
63
+ // Update the selection properly, and avoid reset of selection
64
+ const updatedStartCell = change.value.document.getDescendant(cellsToClear.first().key);
65
+ return change.collapseToStartOf(updatedStartCell);
66
+ }
67
+
68
+ const KEY_ENTER = 'Enter';
69
+ const KEY_TAB = 'Tab';
70
+ const KEY_BACKSPACE = 'Backspace';
71
+ const KEY_DOWN = 'ArrowDown';
72
+ const KEY_UP = 'ArrowUp';
73
+
74
+ /**
75
+ * User is pressing a key in the editor
76
+ */
77
+ function onKeyDown(opts, event, change, editor) {
78
+ // Only handle events in cells
79
+ if (!isSelectionInTable(opts, change.value)) {
80
+ return undefined;
81
+ }
82
+
83
+ // Build arguments list
84
+ const args = [event, change, editor, opts];
85
+
86
+ switch (event.key) {
87
+ case KEY_ENTER:
88
+ if (event.metaKey && opts.exitBlockType) {
89
+ return onModEnter(...args);
90
+ }
91
+ return onEnter(...args);
92
+
93
+ case KEY_TAB:
94
+ return onTab(...args);
95
+ case KEY_BACKSPACE:
96
+ return onBackspace(...args);
97
+ case KEY_DOWN:
98
+ case KEY_UP:
99
+ return onUpDown(...args);
100
+ default:
101
+ return undefined;
102
+ }
103
+ }
104
+
105
+ export default (opts) => {
106
+ const core = EditTable(opts);
107
+
108
+ const tableOpts = new TableOptions(opts);
109
+
110
+ core.onKeyDown = onKeyDown.bind(null, tableOpts);
111
+
112
+ return core;
113
+ };
@@ -0,0 +1,44 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`table-toolbar snapshot renders 1`] = `
4
+ <div
5
+ className="table-toolbar"
6
+ >
7
+ <div>
8
+ <WithStyles(RawButton)
9
+ onClick={[MockFunction]}
10
+ >
11
+ <WithStyles(Component) />
12
+ </WithStyles(RawButton)>
13
+ <WithStyles(RawButton)
14
+ onClick={[MockFunction]}
15
+ >
16
+ <WithStyles(Component) />
17
+ </WithStyles(RawButton)>
18
+ <WithStyles(RawButton)
19
+ onClick={[MockFunction]}
20
+ >
21
+ <WithStyles(Component) />
22
+ </WithStyles(RawButton)>
23
+ <WithStyles(RawButton)
24
+ onClick={[MockFunction]}
25
+ >
26
+ <WithStyles(Component) />
27
+ </WithStyles(RawButton)>
28
+ <WithStyles(RawButton)
29
+ onClick={[MockFunction]}
30
+ >
31
+ <WithStyles(Component) />
32
+ </WithStyles(RawButton)>
33
+ <WithStyles(RawButton)
34
+ active={true}
35
+ onClick={[MockFunction]}
36
+ >
37
+ <pure(BorderAllIcon) />
38
+ </WithStyles(RawButton)>
39
+ </div>
40
+ <WithStyles(RawDoneButton)
41
+ onClick={[Function]}
42
+ />
43
+ </div>
44
+ `;
@@ -0,0 +1,401 @@
1
+ import EditTable from 'slate-edit-table';
2
+ import TablePlugin, { serialization, parseStyleString, reactAttributes } from '../index';
3
+ import { Data, Block, PathUtils } from 'slate';
4
+ import React from 'react';
5
+
6
+ jest.mock('slate-edit-table', () => {
7
+ const mock = {
8
+ default: jest.fn().mockReturnThis(),
9
+ utils: {
10
+ isSelectionInTable: jest.fn().mockReturnValue(true),
11
+ createTable: jest.fn(function(c) {
12
+ return {
13
+ toJSON: jest.fn().mockReturnValue({ object: 'block', type: 'table' }),
14
+ };
15
+ }),
16
+ },
17
+ changes: {
18
+ insertTable: jest.fn(function(c) {
19
+ return c;
20
+ }),
21
+ },
22
+ };
23
+
24
+ return jest.fn().mockReturnValue(mock);
25
+ });
26
+
27
+ describe('table', () => {
28
+ describe('toolbar', () => {
29
+ describe('onClick', () => {
30
+ let plugin;
31
+ let onChange;
32
+ let findDescendant;
33
+ let insertBlock;
34
+ let changeMock;
35
+
36
+ beforeEach(() => {
37
+ plugin = TablePlugin();
38
+ onChange = jest.fn();
39
+ insertBlock = jest.fn();
40
+ findDescendant = jest.fn();
41
+ changeMock = jest.fn().mockReturnValue({
42
+ insertBlock,
43
+ value: {
44
+ document: {
45
+ findDescendant,
46
+ },
47
+ },
48
+ });
49
+ });
50
+
51
+ it('calls utils.createTable', () => {
52
+ plugin.toolbar.onClick({ change: changeMock }, onChange);
53
+
54
+ expect(EditTable().utils.createTable).toHaveBeenCalledWith(2, 2);
55
+ });
56
+
57
+ it('creates table with border: 1 as default', () => {
58
+ plugin.toolbar.onClick({ change: changeMock }, onChange);
59
+
60
+ expect(insertBlock).toHaveBeenCalledWith(
61
+ Block.create({ key: '2', type: 'table', data: { border: '1', newTable: true } }),
62
+ );
63
+ });
64
+
65
+ it('moves cursor to first cell of the table and removes the newTable property', () => {
66
+ const dataRemoveFn = jest.fn().mockReturnValue({ border: '1' });
67
+ const setNodeByKey = jest.fn();
68
+ const newTableBlock = {
69
+ key: '2',
70
+ data: {
71
+ remove: dataRemoveFn,
72
+ },
73
+ };
74
+ const collapseToStartOf = jest.fn();
75
+
76
+ changeMock = jest.fn().mockReturnValue({
77
+ insertBlock,
78
+ collapseToStartOf,
79
+ setNodeByKey,
80
+ value: {
81
+ document: {
82
+ findDescendant: jest.fn().mockReturnValue(newTableBlock),
83
+ },
84
+ },
85
+ });
86
+ plugin.toolbar.onClick({ change: changeMock }, onChange);
87
+
88
+ expect(collapseToStartOf).toHaveBeenCalledWith(newTableBlock);
89
+ expect(dataRemoveFn).toHaveBeenCalledWith('newTable');
90
+ expect(setNodeByKey).toHaveBeenCalledWith('2', { data: { border: '1' } });
91
+ });
92
+ });
93
+
94
+ describe('supports', () => {
95
+ const assertSupports = (inTable, object, expected) => {
96
+ it(`inTable: ${inTable}, type: ${object} => ${expected}`, () => {
97
+ EditTable().utils.isSelectionInTable.mockReturnValue(inTable);
98
+ const plugin = TablePlugin();
99
+ const supports = plugin.toolbar.supports({ object });
100
+ expect(supports).toEqual(expected);
101
+ });
102
+ };
103
+
104
+ assertSupports(true, 'block', true);
105
+ assertSupports(false, 'block', false);
106
+ assertSupports(true, 'inline', false);
107
+ assertSupports(false, 'inline', false);
108
+ });
109
+
110
+ describe('customToolbar', () => {
111
+ describe('toggleBorder', () => {
112
+ const assertToggle = (border, expectedBorder) => {
113
+ describe(`with initial border of ${border}`, () => {
114
+ let change;
115
+ let done;
116
+
117
+ beforeEach(() => {
118
+ const plugin = TablePlugin();
119
+ change = {
120
+ setNodeByKey: jest.fn().mockReturnThis(),
121
+ };
122
+ plugin.utils.getTableBlock = jest.fn().mockReturnValue({
123
+ key: 'tableKey',
124
+ data: Data.create({ border }),
125
+ });
126
+ const node = { key: 'nodeKey' };
127
+ const value = {
128
+ change: jest.fn().mockReturnValue(change),
129
+ };
130
+ done = jest.fn();
131
+ const Comp = plugin.toolbar.customToolbar(node, value, done);
132
+ const c = Comp();
133
+ c.props.onToggleBorder();
134
+ });
135
+
136
+ it(`calls setNodeByKey with ${expectedBorder}`, () => {
137
+ expect(change.setNodeByKey).toHaveBeenCalledWith('tableKey', {
138
+ data: Data.create({ border: expectedBorder }),
139
+ });
140
+ });
141
+
142
+ it('calls onToolbarDone', () => {
143
+ expect(done).toHaveBeenCalledWith(change, false);
144
+ });
145
+ });
146
+ };
147
+
148
+ assertToggle(null, '1');
149
+ assertToggle(undefined, '1');
150
+ assertToggle('0', '1');
151
+ assertToggle('1', '0');
152
+ assertToggle('2', '0');
153
+ });
154
+ });
155
+
156
+ describe('normalizeNode', () => {
157
+ it('should exit the function if the node is not of type document', () => {
158
+ const tablePlugin = TablePlugin();
159
+ const returnValue = tablePlugin.normalizeNode({ object: 'table' });
160
+
161
+ expect(returnValue).toEqual(undefined);
162
+ });
163
+
164
+ it('should exit there are no changes needed', () => {
165
+ const tablePlugin = TablePlugin();
166
+ const nodes = {
167
+ size: 3,
168
+ findLastIndex: jest.fn().mockReturnValue(1),
169
+ };
170
+ const returnValue = tablePlugin.normalizeNode({
171
+ object: 'document',
172
+ nodes,
173
+ findDescendant: jest.fn().mockReturnValue({ object: 'block', type: 'table' }),
174
+ getParent: jest.fn().mockReturnValue(undefined),
175
+ });
176
+ expect(returnValue).toEqual(undefined);
177
+ });
178
+
179
+ it('should return a function if a table does not have a node before or after it', () => {
180
+ const tablePlugin = TablePlugin();
181
+ const nodes = [
182
+ {
183
+ object: 'block',
184
+ type: 'table',
185
+ key: '99',
186
+ data: Data.create({
187
+ newTable: true,
188
+ }),
189
+ },
190
+ ];
191
+ const findDescendant = jest.fn((callback) => {
192
+ nodes.forEach((n) => callback(n));
193
+ });
194
+ const change = {
195
+ insertNodeByPath: jest.fn(),
196
+ value: {
197
+ document: {
198
+ getPath: jest.fn().mockReturnValue(PathUtils.create([0, 0])),
199
+ },
200
+ },
201
+ };
202
+
203
+ const returnValue = tablePlugin.normalizeNode({
204
+ object: 'document',
205
+ findDescendant,
206
+ getPath: jest.fn().mockReturnValue(PathUtils.create([0, 0])),
207
+ getPreviousNode: jest.fn().mockReturnValue(undefined),
208
+ getNextNode: jest.fn().mockReturnValue(undefined),
209
+ });
210
+
211
+ expect(returnValue).toEqual(expect.any(Function));
212
+
213
+ returnValue(change);
214
+
215
+ expect(change.insertNodeByPath).toHaveBeenCalledWith([0], 0, {
216
+ object: 'block',
217
+ type: 'div',
218
+ });
219
+ });
220
+ });
221
+ });
222
+ });
223
+
224
+ describe('parseStyleString', () => {
225
+ const parses = (s, expected) => {
226
+ it(`parses ${s} -> ${JSON.stringify(expected)}`, () => {
227
+ const result = parseStyleString(s);
228
+ expect(result).toEqual(expected);
229
+ });
230
+ };
231
+ parses(' width: 10px ', { width: '10px' });
232
+ parses(' width: 10px; ', { width: '10px' });
233
+ parses(' border-width: 10px; ', { 'border-width': '10px' });
234
+ parses(' border: solid 1px red; height: 1px', {
235
+ border: 'solid 1px red',
236
+ height: '1px',
237
+ });
238
+ });
239
+
240
+ describe('toStyleString', () => {
241
+ const styleString = (o, expected) => {
242
+ it(`${JSON.stringify(s)} -> ${expected}`, () => {
243
+ const result = toStyleString(o);
244
+ expect(result).toEqual(expected);
245
+ });
246
+ };
247
+ });
248
+
249
+ describe('reactAttributes', () => {
250
+ const attributes = (o, expected) => {
251
+ it(`${JSON.stringify(o)} -> ${JSON.stringify(expected)}`, () => {
252
+ const result = reactAttributes(o);
253
+ expect(result).toEqual(expected);
254
+ });
255
+ };
256
+ attributes({ 'border-width': '10px', 'line-height': 1.56 }, { borderWidth: '10px', lineHeight: '1.56' });
257
+ });
258
+
259
+ describe('serialization', () => {
260
+ describe('deserialize', () => {
261
+ let next;
262
+
263
+ beforeEach(() => {
264
+ next = jest.fn().mockReturnValue([]);
265
+ });
266
+
267
+ describe('table', () => {
268
+ let el;
269
+ let out;
270
+ beforeEach(() => {
271
+ el = {
272
+ tagName: 'table',
273
+ children: [],
274
+ getAttribute: jest.fn((name) => {
275
+ switch (name) {
276
+ case 'border':
277
+ return '1';
278
+ case 'cellspacing':
279
+ return '2';
280
+ case 'cellpadding':
281
+ return '3';
282
+ case 'class':
283
+ return 'table-class';
284
+ case 'style':
285
+ return 'width: 10px';
286
+ }
287
+ }),
288
+ };
289
+ out = serialization.deserialize(el, next);
290
+ });
291
+
292
+ const assertData = (name, value) => {
293
+ it(`data.${name} should eql ${value}`, () => {
294
+ expect(out.data[name]).toEqual(value);
295
+ });
296
+ };
297
+
298
+ assertData('border', '1');
299
+ assertData('cellspacing', '2');
300
+ assertData('cellpadding', '3');
301
+ assertData('class', 'table-class');
302
+ assertData('style', { width: '10px' });
303
+ it('returns a table block', () => {
304
+ expect(out).toMatchObject({
305
+ object: 'block',
306
+ type: 'table',
307
+ nodes: [],
308
+ });
309
+ });
310
+ });
311
+
312
+ it('deserializes tr', () => {
313
+ const el = {
314
+ tagName: 'tr',
315
+ children: [],
316
+ };
317
+
318
+ const out = serialization.deserialize(el, next);
319
+
320
+ expect(out).toEqual({
321
+ object: 'block',
322
+ type: 'table_row',
323
+ nodes: [],
324
+ });
325
+ });
326
+
327
+ it('deserializes td', () => {
328
+ const el = {
329
+ tagName: 'td',
330
+ childNodes: [],
331
+ getAttribute: jest.fn(function(name) {
332
+ const o = {
333
+ class: 'class name',
334
+ colspan: '1',
335
+ rowspan: '1',
336
+ };
337
+ return o[name];
338
+ }),
339
+ };
340
+
341
+ const out = serialization.deserialize(el, next);
342
+
343
+ expect(out).toEqual({
344
+ object: 'block',
345
+ type: 'table_cell',
346
+ nodes: [],
347
+ data: {
348
+ colspan: '1',
349
+ rowspan: '1',
350
+ class: 'class name',
351
+ header: false,
352
+ },
353
+ });
354
+ });
355
+ });
356
+
357
+ describe('serialize', () => {
358
+ it('serializes table', () => {
359
+ const el = serialization.serialize({
360
+ object: 'block',
361
+ type: 'table',
362
+ nodes: [],
363
+ data: Data.create({
364
+ border: '1',
365
+ cellpadding: '2',
366
+ cellspacing: '3',
367
+ }),
368
+ });
369
+
370
+ expect(el).toEqual(
371
+ <table border="1" cellPadding="2" cellSpacing="3">
372
+ <tbody />
373
+ </table>,
374
+ );
375
+ });
376
+
377
+ it('serializes table_row', () => {
378
+ const el = serialization.serialize({
379
+ object: 'block',
380
+ type: 'table_row',
381
+ nodes: [],
382
+ });
383
+
384
+ expect(el).toEqual(<tr />);
385
+ });
386
+ it('serializes table_cell', () => {
387
+ const el = serialization.serialize({
388
+ object: 'block',
389
+ type: 'table_cell',
390
+ nodes: [],
391
+ data: Data.create({
392
+ header: false,
393
+ style: { width: '10px' },
394
+ class: 'foo',
395
+ }),
396
+ });
397
+
398
+ expect(el).toEqual(<td style={{ width: '10px' }} className={'foo'} />);
399
+ });
400
+ });
401
+ });
@@ -0,0 +1,42 @@
1
+ import { shallow } from 'enzyme';
2
+ import React from 'react';
3
+ import { TableToolbar } from '../table-toolbar';
4
+ describe('table-toolbar', () => {
5
+ let onDone, onAddColumn, onAddRow, onRemoveColumn, onRemoveRow, onRemoveTable, onToggleBorder;
6
+
7
+ beforeEach(() => {
8
+ onAddColumn = jest.fn();
9
+ onAddRow = jest.fn();
10
+ onRemoveColumn = jest.fn();
11
+ onRemoveRow = jest.fn();
12
+ onRemoveTable = jest.fn();
13
+ onDone = jest.fn();
14
+ onToggleBorder = jest.fn();
15
+ });
16
+
17
+ const mkWrapper = (extras) => {
18
+ const props = {
19
+ onDone,
20
+ onAddRow,
21
+ onRemoveRow,
22
+ onAddColumn,
23
+ onRemoveColumn,
24
+ onRemoveTable,
25
+ hasBorder: true,
26
+ onToggleBorder,
27
+ classes: {
28
+ tableToolbar: 'table-toolbar',
29
+ },
30
+ ...extras,
31
+ };
32
+
33
+ return shallow(<TableToolbar {...props} />);
34
+ };
35
+
36
+ describe('snapshot', () => {
37
+ it('renders', () => {
38
+ const w = mkWrapper();
39
+ expect(w).toMatchSnapshot();
40
+ });
41
+ });
42
+ });