@atlaskit/editor-plugin-table 2.0.1 → 2.1.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.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/version.json +1 -1
- package/dist/esm/version.json +1 -1
- package/package.json +5 -6
- package/src/__tests__/integration/layout.ts +1 -6
- package/src/__tests__/unit/analytics.ts +0 -21
- package/src/__tests__/unit/commands/misc.ts +0 -2
- package/src/__tests__/unit/commands/sort.ts +0 -131
- package/src/__tests__/unit/commands.ts +2 -264
- package/src/__tests__/unit/copy-paste.ts +1 -36
- package/src/__tests__/unit/event-handlers.ts +1 -113
- package/src/__tests__/unit/get-toolbar-config.ts +0 -29
- package/src/__tests__/unit/index.ts +3 -101
- package/src/__tests__/unit/layout.ts +1 -64
- package/src/__tests__/unit/nodeviews/cell.ts +1 -48
- package/src/__tests__/unit/pm-plugins/main.ts +1 -3
- package/src/__tests__/unit/pm-plugins/table-resizing/event-handlers.ts +2 -20
- package/src/__tests__/unit/sort-column.ts +21 -148
- package/src/__tests__/unit/utils/collapse.ts +3 -39
- package/.eslintrc.js +0 -37
- package/src/__tests__/unit/color-picker.ts +0 -110
- package/src/__tests__/unit/floating-toolbar.ts +0 -95
- package/src/__tests__/unit/keymap.ts +0 -609
- package/src/__tests__/unit/pm-plugins/main-with-allow-collapse.ts +0 -110
- package/src/__tests__/unit/pm-plugins/table-selection-keymap.ts +0 -574
|
@@ -1,609 +0,0 @@
|
|
|
1
|
-
import { TableMap } from '@atlaskit/editor-tables/table-map';
|
|
2
|
-
import { CellSelection } from '@atlaskit/editor-tables/cell-selection';
|
|
3
|
-
import { EditorView } from 'prosemirror-view';
|
|
4
|
-
import {
|
|
5
|
-
selectRow,
|
|
6
|
-
selectColumn,
|
|
7
|
-
findTable,
|
|
8
|
-
} from '@atlaskit/editor-tables/utils';
|
|
9
|
-
import { PluginKey } from 'prosemirror-state';
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
createProsemirrorEditorFactory,
|
|
13
|
-
LightEditorPlugin,
|
|
14
|
-
Preset,
|
|
15
|
-
} from '@atlaskit/editor-test-helpers/create-prosemirror-editor';
|
|
16
|
-
import {
|
|
17
|
-
doc,
|
|
18
|
-
table,
|
|
19
|
-
thCursor,
|
|
20
|
-
tr,
|
|
21
|
-
td,
|
|
22
|
-
tdEmpty,
|
|
23
|
-
tdCursor,
|
|
24
|
-
thEmpty,
|
|
25
|
-
p,
|
|
26
|
-
DocBuilder,
|
|
27
|
-
} from '@atlaskit/editor-test-helpers/doc-builder';
|
|
28
|
-
import { pmNodeBuilder } from '@atlaskit/editor-test-helpers/schema-element-builder';
|
|
29
|
-
import defaultSchema from '@atlaskit/editor-test-helpers/schema';
|
|
30
|
-
import sendKeyToPm from '@atlaskit/editor-test-helpers/send-key-to-pm';
|
|
31
|
-
import { uuid } from '@atlaskit/adf-schema';
|
|
32
|
-
import { uuid as tablesUuid } from '@atlaskit/editor-tables';
|
|
33
|
-
|
|
34
|
-
import { gridPlugin } from '@atlaskit/editor-plugin-grid';
|
|
35
|
-
import panelPlugin from '@atlaskit/editor-core/src/plugins/panel';
|
|
36
|
-
import expandPlugin from '@atlaskit/editor-core/src/plugins/expand';
|
|
37
|
-
import tasksDecisionsPlugin from '@atlaskit/editor-core/src/plugins/tasks-and-decisions';
|
|
38
|
-
import selectionPlugin from '@atlaskit/editor-core/src/plugins/selection';
|
|
39
|
-
import mediaPlugin from '@atlaskit/editor-core/src/plugins/media';
|
|
40
|
-
import type { analyticsPlugin } from '@atlaskit/editor-plugin-analytics';
|
|
41
|
-
import listPlugin from '@atlaskit/editor-core/src/plugins/list';
|
|
42
|
-
import blockTypePlugin from '@atlaskit/editor-core/src/plugins/block-type';
|
|
43
|
-
import codeBlockPlugin from '@atlaskit/editor-core/src/plugins/code-block';
|
|
44
|
-
import rulePlugin from '@atlaskit/editor-core/src/plugins/rule';
|
|
45
|
-
import mentionsPlugin from '@atlaskit/editor-core/src/plugins/mentions';
|
|
46
|
-
import emojiPlugin from '@atlaskit/editor-core/src/plugins/emoji';
|
|
47
|
-
import jiraIssuePlugin from '@atlaskit/editor-core/src/plugins/jira-issue';
|
|
48
|
-
import extensionPlugin from '@atlaskit/editor-core/src/plugins/extension';
|
|
49
|
-
import datePlugin from '@atlaskit/editor-core/src/plugins/date';
|
|
50
|
-
import layoutPlugin from '@atlaskit/editor-core/src/plugins/layout';
|
|
51
|
-
import statusPlugin from '@atlaskit/editor-core/src/plugins/status';
|
|
52
|
-
import floatingToolbarPlugin from '@atlaskit/editor-core/src/plugins/floating-toolbar';
|
|
53
|
-
import tablePlugin from '../../plugins/table';
|
|
54
|
-
import { TablePluginState } from '../../plugins/table/types';
|
|
55
|
-
import { pluginKey } from '../../plugins/table/pm-plugins/plugin-key';
|
|
56
|
-
import { widthPlugin } from '@atlaskit/editor-plugin-width';
|
|
57
|
-
import editorDisabledPlugin from '@atlaskit/editor-core/src/plugins/editor-disabled';
|
|
58
|
-
import featureFlagsPlugin from '@atlaskit/editor-plugin-feature-flags';
|
|
59
|
-
import { contentInsertionPlugin } from '@atlaskit/editor-plugin-content-insertion';
|
|
60
|
-
import { decorationsPlugin } from '@atlaskit/editor-plugin-decorations';
|
|
61
|
-
|
|
62
|
-
const TABLE_LOCAL_ID = 'test-table-local-id';
|
|
63
|
-
|
|
64
|
-
// We don't need to test if the analytics implementation works (tested elsewhere)
|
|
65
|
-
// We just want to know if the action is called.
|
|
66
|
-
const mockAttachPayload = jest.fn();
|
|
67
|
-
const analyticsPluginFake = () => ({
|
|
68
|
-
name: 'analytics',
|
|
69
|
-
actions: {
|
|
70
|
-
attachAnalyticsEvent: mockAttachPayload.mockImplementation(() => () => {}),
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
describe('table keymap', () => {
|
|
75
|
-
beforeAll(() => {
|
|
76
|
-
uuid.setStatic(TABLE_LOCAL_ID);
|
|
77
|
-
tablesUuid.setStatic(TABLE_LOCAL_ID);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
afterAll(() => {
|
|
81
|
-
uuid.setStatic(false);
|
|
82
|
-
tablesUuid.setStatic(false);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
const createEditor = createProsemirrorEditorFactory();
|
|
86
|
-
const preset = new Preset<LightEditorPlugin>()
|
|
87
|
-
.add([featureFlagsPlugin, {}])
|
|
88
|
-
.add([analyticsPluginFake as unknown as typeof analyticsPlugin, {}])
|
|
89
|
-
.add(contentInsertionPlugin)
|
|
90
|
-
.add(decorationsPlugin)
|
|
91
|
-
.add(widthPlugin)
|
|
92
|
-
.add(gridPlugin)
|
|
93
|
-
.add(selectionPlugin)
|
|
94
|
-
.add([tablePlugin, { tableOptions: {} }])
|
|
95
|
-
.add(expandPlugin)
|
|
96
|
-
.add(tasksDecisionsPlugin)
|
|
97
|
-
.add(panelPlugin)
|
|
98
|
-
.add(listPlugin)
|
|
99
|
-
.add(blockTypePlugin)
|
|
100
|
-
.add([codeBlockPlugin, { appearance: 'full-page' }])
|
|
101
|
-
.add(rulePlugin)
|
|
102
|
-
.add(mentionsPlugin)
|
|
103
|
-
.add(emojiPlugin)
|
|
104
|
-
.add(jiraIssuePlugin)
|
|
105
|
-
.add(extensionPlugin)
|
|
106
|
-
.add(editorDisabledPlugin)
|
|
107
|
-
.add(datePlugin)
|
|
108
|
-
.add(layoutPlugin)
|
|
109
|
-
.add([statusPlugin, { menuDisabled: false }])
|
|
110
|
-
.add(floatingToolbarPlugin)
|
|
111
|
-
.add([mediaPlugin, { allowMediaSingle: true }]);
|
|
112
|
-
|
|
113
|
-
const editor = (doc: DocBuilder) =>
|
|
114
|
-
createEditor<TablePluginState, PluginKey>({
|
|
115
|
-
doc,
|
|
116
|
-
preset,
|
|
117
|
-
pluginKey,
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
let editorView: EditorView;
|
|
121
|
-
|
|
122
|
-
describe('Tab keypress', () => {
|
|
123
|
-
describe('when the whole row is selected', () => {
|
|
124
|
-
it('should select the first cell of the next row', () => {
|
|
125
|
-
const { editorView, refs } = editor(
|
|
126
|
-
doc(
|
|
127
|
-
table()(tr(tdCursor, tdEmpty), tr(td({})(p('{nextPos}')), tdEmpty)),
|
|
128
|
-
),
|
|
129
|
-
);
|
|
130
|
-
const { nextPos } = refs;
|
|
131
|
-
editorView.dispatch(selectRow(0)(editorView.state.tr));
|
|
132
|
-
sendKeyToPm(editorView, 'Tab');
|
|
133
|
-
expect(editorView.state.selection.$from.pos).toEqual(nextPos);
|
|
134
|
-
expect(editorView.state.selection.empty).toEqual(true);
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
describe('when the whole column is selected', () => {
|
|
139
|
-
it('should select the last cell of the next column', () => {
|
|
140
|
-
const { editorView, refs } = editor(
|
|
141
|
-
doc(
|
|
142
|
-
table()(tr(tdCursor, tdEmpty), tr(tdEmpty, td({})(p('{nextPos}')))),
|
|
143
|
-
),
|
|
144
|
-
);
|
|
145
|
-
const { nextPos } = refs;
|
|
146
|
-
|
|
147
|
-
editorView.dispatch(selectColumn(0)(editorView.state.tr));
|
|
148
|
-
sendKeyToPm(editorView, 'Tab');
|
|
149
|
-
expect(editorView.state.selection.$from.pos).toEqual(nextPos);
|
|
150
|
-
expect(editorView.state.selection.empty).toEqual(true);
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
describe('when the cursor is at the first cell of the first row', () => {
|
|
155
|
-
it('should select next cell of the current row', () => {
|
|
156
|
-
const { editorView, refs } = editor(
|
|
157
|
-
doc(table()(tr(tdCursor, td({})(p('{nextPos}')), tdEmpty))),
|
|
158
|
-
);
|
|
159
|
-
const { nextPos } = refs;
|
|
160
|
-
sendKeyToPm(editorView, 'Tab');
|
|
161
|
-
expect(editorView.state.selection.$from.pos).toEqual(nextPos);
|
|
162
|
-
expect(editorView.state.selection.empty).toEqual(true);
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
describe('when the cursor is at the last cell of the first row', () => {
|
|
167
|
-
it('should select first cell of the next row', () => {
|
|
168
|
-
const { editorView, refs } = editor(
|
|
169
|
-
doc(
|
|
170
|
-
table()(
|
|
171
|
-
tr(tdEmpty, tdEmpty, tdCursor),
|
|
172
|
-
tr(td({})(p('{nextPos}')), tdEmpty, tdEmpty),
|
|
173
|
-
),
|
|
174
|
-
),
|
|
175
|
-
);
|
|
176
|
-
const { nextPos } = refs;
|
|
177
|
-
sendKeyToPm(editorView, 'Tab');
|
|
178
|
-
expect(editorView.state.selection.$from.pos).toEqual(nextPos);
|
|
179
|
-
expect(editorView.state.selection.empty).toEqual(true);
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
describe('when the cursor is at the last cell of the last row', () => {
|
|
184
|
-
it('should create a new row and select the first cell of the new row', () => {
|
|
185
|
-
const { editorView } = editor(
|
|
186
|
-
doc(
|
|
187
|
-
table()(
|
|
188
|
-
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
189
|
-
tr(tdEmpty, tdEmpty, tdCursor),
|
|
190
|
-
),
|
|
191
|
-
),
|
|
192
|
-
);
|
|
193
|
-
sendKeyToPm(editorView, 'Tab');
|
|
194
|
-
const tableNode = findTable(editorView.state.selection)!;
|
|
195
|
-
const map = TableMap.get(tableNode.node);
|
|
196
|
-
expect(map.height).toEqual(3);
|
|
197
|
-
expect(editorView.state.selection.$from.pos).toEqual(32);
|
|
198
|
-
expect(editorView.state.selection.empty).toEqual(true);
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
describe('Shift-Tab keypress', () => {
|
|
204
|
-
describe('when the cursor is at the last cell of the first row', () => {
|
|
205
|
-
it('should select previous cell of the current row', () => {
|
|
206
|
-
const { editorView, refs } = editor(
|
|
207
|
-
doc(table()(tr(tdEmpty, td({})(p('{nextPos}')), tdCursor))),
|
|
208
|
-
);
|
|
209
|
-
const { nextPos } = refs;
|
|
210
|
-
sendKeyToPm(editorView, 'Shift-Tab');
|
|
211
|
-
expect(editorView.state.selection.$from.pos).toEqual(nextPos);
|
|
212
|
-
expect(editorView.state.selection.empty).toEqual(true);
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
describe('when the cursor is at the first cell of the second row', () => {
|
|
217
|
-
it('should select the last cell of the first row', () => {
|
|
218
|
-
const { editorView, refs } = editor(
|
|
219
|
-
doc(
|
|
220
|
-
table()(
|
|
221
|
-
tr(tdEmpty, tdEmpty, td({})(p('{nextPos}'))),
|
|
222
|
-
tr(tdCursor, tdEmpty, tdEmpty),
|
|
223
|
-
),
|
|
224
|
-
),
|
|
225
|
-
);
|
|
226
|
-
const { nextPos } = refs;
|
|
227
|
-
sendKeyToPm(editorView, 'Shift-Tab');
|
|
228
|
-
expect(editorView.state.selection.$from.pos).toEqual(nextPos);
|
|
229
|
-
expect(editorView.state.selection.empty).toEqual(true);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
describe('when the cursor is at the first cell of the first row', () => {
|
|
234
|
-
it('should create a new row and select the first cell of the new row', () => {
|
|
235
|
-
const { editorView } = editor(
|
|
236
|
-
doc(
|
|
237
|
-
table()(
|
|
238
|
-
tr(tdCursor, tdEmpty, tdEmpty),
|
|
239
|
-
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
240
|
-
),
|
|
241
|
-
),
|
|
242
|
-
);
|
|
243
|
-
sendKeyToPm(editorView, 'Shift-Tab');
|
|
244
|
-
const tableNode = findTable(editorView.state.selection)!;
|
|
245
|
-
const map = TableMap.get(tableNode.node);
|
|
246
|
-
expect(map.height).toEqual(3);
|
|
247
|
-
expect(editorView.state.selection.$from.pos).toEqual(4);
|
|
248
|
-
expect(editorView.state.selection.empty).toEqual(true);
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
describe('Backspace keypress', () => {
|
|
254
|
-
describe('when cursor is immediately after the table', () => {
|
|
255
|
-
it('should move cursor to the last cell', () => {
|
|
256
|
-
const { editorView, refs } = editor(
|
|
257
|
-
doc(
|
|
258
|
-
p('text'),
|
|
259
|
-
table()(tr(tdEmpty, td({})(p('hello{nextPos}')))),
|
|
260
|
-
p('{<>}text'),
|
|
261
|
-
),
|
|
262
|
-
);
|
|
263
|
-
const { nextPos } = refs;
|
|
264
|
-
|
|
265
|
-
sendKeyToPm(editorView, 'Backspace');
|
|
266
|
-
expect(editorView.state.selection.$from.pos).toEqual(nextPos);
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
const backspace = (view: EditorView) => {
|
|
270
|
-
const {
|
|
271
|
-
state: {
|
|
272
|
-
tr,
|
|
273
|
-
selection: { $head },
|
|
274
|
-
},
|
|
275
|
-
} = view;
|
|
276
|
-
view.dispatch(tr.delete($head.pos - 1, $head.pos));
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
const excludeNodes = ['doc', 'table', 'bodiedExtension'];
|
|
280
|
-
|
|
281
|
-
Object.keys(defaultSchema.nodes).forEach((nodeName) => {
|
|
282
|
-
const node = defaultSchema.nodes[nodeName];
|
|
283
|
-
if (
|
|
284
|
-
node.spec.group !== 'block' ||
|
|
285
|
-
excludeNodes.indexOf(nodeName) > -1
|
|
286
|
-
) {
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
if (!(pmNodeBuilder as Record<string, any>)[nodeName]) {
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
it(`should remove a ${nodeName}, and place the cursor into the last cell`, () => {
|
|
295
|
-
const { editorView, refs } = editor(
|
|
296
|
-
doc(
|
|
297
|
-
table()(tr(tdEmpty, td({})(p('hello{nextPos}')))),
|
|
298
|
-
(pmNodeBuilder as Record<string, any>)[nodeName],
|
|
299
|
-
),
|
|
300
|
-
);
|
|
301
|
-
const { nextPos } = refs;
|
|
302
|
-
const { state } = editorView;
|
|
303
|
-
|
|
304
|
-
// work backwards from document end to find out where to put the cursor
|
|
305
|
-
let last = state.doc.lastChild;
|
|
306
|
-
|
|
307
|
-
while (last && !last.isTextblock) {
|
|
308
|
-
last = last.lastChild;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
let backspaceAmount = 0;
|
|
312
|
-
if (last) {
|
|
313
|
-
// also delete any existing placeholder content that pmNodeBuilder gave us
|
|
314
|
-
backspaceAmount += last.content.size;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// lists need an an extra backspace before cursor moves to table, since we need to
|
|
318
|
-
// outdent the first item, first.
|
|
319
|
-
if (nodeName.endsWith('List')) {
|
|
320
|
-
backspaceAmount++;
|
|
321
|
-
}
|
|
322
|
-
for (let i = 0; i < backspaceAmount; i++) {
|
|
323
|
-
sendKeyToPm(editorView, 'Backspace');
|
|
324
|
-
backspace(editorView);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
sendKeyToPm(editorView, 'Backspace');
|
|
328
|
-
expect(editorView.state.selection.$from.pos).toEqual(nextPos);
|
|
329
|
-
});
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
describe('when whole table is selected', () => {
|
|
334
|
-
it('should delete table node', () => {
|
|
335
|
-
const { editorView } = editor(
|
|
336
|
-
doc(
|
|
337
|
-
table()(
|
|
338
|
-
tr(td()(p('{<cell}1')), td()(p('2')), td()(p('3'))),
|
|
339
|
-
tr(td()(p('1')), td()(p('2')), td()(p('3{cell>}'))),
|
|
340
|
-
),
|
|
341
|
-
p(''),
|
|
342
|
-
),
|
|
343
|
-
);
|
|
344
|
-
|
|
345
|
-
sendKeyToPm(editorView, 'Backspace');
|
|
346
|
-
expect(editorView.state).toEqualDocumentAndSelection(doc(p('{<>}')));
|
|
347
|
-
});
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
[0, 1, 2].forEach((index) => {
|
|
351
|
-
describe(`when row ${index + 1} is selected`, () => {
|
|
352
|
-
it(`should empty cells in the row ${
|
|
353
|
-
index + 1
|
|
354
|
-
} and move cursor to the first selected cell`, () => {
|
|
355
|
-
const { editorView } = editor(
|
|
356
|
-
doc(
|
|
357
|
-
table()(
|
|
358
|
-
tr(tdEmpty, td({})(p('{<>}1'))),
|
|
359
|
-
tr(tdEmpty, td({})(p('2'))),
|
|
360
|
-
tr(tdEmpty, td({})(p('3'))),
|
|
361
|
-
),
|
|
362
|
-
),
|
|
363
|
-
);
|
|
364
|
-
|
|
365
|
-
editorView.dispatch(selectRow(index)(editorView.state.tr));
|
|
366
|
-
expect(editorView.state.selection instanceof CellSelection).toEqual(
|
|
367
|
-
true,
|
|
368
|
-
);
|
|
369
|
-
const { selection } = editorView.state;
|
|
370
|
-
const { start } = findTable(selection)!;
|
|
371
|
-
const cursorPos =
|
|
372
|
-
selection.$head.pos - selection.$head.parentOffset + start!;
|
|
373
|
-
sendKeyToPm(editorView, 'Backspace');
|
|
374
|
-
const rows: any = [];
|
|
375
|
-
for (let i = 0; i < 3; i++) {
|
|
376
|
-
rows.push(tr(tdEmpty, td({})(p(i === index ? '' : `${i + 1}`))));
|
|
377
|
-
}
|
|
378
|
-
expect(editorView.state.doc).toEqualDocument(
|
|
379
|
-
doc(table({ localId: TABLE_LOCAL_ID })(...rows)),
|
|
380
|
-
);
|
|
381
|
-
expect(cursorPos).toEqual(editorView.state.selection.$from.pos);
|
|
382
|
-
expect(editorView.state.selection.$from.pos).toEqual(
|
|
383
|
-
[4, 15, 26][index],
|
|
384
|
-
);
|
|
385
|
-
});
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
describe(`when column ${index + 1} is selected`, () => {
|
|
389
|
-
it(`should empty cells in the column ${
|
|
390
|
-
index + 1
|
|
391
|
-
} and move cursor to the last selected cell`, () => {
|
|
392
|
-
const emptyRow = tr(tdEmpty, tdEmpty, tdEmpty);
|
|
393
|
-
const { editorView } = editor(
|
|
394
|
-
doc(
|
|
395
|
-
table()(
|
|
396
|
-
emptyRow,
|
|
397
|
-
tr(td({})(p('{<>}1')), td({})(p('2')), td({})(p('3'))),
|
|
398
|
-
),
|
|
399
|
-
),
|
|
400
|
-
);
|
|
401
|
-
|
|
402
|
-
editorView.dispatch(selectColumn(index)(editorView.state.tr));
|
|
403
|
-
expect(editorView.state.selection instanceof CellSelection).toEqual(
|
|
404
|
-
true,
|
|
405
|
-
);
|
|
406
|
-
const { selection } = editorView.state;
|
|
407
|
-
const { start } = findTable(selection)!;
|
|
408
|
-
const cursorPos =
|
|
409
|
-
selection.$head.pos - selection.$head.parentOffset + start;
|
|
410
|
-
sendKeyToPm(editorView, 'Backspace');
|
|
411
|
-
const columns: any = [];
|
|
412
|
-
for (let i = 0; i < 3; i++) {
|
|
413
|
-
columns.push(td({})(p(i === index ? '' : `${i + 1}`)));
|
|
414
|
-
}
|
|
415
|
-
expect(editorView.state.doc).toEqualDocument(
|
|
416
|
-
doc(table({ localId: TABLE_LOCAL_ID })(emptyRow, tr(...columns))),
|
|
417
|
-
);
|
|
418
|
-
expect(cursorPos).toEqual(editorView.state.selection.$from.pos);
|
|
419
|
-
expect(editorView.state.selection.$from.pos).toEqual(
|
|
420
|
-
[4, 8, 12][index],
|
|
421
|
-
);
|
|
422
|
-
});
|
|
423
|
-
});
|
|
424
|
-
});
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
describe('Cmd-A keypress', () => {
|
|
428
|
-
describe('when a table cell is selected', () => {
|
|
429
|
-
it('should select whole editor', () => {
|
|
430
|
-
const { editorView } = editor(
|
|
431
|
-
doc(
|
|
432
|
-
p('testing'),
|
|
433
|
-
table()(tr(tdCursor, tdEmpty), tr(tdEmpty, tdEmpty)),
|
|
434
|
-
p('testing'),
|
|
435
|
-
),
|
|
436
|
-
);
|
|
437
|
-
sendKeyToPm(editorView, 'Mod-a');
|
|
438
|
-
expect(editorView.state.selection.$from.pos).toEqual(0);
|
|
439
|
-
expect(editorView.state.selection.$to.pos).toEqual(
|
|
440
|
-
editorView.state.doc.content.size,
|
|
441
|
-
);
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
describe('when a table row is selected', () => {
|
|
446
|
-
it('should select whole editor', () => {
|
|
447
|
-
const { editorView } = editor(
|
|
448
|
-
doc(
|
|
449
|
-
p('testing'),
|
|
450
|
-
table()(tr(td()(p('{<}testing{>}'))), tr(tdEmpty)),
|
|
451
|
-
p('testing'),
|
|
452
|
-
),
|
|
453
|
-
);
|
|
454
|
-
sendKeyToPm(editorView, 'Mod-a');
|
|
455
|
-
expect(editorView.state.selection.$from.pos).toEqual(0);
|
|
456
|
-
expect(editorView.state.selection.$to.pos).toEqual(
|
|
457
|
-
editorView.state.doc.content.size,
|
|
458
|
-
);
|
|
459
|
-
});
|
|
460
|
-
});
|
|
461
|
-
});
|
|
462
|
-
|
|
463
|
-
describe('Ctrl-Alt-Arrows', () => {
|
|
464
|
-
it('should add row before any table row', () => {
|
|
465
|
-
const { editorView } = editor(
|
|
466
|
-
doc(table()(tr(tdCursor, td()(p('text'))))),
|
|
467
|
-
);
|
|
468
|
-
|
|
469
|
-
sendKeyToPm(editorView, 'Ctrl-Alt-ArrowUp');
|
|
470
|
-
|
|
471
|
-
expect(editorView.state.doc).toEqualDocument(
|
|
472
|
-
doc(
|
|
473
|
-
table({ localId: TABLE_LOCAL_ID })(
|
|
474
|
-
tr(tdEmpty, tdEmpty),
|
|
475
|
-
tr(tdCursor, td()(p('text'))),
|
|
476
|
-
),
|
|
477
|
-
),
|
|
478
|
-
);
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
it('should not add row before when cursor in table header', () => {
|
|
482
|
-
const { editorView } = editor(doc(table()(tr(thCursor, thEmpty))));
|
|
483
|
-
|
|
484
|
-
sendKeyToPm(editorView, 'Ctrl-Alt-ArrowUp');
|
|
485
|
-
|
|
486
|
-
expect(editorView.state.doc).toEqualDocument(
|
|
487
|
-
doc(table({ localId: TABLE_LOCAL_ID })(tr(thCursor, thEmpty))),
|
|
488
|
-
);
|
|
489
|
-
});
|
|
490
|
-
|
|
491
|
-
it('should not add row before when selected table header', () => {
|
|
492
|
-
const { editorView } = editor(doc(table()(tr(thEmpty, thEmpty))));
|
|
493
|
-
|
|
494
|
-
editorView.dispatch(selectRow(0)(editorView.state.tr));
|
|
495
|
-
sendKeyToPm(editorView, 'Ctrl-Alt-ArrowUp');
|
|
496
|
-
|
|
497
|
-
expect(editorView.state.doc).toEqualDocument(
|
|
498
|
-
doc(table({ localId: TABLE_LOCAL_ID })(tr(thEmpty, thEmpty))),
|
|
499
|
-
);
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
it('should add row after any table row', () => {
|
|
503
|
-
const { editorView } = editor(doc(table()(tr(tdCursor, tdEmpty))));
|
|
504
|
-
|
|
505
|
-
sendKeyToPm(editorView, 'Ctrl-Alt-ArrowDown');
|
|
506
|
-
|
|
507
|
-
expect(editorView.state.doc).toEqualDocument(
|
|
508
|
-
doc(
|
|
509
|
-
table({ localId: TABLE_LOCAL_ID })(
|
|
510
|
-
tr(tdCursor, tdEmpty),
|
|
511
|
-
tr(tdEmpty, tdEmpty),
|
|
512
|
-
),
|
|
513
|
-
),
|
|
514
|
-
);
|
|
515
|
-
});
|
|
516
|
-
|
|
517
|
-
it('should add row after table header', () => {
|
|
518
|
-
const { editorView } = editor(doc(table()(tr(thCursor, thEmpty))));
|
|
519
|
-
|
|
520
|
-
sendKeyToPm(editorView, 'Ctrl-Alt-ArrowDown');
|
|
521
|
-
|
|
522
|
-
expect(editorView.state.doc).toEqualDocument(
|
|
523
|
-
doc(
|
|
524
|
-
table({ localId: TABLE_LOCAL_ID })(
|
|
525
|
-
tr(thCursor, thEmpty),
|
|
526
|
-
tr(tdEmpty, tdEmpty),
|
|
527
|
-
),
|
|
528
|
-
),
|
|
529
|
-
);
|
|
530
|
-
});
|
|
531
|
-
|
|
532
|
-
it('should add column before any table column', () => {
|
|
533
|
-
const { editorView } = editor(doc(table()(tr(tdCursor, tdEmpty))));
|
|
534
|
-
|
|
535
|
-
sendKeyToPm(editorView, 'Ctrl-Alt-ArrowLeft');
|
|
536
|
-
|
|
537
|
-
expect(editorView.state.doc).toEqualDocument(
|
|
538
|
-
doc(table({ localId: TABLE_LOCAL_ID })(tr(tdEmpty, tdCursor, tdEmpty))),
|
|
539
|
-
);
|
|
540
|
-
});
|
|
541
|
-
|
|
542
|
-
it('should not add column before when cursor in table header', () => {
|
|
543
|
-
const { editorView } = editor(doc(table()(tr(thCursor, thEmpty))));
|
|
544
|
-
|
|
545
|
-
sendKeyToPm(editorView, 'Ctrl-Alt-ArrowLeft');
|
|
546
|
-
|
|
547
|
-
expect(editorView.state.doc).toEqualDocument(
|
|
548
|
-
doc(table({ localId: TABLE_LOCAL_ID })(tr(thCursor, thEmpty))),
|
|
549
|
-
);
|
|
550
|
-
});
|
|
551
|
-
|
|
552
|
-
it('should not add column before when selected table header', () => {
|
|
553
|
-
const { editorView } = editor(doc(table()(tr(thEmpty, thEmpty))));
|
|
554
|
-
|
|
555
|
-
editorView.dispatch(selectRow(0)(editorView.state.tr));
|
|
556
|
-
sendKeyToPm(editorView, 'Ctrl-Alt-ArrowLeft');
|
|
557
|
-
|
|
558
|
-
expect(editorView.state.doc).toEqualDocument(
|
|
559
|
-
doc(table({ localId: TABLE_LOCAL_ID })(tr(thEmpty, thEmpty))),
|
|
560
|
-
);
|
|
561
|
-
});
|
|
562
|
-
|
|
563
|
-
it('should add column after any table column', () => {
|
|
564
|
-
const { editorView } = editor(doc(table()(tr(tdCursor, tdEmpty))));
|
|
565
|
-
|
|
566
|
-
sendKeyToPm(editorView, 'Ctrl-Alt-ArrowRight');
|
|
567
|
-
|
|
568
|
-
expect(editorView.state.doc).toEqualDocument(
|
|
569
|
-
doc(table({ localId: TABLE_LOCAL_ID })(tr(tdCursor, tdEmpty, tdEmpty))),
|
|
570
|
-
);
|
|
571
|
-
});
|
|
572
|
-
|
|
573
|
-
it('should add column after table header', () => {
|
|
574
|
-
const { editorView } = editor(doc(table()(tr(thCursor, thEmpty))));
|
|
575
|
-
|
|
576
|
-
sendKeyToPm(editorView, 'Ctrl-Alt-ArrowRight');
|
|
577
|
-
|
|
578
|
-
expect(editorView.state.doc).toEqualDocument(
|
|
579
|
-
doc(table({ localId: TABLE_LOCAL_ID })(tr(thCursor, thEmpty, thEmpty))),
|
|
580
|
-
);
|
|
581
|
-
});
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
describe('Shift-Alt-T keypress', () => {
|
|
585
|
-
beforeEach(() => {
|
|
586
|
-
({ editorView } = editor(doc(p())));
|
|
587
|
-
sendKeyToPm(editorView, 'Shift-Alt-T');
|
|
588
|
-
});
|
|
589
|
-
|
|
590
|
-
it('should insert 3x3 table', () => {
|
|
591
|
-
const tableNode = table({ localId: TABLE_LOCAL_ID })(
|
|
592
|
-
tr(thEmpty, thEmpty, thEmpty),
|
|
593
|
-
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
594
|
-
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
595
|
-
);
|
|
596
|
-
expect(editorView.state.doc).toEqualDocument(doc(tableNode));
|
|
597
|
-
});
|
|
598
|
-
|
|
599
|
-
it('should dispatch analytics event', () => {
|
|
600
|
-
expect(mockAttachPayload).toBeCalledWith({
|
|
601
|
-
action: 'inserted',
|
|
602
|
-
actionSubject: 'document',
|
|
603
|
-
actionSubjectId: 'table',
|
|
604
|
-
attributes: expect.objectContaining({ inputMethod: 'shortcut' }),
|
|
605
|
-
eventType: 'track',
|
|
606
|
-
});
|
|
607
|
-
});
|
|
608
|
-
});
|
|
609
|
-
});
|