quill-table-up 3.1.2 → 3.2.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 (111) hide show
  1. package/README.md +15 -8
  2. package/dist/index.css +1 -1
  3. package/dist/index.d.ts +168 -146
  4. package/dist/index.js +47 -47
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.umd.js +52 -52
  7. package/dist/index.umd.js.map +1 -1
  8. package/package.json +22 -24
  9. package/src/__tests__/e2e/custom-creator.test.ts +44 -44
  10. package/src/__tests__/e2e/editor-page.ts +77 -77
  11. package/src/__tests__/e2e/table-align.test.ts +104 -104
  12. package/src/__tests__/e2e/table-blots.test.ts +169 -169
  13. package/src/__tests__/e2e/table-caption.test.ts +134 -134
  14. package/src/__tests__/e2e/table-clipboard.test.ts +20 -20
  15. package/src/__tests__/e2e/table-hack.test.ts +151 -151
  16. package/src/__tests__/e2e/table-keyboard-handler.test.ts +20 -4
  17. package/src/__tests__/e2e/table-menu.test.ts +172 -172
  18. package/src/__tests__/e2e/table-resize.test.ts +654 -9
  19. package/src/__tests__/e2e/table-scrollbar.test.ts +144 -144
  20. package/src/__tests__/e2e/table-selection.test.ts +563 -563
  21. package/src/__tests__/e2e/types.d.ts +8 -7
  22. package/src/__tests__/e2e/utils.ts +52 -52
  23. package/src/__tests__/unit/table-blots.test.ts +720 -720
  24. package/src/__tests__/unit/table-caption.test.ts +234 -234
  25. package/src/__tests__/unit/table-cell-merge.test.ts +713 -724
  26. package/src/__tests__/unit/table-clipboard.test.ts +2176 -2176
  27. package/src/__tests__/unit/table-hack.test.ts +1014 -1014
  28. package/src/__tests__/unit/table-insert.test.ts +915 -926
  29. package/src/__tests__/unit/table-redo-undo.test.ts +2429 -2429
  30. package/src/__tests__/unit/table-remove.test.ts +313 -343
  31. package/src/__tests__/unit/utils.test-d.ts +49 -49
  32. package/src/__tests__/unit/utils.test.ts +711 -711
  33. package/src/__tests__/unit/utils.ts +307 -307
  34. package/src/__tests__/unit/vitest.d.ts +14 -14
  35. package/src/formats/container-format.ts +107 -107
  36. package/src/formats/overrides/block-embed.ts +72 -72
  37. package/src/formats/overrides/block.ts +95 -95
  38. package/src/formats/overrides/index.ts +3 -3
  39. package/src/formats/overrides/scroll.ts +70 -70
  40. package/src/formats/table-body-format.ts +52 -52
  41. package/src/formats/table-caption-format.ts +116 -116
  42. package/src/formats/table-cell-format.ts +304 -304
  43. package/src/formats/table-cell-inner-format.ts +403 -398
  44. package/src/formats/table-colgroup-format.ts +136 -136
  45. package/src/formats/table-foot-format.ts +7 -7
  46. package/src/formats/table-head-format.ts +7 -7
  47. package/src/formats/table-main-format.ts +1 -1
  48. package/src/formats/table-row-format.ts +218 -210
  49. package/src/formats/utils.ts +6 -6
  50. package/src/index.ts +19 -19
  51. package/src/modules/index.ts +7 -7
  52. package/src/modules/table-align.ts +131 -131
  53. package/src/modules/table-clipboard/table-clipboard.ts +6 -8
  54. package/src/modules/table-dom-selector.ts +33 -33
  55. package/src/modules/table-menu/constants.ts +223 -223
  56. package/src/modules/table-menu/index.ts +4 -4
  57. package/src/modules/table-menu/table-menu-common.ts +330 -329
  58. package/src/modules/table-menu/table-menu-contextmenu.ts +111 -118
  59. package/src/modules/table-menu/table-menu-select.ts +96 -94
  60. package/src/modules/table-resize/index.ts +5 -5
  61. package/src/modules/table-resize/table-resize-box.ts +714 -363
  62. package/src/modules/table-resize/table-resize-common.ts +246 -382
  63. package/src/modules/table-resize/table-resize-drag.ts +241 -0
  64. package/src/modules/table-resize/table-resize-line.ts +244 -182
  65. package/src/modules/table-resize/table-resize-scale.ts +174 -173
  66. package/src/modules/table-resize/utils.ts +84 -3
  67. package/src/modules/table-scrollbar.ts +292 -292
  68. package/src/modules/table-selection.ts +613 -669
  69. package/src/style/button.less +45 -45
  70. package/src/style/color-picker.less +136 -136
  71. package/src/style/dialog.less +53 -53
  72. package/src/style/functions.less +9 -9
  73. package/src/style/index.less +120 -120
  74. package/src/style/input.less +64 -64
  75. package/src/style/select-box.less +52 -52
  76. package/src/style/table-creator.less +56 -56
  77. package/src/style/table-menu.less +125 -125
  78. package/src/style/table-resize-scale.less +31 -31
  79. package/src/style/table-resize.less +249 -202
  80. package/src/style/table-scrollbar.less +49 -49
  81. package/src/style/table-selection.less +23 -23
  82. package/src/style/tooltip.less +19 -19
  83. package/src/style/variables.less +1 -1
  84. package/src/svg/arrow-up-down.svg +11 -11
  85. package/src/svg/convert-cell.svg +7 -7
  86. package/src/table-up.ts +1363 -1360
  87. package/src/types.d.ts +4 -4
  88. package/src/utils/bem.ts +23 -23
  89. package/src/utils/blot-helper.ts +101 -105
  90. package/src/utils/color.ts +109 -109
  91. package/src/utils/components/button.ts +22 -22
  92. package/src/utils/components/color-picker.ts +236 -236
  93. package/src/utils/components/dialog.ts +83 -41
  94. package/src/utils/components/index.ts +6 -6
  95. package/src/utils/components/input.ts +74 -74
  96. package/src/utils/components/table/creator.ts +89 -89
  97. package/src/utils/components/table/index.ts +2 -2
  98. package/src/utils/components/table/select-box.ts +78 -78
  99. package/src/utils/components/tooltip.ts +179 -189
  100. package/src/utils/constants.ts +125 -124
  101. package/src/utils/drag-helper.ts +112 -0
  102. package/src/utils/index.ts +15 -14
  103. package/src/utils/is.ts +9 -9
  104. package/src/utils/position.ts +60 -60
  105. package/src/utils/resize-observer-helper.ts +47 -47
  106. package/src/utils/scroll.ts +145 -47
  107. package/src/utils/style-helper.ts +47 -47
  108. package/src/utils/transformer.ts +10 -10
  109. package/src/utils/transition-event-helper.ts +8 -8
  110. package/src/utils/types.ts +156 -157
  111. package/src/utils/utils.ts +12 -12
@@ -1,711 +1,711 @@
1
- import Quill from 'quill';
2
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
- import { TableBodyFormat, TableCellFormat, TableCellInnerFormat, TableColFormat, TableMainFormat, TableRowFormat, TableWrapperFormat } from '../../formats';
4
- import { TableUp, updateTableConstants } from '../../table-up';
5
- import { blotName, findParentBlot, findParentBlots } from '../../utils';
6
- import { createTable, createTableHTML, createTaleColHTML, datasetFull, getColWidthStyle, normalizeHTML } from './utils';
7
-
8
- beforeEach(() => {
9
- vi.useFakeTimers();
10
- });
11
- afterEach(() => {
12
- vi.useRealTimers();
13
- });
14
-
15
- function createOverridesTable(html: string, options = true, moduleOptions = {}, register = {}) {
16
- updateTableConstants({
17
- blotName: {
18
- tableCol: 'a-col',
19
- tableCell: 'a-cell',
20
- tableCellInner: 'a-cell-inner',
21
- },
22
- });
23
-
24
- // rename `colId` to `column`
25
- class TableColFormatOverride extends TableColFormat {
26
- static create(value: any) {
27
- const { colId, column } = value;
28
- const node = super.create(value);
29
- node.dataset.colId = column || colId;
30
- node.setAttribute('contenteditable', 'false');
31
- return node;
32
- }
33
-
34
- static value(domNode: HTMLElement) {
35
- const value = super.value(domNode);
36
- value.column = value.colId;
37
- delete value.colId;
38
- return value;
39
- }
40
- }
41
- // rename `rowId` to `row`, `colId` to `cell`
42
- class TableCellFormatOverride extends TableCellFormat {
43
- static allowDataAttrs = new Set(['table-id', 'row', 'cell']);
44
- static create(value: any) {
45
- const node = super.create(value);
46
- let { rowId, colId, row, cell } = value;
47
- row = row || rowId;
48
- cell = cell || colId;
49
- node.dataset.row = row;
50
- node.dataset.cell = cell;
51
- node.removeAttribute('data-row-id');
52
- node.removeAttribute('data-col-id');
53
- return node;
54
- }
55
-
56
- static formats(domNode: HTMLElement) {
57
- const value = super.formats(domNode);
58
- const { row, cell } = domNode.dataset;
59
- value.row = row;
60
- value.cell = cell;
61
- delete value.rowId;
62
- delete value.colId;
63
- return value;
64
- }
65
-
66
- get rowId() {
67
- return this.domNode.dataset.row!;
68
- }
69
-
70
- get colId() {
71
- return this.domNode.dataset.cell!;
72
- }
73
- }
74
- class TableCellInnerFormatOverride extends TableCellInnerFormat {
75
- static allowDataAttrs = new Set(['table-id', 'row', 'cell', 'rowspan', 'colspan']);
76
- static create(value: any) {
77
- const node = super.create(value);
78
- let { rowId, colId, row, cell } = value;
79
- row = row || rowId;
80
- cell = cell || colId;
81
- node.dataset.row = row;
82
- node.dataset.cell = cell;
83
- node.removeAttribute('data-row-id');
84
- node.removeAttribute('data-col-id');
85
- return node;
86
- }
87
-
88
- static formats(domNode: HTMLElement) {
89
- const value = super.formats(domNode);
90
- const { row, cell } = domNode.dataset;
91
- value.row = row;
92
- value.cell = cell;
93
- delete value.rowId;
94
- delete value.colId;
95
- return value;
96
- }
97
-
98
- get rowId() {
99
- return this.domNode.dataset.row!;
100
- }
101
-
102
- set rowId(value) {
103
- this.setFormatValue('row', value);
104
- }
105
-
106
- get colId() {
107
- return this.domNode.dataset.cell!;
108
- }
109
-
110
- set colId(value) {
111
- this.setFormatValue('cell', value);
112
- }
113
- }
114
- class TableUpOverride extends TableUp {
115
- static register(): void {
116
- super.register();
117
- Quill.register({
118
- 'formats/a-col': TableColFormatOverride,
119
- 'formats/a-cell': TableCellFormatOverride,
120
- 'formats/a-cell-inner': TableCellInnerFormatOverride,
121
- }, true);
122
- }
123
- }
124
- Quill.register({
125
- 'modules/tableUpOverride': TableUpOverride,
126
- ...register,
127
- }, true);
128
- const container = document.body.appendChild(document.createElement('div'));
129
- container.innerHTML = normalizeHTML(html);
130
- const quill = new Quill(container, {
131
- modules: {
132
- tableUpOverride: options,
133
- history: {
134
- delay: 0,
135
- },
136
- ...moduleOptions,
137
- },
138
- });
139
- return quill;
140
- }
141
-
142
- describe('test utils', () => {
143
- it('test findParentBlot', async () => {
144
- const quill = await createTable(1, 1);
145
- const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
146
- const tableCellBlot = findParentBlot(tds[0], blotName.tableCell);
147
- expect(tableCellBlot).toBeInstanceOf(TableCellFormat);
148
- const tableRowBlot = findParentBlot(tds[0], blotName.tableRow);
149
- expect(tableRowBlot).toBeInstanceOf(TableRowFormat);
150
- const tableBodyBlot = findParentBlot(tds[0], blotName.tableBody);
151
- expect(tableBodyBlot).toBeInstanceOf(TableBodyFormat);
152
- const tableMainBlot = findParentBlot(tds[0], blotName.tableMain);
153
- expect(tableMainBlot).toBeInstanceOf(TableMainFormat);
154
- const tableWrapperBlot = findParentBlot(tds[0], blotName.tableWrapper);
155
- expect(tableWrapperBlot).toBeInstanceOf(TableWrapperFormat);
156
- expect(() => findParentBlot(tds[0], 'scroll')).toThrowError(`${blotName.tableCellInner} must be a child of scroll`);
157
- });
158
-
159
- it('test findParentBlots', async () => {
160
- const quill = await createTable(1, 1);
161
- const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
162
- const [tableCellBlot, tableRowBlot, tableBodyBlot, tableMainBlot, tableWrapperBlot] = findParentBlots(
163
- tds[0],
164
- [
165
- blotName.tableCell,
166
- blotName.tableRow,
167
- blotName.tableBody,
168
- blotName.tableMain,
169
- blotName.tableWrapper,
170
- ] as const,
171
- );
172
- expect(tableCellBlot).toBeInstanceOf(TableCellFormat);
173
- expect(tableRowBlot).toBeInstanceOf(TableRowFormat);
174
- expect(tableBodyBlot).toBeInstanceOf(TableBodyFormat);
175
- expect(tableMainBlot).toBeInstanceOf(TableMainFormat);
176
- expect(tableWrapperBlot).toBeInstanceOf(TableWrapperFormat);
177
- });
178
- });
179
-
180
- // this test need be last. it's effect `blotName`
181
- describe('test override format', () => {
182
- it('should change blotName', async () => {
183
- updateTableConstants({
184
- blotName: {
185
- tableCol: 'a-col',
186
- tableCellInner: 'a-cell-inner',
187
- },
188
- });
189
- const quill = await createTable(2, 2);
190
- expect(quill.getContents()).toMatchObject({
191
- ops: [
192
- {
193
- insert: '\n',
194
- },
195
- {
196
- insert: {
197
- 'a-col': {
198
- tableId: '1',
199
- colId: '1',
200
- full: true,
201
- width: 50,
202
- },
203
- },
204
- },
205
- {
206
- insert: {
207
- 'a-col': {
208
- tableId: '1',
209
- colId: '2',
210
- full: true,
211
- width: 50,
212
- },
213
- },
214
- },
215
- {
216
- insert: '1',
217
- },
218
- {
219
- attributes: {
220
- 'a-cell-inner': {
221
- tableId: '1',
222
- colId: '1',
223
- rowId: '1',
224
- rowspan: 1,
225
- colspan: 1,
226
- },
227
- },
228
- insert: '\n',
229
- },
230
- {
231
- insert: '2',
232
- },
233
- {
234
- attributes: {
235
- 'a-cell-inner': {
236
- tableId: '1',
237
- colId: '2',
238
- rowId: '1',
239
- rowspan: 1,
240
- colspan: 1,
241
- },
242
- },
243
- insert: '\n',
244
- },
245
- {
246
- insert: '3',
247
- },
248
- {
249
- attributes: {
250
- 'a-cell-inner': {
251
- tableId: '1',
252
- colId: '1',
253
- rowId: '2',
254
- rowspan: 1,
255
- colspan: 1,
256
- },
257
- },
258
- insert: '\n',
259
- },
260
- {
261
- insert: '4',
262
- },
263
- {
264
- attributes: {
265
- 'a-cell-inner': {
266
- tableId: '1',
267
- colId: '2',
268
- rowId: '2',
269
- rowspan: 1,
270
- colspan: 1,
271
- },
272
- },
273
- insert: '\n',
274
- },
275
- {
276
- insert: '\n',
277
- },
278
- ],
279
- });
280
- expect(quill.root).toEqualHTML(
281
- `
282
- <p><br></p>
283
- ${createTableHTML(2, 2)}
284
- <p><br></p>
285
- `,
286
- { ignoreAttrs: ['class', 'style', 'data-table-id', 'contenteditable'] },
287
- );
288
- const tableModule = quill.getModule(TableUp.moduleName) as TableUp;
289
- const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
290
- tableModule.mergeCells([tds[0], tds[1], tds[2], tds[3]]);
291
- await vi.runAllTimersAsync();
292
- expect(quill.getContents()).toMatchObject({
293
- ops: [
294
- {
295
- insert: '\n',
296
- },
297
- {
298
- insert: {
299
- 'a-col': {
300
- tableId: '1',
301
- colId: '1',
302
- full: true,
303
- width: 100,
304
- },
305
- },
306
- },
307
- {
308
- insert: '1',
309
- },
310
- {
311
- attributes: {
312
- 'a-cell-inner': {
313
- tableId: '1',
314
- colId: '1',
315
- rowId: '1',
316
- rowspan: 1,
317
- colspan: 1,
318
- },
319
- },
320
- insert: '\n',
321
- },
322
- {
323
- insert: '2',
324
- },
325
- {
326
- attributes: {
327
- 'a-cell-inner': {
328
- tableId: '1',
329
- colId: '1',
330
- rowId: '1',
331
- rowspan: 1,
332
- colspan: 1,
333
- },
334
- },
335
- insert: '\n',
336
- },
337
- {
338
- insert: '3',
339
- },
340
- {
341
- attributes: {
342
- 'a-cell-inner': {
343
- tableId: '1',
344
- colId: '1',
345
- rowId: '1',
346
- rowspan: 1,
347
- colspan: 1,
348
- },
349
- },
350
- insert: '\n',
351
- },
352
- {
353
- insert: '4',
354
- },
355
- {
356
- attributes: {
357
- 'a-cell-inner': {
358
- tableId: '1',
359
- colId: '1',
360
- rowId: '1',
361
- rowspan: 1,
362
- colspan: 1,
363
- },
364
- },
365
- insert: '\n',
366
- },
367
- {
368
- insert: '\n',
369
- },
370
- ],
371
- });
372
- expect(quill.root).toEqualHTML(
373
- `
374
- <p><br></p>
375
- <div>
376
- <table cellpadding="0" cellspacing="0" data-full="true">
377
- ${createTaleColHTML(1)}
378
- <tbody>
379
- <tr data-row-id="1">
380
- <td rowspan="1" colspan="1" data-row-id="1" data-col-id="1">
381
- <div data-rowspan="1" data-colspan="1" data-row-id="1" data-col-id="1">
382
- <p>1</p>
383
- <p>2</p>
384
- <p>3</p>
385
- <p>4</p>
386
- </div>
387
- </td>
388
- </tr>
389
- </tbody>
390
- </table>
391
- </div>
392
- <p><br></p>
393
- `,
394
- { ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'contenteditable'] },
395
- );
396
- });
397
-
398
- it('should change format name in delta', async () => {
399
- const quill = createOverridesTable(`<p><br></p>`);
400
- quill.setContents([
401
- { insert: '\n' },
402
- {
403
- insert: {
404
- 'a-col': { tableId: '1', column: '1', full: true, width: 50 },
405
- },
406
- },
407
- {
408
- insert: {
409
- 'a-col': { tableId: '1', column: '2', full: true, width: 50 },
410
- },
411
- },
412
- {
413
- attributes: {
414
- 'a-cell-inner': { tableId: '1', row: '1', cell: '1', rowspan: 1, colspan: 1 },
415
- },
416
- insert: '\n',
417
- },
418
- {
419
- attributes: {
420
- 'a-cell-inner': { tableId: '1', row: '1', cell: '2', rowspan: 1, colspan: 1 },
421
- },
422
- insert: '\n',
423
- },
424
- {
425
- attributes: {
426
- 'a-cell-inner': { tableId: '1', row: '2', cell: '1', rowspan: 1, colspan: 1 },
427
- },
428
- insert: '\n',
429
- },
430
- {
431
- attributes: {
432
- 'a-cell-inner': { tableId: '1', row: '2', cell: '2', rowspan: 1, colspan: 1 },
433
- },
434
- insert: '\n',
435
- },
436
- { insert: '\n' },
437
- ]);
438
- await vi.runAllTimersAsync();
439
- expect(quill.getContents()).toMatchObject({
440
- ops: [
441
- {
442
- insert: '\n',
443
- },
444
- {
445
- insert: {
446
- 'a-col': {
447
- tableId: '1',
448
- column: '1',
449
- full: true,
450
- width: 50,
451
- },
452
- },
453
- },
454
- {
455
- insert: {
456
- 'a-col': {
457
- tableId: '1',
458
- column: '2',
459
- full: true,
460
- width: 50,
461
- },
462
- },
463
- },
464
- {
465
- attributes: {
466
- 'a-cell-inner': {
467
- tableId: '1',
468
- cell: '1',
469
- row: '1',
470
- rowspan: 1,
471
- colspan: 1,
472
- },
473
- },
474
- insert: '\n',
475
- },
476
- {
477
- attributes: {
478
- 'a-cell-inner': {
479
- tableId: '1',
480
- cell: '2',
481
- row: '1',
482
- rowspan: 1,
483
- colspan: 1,
484
- },
485
- },
486
- insert: '\n',
487
- },
488
- {
489
- attributes: {
490
- 'a-cell-inner': {
491
- tableId: '1',
492
- cell: '1',
493
- row: '2',
494
- rowspan: 1,
495
- colspan: 1,
496
- },
497
- },
498
- insert: '\n',
499
- },
500
- {
501
- attributes: {
502
- 'a-cell-inner': {
503
- tableId: '1',
504
- cell: '2',
505
- row: '2',
506
- rowspan: 1,
507
- colspan: 1,
508
- },
509
- },
510
- insert: '\n',
511
- },
512
- {
513
- insert: '\n',
514
- },
515
- ],
516
- });
517
- const colWidth = getColWidthStyle({ full: true, colNum: 2 });
518
- expect(quill.root).toEqualHTML(
519
- `
520
- <p><br></p>
521
- <div>
522
- <table cellpadding="0" cellspacing="0"${datasetFull(true)}>
523
- <colgroup${datasetFull(true)}>
524
- ${new Array(2).fill(0).map((_, i) => `<col ${colWidth} data-col-id="${i + 1}"${datasetFull(true)} />`).join('\n')}
525
- </colgroup>
526
- <tbody>
527
- ${
528
- new Array(2).fill(0).map((_, i) => `
529
- <tr data-row-id="${i + 1}">
530
- ${
531
- new Array(2).fill(0).map((_, j) => `<td rowspan="1" colspan="1" data-row="${i + 1}" data-cell="${j + 1}">
532
- <div data-rowspan="1" data-colspan="1" data-row="${i + 1}" data-cell="${j + 1}">
533
- <p>
534
- <br>
535
- </p>
536
- </div>
537
- </td>`).join('\n')
538
- }
539
- </tr>
540
- `).join('\n')
541
- }
542
- </tbody>
543
- </table>
544
- </div>
545
- <p><br></p>
546
- `,
547
- { ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'contenteditable'] },
548
- );
549
- });
550
-
551
- it('should change format name in delta with contents', async () => {
552
- const quill = createOverridesTable(`<p><br></p>`);
553
- quill.setContents([
554
- { insert: '\n' },
555
- {
556
- insert: {
557
- 'a-col': { tableId: '1', column: '1', full: true, width: 50 },
558
- },
559
- },
560
- {
561
- insert: {
562
- 'a-col': { tableId: '1', column: '2', full: true, width: 50 },
563
- },
564
- },
565
- { insert: '1' },
566
- {
567
- attributes: {
568
- 'a-cell-inner': { tableId: '1', row: '1', cell: '1', rowspan: 1, colspan: 1 },
569
- },
570
- insert: '\n',
571
- },
572
- { insert: '2' },
573
- {
574
- attributes: {
575
- 'a-cell-inner': { tableId: '1', row: '1', cell: '2', rowspan: 1, colspan: 1 },
576
- },
577
- insert: '\n',
578
- },
579
- { insert: '3' },
580
- {
581
- attributes: {
582
- 'a-cell-inner': { tableId: '1', row: '2', cell: '1', rowspan: 1, colspan: 1 },
583
- },
584
- insert: '\n',
585
- },
586
- { insert: '4' },
587
- {
588
- attributes: {
589
- 'a-cell-inner': { tableId: '1', row: '2', cell: '2', rowspan: 1, colspan: 1 },
590
- },
591
- insert: '\n',
592
- },
593
- { insert: '\n' },
594
- ]);
595
- await vi.runAllTimersAsync();
596
- expect(quill.getContents()).toMatchObject({
597
- ops: [
598
- {
599
- insert: '\n',
600
- },
601
- {
602
- insert: {
603
- 'a-col': {
604
- tableId: '1',
605
- column: '1',
606
- full: true,
607
- width: 50,
608
- },
609
- },
610
- },
611
- {
612
- insert: {
613
- 'a-col': {
614
- tableId: '1',
615
- column: '2',
616
- full: true,
617
- width: 50,
618
- },
619
- },
620
- },
621
- { insert: '1' },
622
- {
623
- attributes: {
624
- 'a-cell-inner': {
625
- tableId: '1',
626
- cell: '1',
627
- row: '1',
628
- rowspan: 1,
629
- colspan: 1,
630
- },
631
- },
632
- insert: '\n',
633
- },
634
- { insert: '2' },
635
- {
636
- attributes: {
637
- 'a-cell-inner': {
638
- tableId: '1',
639
- cell: '2',
640
- row: '1',
641
- rowspan: 1,
642
- colspan: 1,
643
- },
644
- },
645
- insert: '\n',
646
- },
647
- { insert: '3' },
648
- {
649
- attributes: {
650
- 'a-cell-inner': {
651
- tableId: '1',
652
- cell: '1',
653
- row: '2',
654
- rowspan: 1,
655
- colspan: 1,
656
- },
657
- },
658
- insert: '\n',
659
- },
660
- { insert: '4' },
661
- {
662
- attributes: {
663
- 'a-cell-inner': {
664
- tableId: '1',
665
- cell: '2',
666
- row: '2',
667
- rowspan: 1,
668
- colspan: 1,
669
- },
670
- },
671
- insert: '\n',
672
- },
673
- {
674
- insert: '\n',
675
- },
676
- ],
677
- });
678
- const colWidth = getColWidthStyle({ full: true, colNum: 2 });
679
- expect(quill.root).toEqualHTML(
680
- `
681
- <p><br></p>
682
- <div>
683
- <table cellpadding="0" cellspacing="0"${datasetFull(true)}>
684
- <colgroup${datasetFull(true)}>
685
- ${new Array(2).fill(0).map((_, i) => `<col ${colWidth} data-col-id="${i + 1}"${datasetFull(true)} />`).join('\n')}
686
- </colgroup>
687
- <tbody>
688
- ${
689
- new Array(2).fill(0).map((_, i) => `
690
- <tr data-row-id="${i + 1}">
691
- ${
692
- new Array(2).fill(0).map((_, j) => `<td rowspan="1" colspan="1" data-row="${i + 1}" data-cell="${j + 1}">
693
- <div data-rowspan="1" data-colspan="1" data-row="${i + 1}" data-cell="${j + 1}">
694
- <p>
695
- ${i * 2 + j + 1}
696
- </p>
697
- </div>
698
- </td>`).join('\n')
699
- }
700
- </tr>
701
- `).join('\n')
702
- }
703
- </tbody>
704
- </table>
705
- </div>
706
- <p><br></p>
707
- `,
708
- { ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'contenteditable'] },
709
- );
710
- });
711
- });
1
+ import Quill from 'quill';
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
+ import { TableBodyFormat, TableCellFormat, TableCellInnerFormat, TableColFormat, TableMainFormat, TableRowFormat, TableWrapperFormat } from '../../formats';
4
+ import { TableUp, updateTableConstants } from '../../table-up';
5
+ import { blotName, findParentBlot, findParentBlots } from '../../utils';
6
+ import { createTable, createTableHTML, createTaleColHTML, datasetFull, getColWidthStyle, normalizeHTML } from './utils';
7
+
8
+ beforeEach(() => {
9
+ vi.useFakeTimers();
10
+ });
11
+ afterEach(() => {
12
+ vi.useRealTimers();
13
+ });
14
+
15
+ function createOverridesTable(html: string, options = true, moduleOptions = {}, register = {}) {
16
+ updateTableConstants({
17
+ blotName: {
18
+ tableCol: 'a-col',
19
+ tableCell: 'a-cell',
20
+ tableCellInner: 'a-cell-inner',
21
+ },
22
+ });
23
+
24
+ // rename `colId` to `column`
25
+ class TableColFormatOverride extends TableColFormat {
26
+ static create(value: any) {
27
+ const { colId, column } = value;
28
+ const node = super.create(value);
29
+ node.dataset.colId = column || colId;
30
+ node.setAttribute('contenteditable', 'false');
31
+ return node;
32
+ }
33
+
34
+ static value(domNode: HTMLElement) {
35
+ const value = super.value(domNode);
36
+ value.column = value.colId;
37
+ delete value.colId;
38
+ return value;
39
+ }
40
+ }
41
+ // rename `rowId` to `row`, `colId` to `cell`
42
+ class TableCellFormatOverride extends TableCellFormat {
43
+ static allowDataAttrs = new Set(['table-id', 'row', 'cell']);
44
+ static create(value: any) {
45
+ const node = super.create(value);
46
+ let { rowId, colId, row, cell } = value;
47
+ row = row || rowId;
48
+ cell = cell || colId;
49
+ node.dataset.row = row;
50
+ node.dataset.cell = cell;
51
+ node.removeAttribute('data-row-id');
52
+ node.removeAttribute('data-col-id');
53
+ return node;
54
+ }
55
+
56
+ static formats(domNode: HTMLElement) {
57
+ const value = super.formats(domNode);
58
+ const { row, cell } = domNode.dataset;
59
+ value.row = row;
60
+ value.cell = cell;
61
+ delete value.rowId;
62
+ delete value.colId;
63
+ return value;
64
+ }
65
+
66
+ get rowId() {
67
+ return this.domNode.dataset.row!;
68
+ }
69
+
70
+ get colId() {
71
+ return this.domNode.dataset.cell!;
72
+ }
73
+ }
74
+ class TableCellInnerFormatOverride extends TableCellInnerFormat {
75
+ static allowDataAttrs = new Set(['table-id', 'row', 'cell', 'rowspan', 'colspan']);
76
+ static create(value: any) {
77
+ const node = super.create(value);
78
+ let { rowId, colId, row, cell } = value;
79
+ row = row || rowId;
80
+ cell = cell || colId;
81
+ node.dataset.row = row;
82
+ node.dataset.cell = cell;
83
+ node.removeAttribute('data-row-id');
84
+ node.removeAttribute('data-col-id');
85
+ return node;
86
+ }
87
+
88
+ static formats(domNode: HTMLElement) {
89
+ const value = super.formats(domNode);
90
+ const { row, cell } = domNode.dataset;
91
+ value.row = row;
92
+ value.cell = cell;
93
+ delete value.rowId;
94
+ delete value.colId;
95
+ return value;
96
+ }
97
+
98
+ get rowId() {
99
+ return this.domNode.dataset.row!;
100
+ }
101
+
102
+ set rowId(value) {
103
+ this.setFormatValue('row', value);
104
+ }
105
+
106
+ get colId() {
107
+ return this.domNode.dataset.cell!;
108
+ }
109
+
110
+ set colId(value) {
111
+ this.setFormatValue('cell', value);
112
+ }
113
+ }
114
+ class TableUpOverride extends TableUp {
115
+ static register(): void {
116
+ super.register();
117
+ Quill.register({
118
+ 'formats/a-col': TableColFormatOverride,
119
+ 'formats/a-cell': TableCellFormatOverride,
120
+ 'formats/a-cell-inner': TableCellInnerFormatOverride,
121
+ }, true);
122
+ }
123
+ }
124
+ Quill.register({
125
+ 'modules/tableUpOverride': TableUpOverride,
126
+ ...register,
127
+ }, true);
128
+ const container = document.body.appendChild(document.createElement('div'));
129
+ container.innerHTML = normalizeHTML(html);
130
+ const quill = new Quill(container, {
131
+ modules: {
132
+ tableUpOverride: options,
133
+ history: {
134
+ delay: 0,
135
+ },
136
+ ...moduleOptions,
137
+ },
138
+ });
139
+ return quill;
140
+ }
141
+
142
+ describe('test utils', () => {
143
+ it('test findParentBlot', async () => {
144
+ const quill = await createTable(1, 1);
145
+ const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
146
+ const tableCellBlot = findParentBlot(tds[0], blotName.tableCell);
147
+ expect(tableCellBlot).toBeInstanceOf(TableCellFormat);
148
+ const tableRowBlot = findParentBlot(tds[0], blotName.tableRow);
149
+ expect(tableRowBlot).toBeInstanceOf(TableRowFormat);
150
+ const tableBodyBlot = findParentBlot(tds[0], blotName.tableBody);
151
+ expect(tableBodyBlot).toBeInstanceOf(TableBodyFormat);
152
+ const tableMainBlot = findParentBlot(tds[0], blotName.tableMain);
153
+ expect(tableMainBlot).toBeInstanceOf(TableMainFormat);
154
+ const tableWrapperBlot = findParentBlot(tds[0], blotName.tableWrapper);
155
+ expect(tableWrapperBlot).toBeInstanceOf(TableWrapperFormat);
156
+ expect(() => findParentBlot(tds[0], 'scroll')).toThrowError(`${blotName.tableCellInner} must be a child of scroll`);
157
+ });
158
+
159
+ it('test findParentBlots', async () => {
160
+ const quill = await createTable(1, 1);
161
+ const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
162
+ const [tableCellBlot, tableRowBlot, tableBodyBlot, tableMainBlot, tableWrapperBlot] = findParentBlots(
163
+ tds[0],
164
+ [
165
+ blotName.tableCell,
166
+ blotName.tableRow,
167
+ blotName.tableBody,
168
+ blotName.tableMain,
169
+ blotName.tableWrapper,
170
+ ] as const,
171
+ );
172
+ expect(tableCellBlot).toBeInstanceOf(TableCellFormat);
173
+ expect(tableRowBlot).toBeInstanceOf(TableRowFormat);
174
+ expect(tableBodyBlot).toBeInstanceOf(TableBodyFormat);
175
+ expect(tableMainBlot).toBeInstanceOf(TableMainFormat);
176
+ expect(tableWrapperBlot).toBeInstanceOf(TableWrapperFormat);
177
+ });
178
+ });
179
+
180
+ // this test need be last. it's effect `blotName`
181
+ describe('test override format', () => {
182
+ it('should change blotName', async () => {
183
+ updateTableConstants({
184
+ blotName: {
185
+ tableCol: 'a-col',
186
+ tableCellInner: 'a-cell-inner',
187
+ },
188
+ });
189
+ const quill = await createTable(2, 2);
190
+ expect(quill.getContents()).toMatchObject({
191
+ ops: [
192
+ {
193
+ insert: '\n',
194
+ },
195
+ {
196
+ insert: {
197
+ 'a-col': {
198
+ tableId: '1',
199
+ colId: '1',
200
+ full: true,
201
+ width: 50,
202
+ },
203
+ },
204
+ },
205
+ {
206
+ insert: {
207
+ 'a-col': {
208
+ tableId: '1',
209
+ colId: '2',
210
+ full: true,
211
+ width: 50,
212
+ },
213
+ },
214
+ },
215
+ {
216
+ insert: '1',
217
+ },
218
+ {
219
+ attributes: {
220
+ 'a-cell-inner': {
221
+ tableId: '1',
222
+ colId: '1',
223
+ rowId: '1',
224
+ rowspan: 1,
225
+ colspan: 1,
226
+ },
227
+ },
228
+ insert: '\n',
229
+ },
230
+ {
231
+ insert: '2',
232
+ },
233
+ {
234
+ attributes: {
235
+ 'a-cell-inner': {
236
+ tableId: '1',
237
+ colId: '2',
238
+ rowId: '1',
239
+ rowspan: 1,
240
+ colspan: 1,
241
+ },
242
+ },
243
+ insert: '\n',
244
+ },
245
+ {
246
+ insert: '3',
247
+ },
248
+ {
249
+ attributes: {
250
+ 'a-cell-inner': {
251
+ tableId: '1',
252
+ colId: '1',
253
+ rowId: '2',
254
+ rowspan: 1,
255
+ colspan: 1,
256
+ },
257
+ },
258
+ insert: '\n',
259
+ },
260
+ {
261
+ insert: '4',
262
+ },
263
+ {
264
+ attributes: {
265
+ 'a-cell-inner': {
266
+ tableId: '1',
267
+ colId: '2',
268
+ rowId: '2',
269
+ rowspan: 1,
270
+ colspan: 1,
271
+ },
272
+ },
273
+ insert: '\n',
274
+ },
275
+ {
276
+ insert: '\n',
277
+ },
278
+ ],
279
+ });
280
+ expect(quill.root).toEqualHTML(
281
+ `
282
+ <p><br></p>
283
+ ${createTableHTML(2, 2)}
284
+ <p><br></p>
285
+ `,
286
+ { ignoreAttrs: ['class', 'style', 'data-table-id', 'contenteditable'] },
287
+ );
288
+ const tableModule = quill.getModule(TableUp.moduleName) as TableUp;
289
+ const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
290
+ tableModule.mergeCells([tds[0], tds[1], tds[2], tds[3]]);
291
+ await vi.runAllTimersAsync();
292
+ expect(quill.getContents()).toMatchObject({
293
+ ops: [
294
+ {
295
+ insert: '\n',
296
+ },
297
+ {
298
+ insert: {
299
+ 'a-col': {
300
+ tableId: '1',
301
+ colId: '1',
302
+ full: true,
303
+ width: 100,
304
+ },
305
+ },
306
+ },
307
+ {
308
+ insert: '1',
309
+ },
310
+ {
311
+ attributes: {
312
+ 'a-cell-inner': {
313
+ tableId: '1',
314
+ colId: '1',
315
+ rowId: '1',
316
+ rowspan: 1,
317
+ colspan: 1,
318
+ },
319
+ },
320
+ insert: '\n',
321
+ },
322
+ {
323
+ insert: '2',
324
+ },
325
+ {
326
+ attributes: {
327
+ 'a-cell-inner': {
328
+ tableId: '1',
329
+ colId: '1',
330
+ rowId: '1',
331
+ rowspan: 1,
332
+ colspan: 1,
333
+ },
334
+ },
335
+ insert: '\n',
336
+ },
337
+ {
338
+ insert: '3',
339
+ },
340
+ {
341
+ attributes: {
342
+ 'a-cell-inner': {
343
+ tableId: '1',
344
+ colId: '1',
345
+ rowId: '1',
346
+ rowspan: 1,
347
+ colspan: 1,
348
+ },
349
+ },
350
+ insert: '\n',
351
+ },
352
+ {
353
+ insert: '4',
354
+ },
355
+ {
356
+ attributes: {
357
+ 'a-cell-inner': {
358
+ tableId: '1',
359
+ colId: '1',
360
+ rowId: '1',
361
+ rowspan: 1,
362
+ colspan: 1,
363
+ },
364
+ },
365
+ insert: '\n',
366
+ },
367
+ {
368
+ insert: '\n',
369
+ },
370
+ ],
371
+ });
372
+ expect(quill.root).toEqualHTML(
373
+ `
374
+ <p><br></p>
375
+ <div>
376
+ <table cellpadding="0" cellspacing="0" data-full="true">
377
+ ${createTaleColHTML(1)}
378
+ <tbody>
379
+ <tr data-row-id="1">
380
+ <td rowspan="1" colspan="1" data-row-id="1" data-col-id="1">
381
+ <div data-rowspan="1" data-colspan="1" data-row-id="1" data-col-id="1">
382
+ <p>1</p>
383
+ <p>2</p>
384
+ <p>3</p>
385
+ <p>4</p>
386
+ </div>
387
+ </td>
388
+ </tr>
389
+ </tbody>
390
+ </table>
391
+ </div>
392
+ <p><br></p>
393
+ `,
394
+ { ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'contenteditable'] },
395
+ );
396
+ });
397
+
398
+ it('should change format name in delta', async () => {
399
+ const quill = createOverridesTable(`<p><br></p>`);
400
+ quill.setContents([
401
+ { insert: '\n' },
402
+ {
403
+ insert: {
404
+ 'a-col': { tableId: '1', column: '1', full: true, width: 50 },
405
+ },
406
+ },
407
+ {
408
+ insert: {
409
+ 'a-col': { tableId: '1', column: '2', full: true, width: 50 },
410
+ },
411
+ },
412
+ {
413
+ attributes: {
414
+ 'a-cell-inner': { tableId: '1', row: '1', cell: '1', rowspan: 1, colspan: 1 },
415
+ },
416
+ insert: '\n',
417
+ },
418
+ {
419
+ attributes: {
420
+ 'a-cell-inner': { tableId: '1', row: '1', cell: '2', rowspan: 1, colspan: 1 },
421
+ },
422
+ insert: '\n',
423
+ },
424
+ {
425
+ attributes: {
426
+ 'a-cell-inner': { tableId: '1', row: '2', cell: '1', rowspan: 1, colspan: 1 },
427
+ },
428
+ insert: '\n',
429
+ },
430
+ {
431
+ attributes: {
432
+ 'a-cell-inner': { tableId: '1', row: '2', cell: '2', rowspan: 1, colspan: 1 },
433
+ },
434
+ insert: '\n',
435
+ },
436
+ { insert: '\n' },
437
+ ]);
438
+ await vi.runAllTimersAsync();
439
+ expect(quill.getContents()).toMatchObject({
440
+ ops: [
441
+ {
442
+ insert: '\n',
443
+ },
444
+ {
445
+ insert: {
446
+ 'a-col': {
447
+ tableId: '1',
448
+ column: '1',
449
+ full: true,
450
+ width: 50,
451
+ },
452
+ },
453
+ },
454
+ {
455
+ insert: {
456
+ 'a-col': {
457
+ tableId: '1',
458
+ column: '2',
459
+ full: true,
460
+ width: 50,
461
+ },
462
+ },
463
+ },
464
+ {
465
+ attributes: {
466
+ 'a-cell-inner': {
467
+ tableId: '1',
468
+ cell: '1',
469
+ row: '1',
470
+ rowspan: 1,
471
+ colspan: 1,
472
+ },
473
+ },
474
+ insert: '\n',
475
+ },
476
+ {
477
+ attributes: {
478
+ 'a-cell-inner': {
479
+ tableId: '1',
480
+ cell: '2',
481
+ row: '1',
482
+ rowspan: 1,
483
+ colspan: 1,
484
+ },
485
+ },
486
+ insert: '\n',
487
+ },
488
+ {
489
+ attributes: {
490
+ 'a-cell-inner': {
491
+ tableId: '1',
492
+ cell: '1',
493
+ row: '2',
494
+ rowspan: 1,
495
+ colspan: 1,
496
+ },
497
+ },
498
+ insert: '\n',
499
+ },
500
+ {
501
+ attributes: {
502
+ 'a-cell-inner': {
503
+ tableId: '1',
504
+ cell: '2',
505
+ row: '2',
506
+ rowspan: 1,
507
+ colspan: 1,
508
+ },
509
+ },
510
+ insert: '\n',
511
+ },
512
+ {
513
+ insert: '\n',
514
+ },
515
+ ],
516
+ });
517
+ const colWidth = getColWidthStyle({ full: true, colNum: 2 });
518
+ expect(quill.root).toEqualHTML(
519
+ `
520
+ <p><br></p>
521
+ <div>
522
+ <table cellpadding="0" cellspacing="0"${datasetFull(true)}>
523
+ <colgroup${datasetFull(true)}>
524
+ ${new Array(2).fill(0).map((_, i) => `<col ${colWidth} data-col-id="${i + 1}"${datasetFull(true)} />`).join('\n')}
525
+ </colgroup>
526
+ <tbody>
527
+ ${
528
+ new Array(2).fill(0).map((_, i) => `
529
+ <tr data-row-id="${i + 1}">
530
+ ${
531
+ new Array(2).fill(0).map((_, j) => `<td rowspan="1" colspan="1" data-row="${i + 1}" data-cell="${j + 1}">
532
+ <div data-rowspan="1" data-colspan="1" data-row="${i + 1}" data-cell="${j + 1}">
533
+ <p>
534
+ <br>
535
+ </p>
536
+ </div>
537
+ </td>`).join('\n')
538
+ }
539
+ </tr>
540
+ `).join('\n')
541
+ }
542
+ </tbody>
543
+ </table>
544
+ </div>
545
+ <p><br></p>
546
+ `,
547
+ { ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'contenteditable'] },
548
+ );
549
+ });
550
+
551
+ it('should change format name in delta with contents', async () => {
552
+ const quill = createOverridesTable(`<p><br></p>`);
553
+ quill.setContents([
554
+ { insert: '\n' },
555
+ {
556
+ insert: {
557
+ 'a-col': { tableId: '1', column: '1', full: true, width: 50 },
558
+ },
559
+ },
560
+ {
561
+ insert: {
562
+ 'a-col': { tableId: '1', column: '2', full: true, width: 50 },
563
+ },
564
+ },
565
+ { insert: '1' },
566
+ {
567
+ attributes: {
568
+ 'a-cell-inner': { tableId: '1', row: '1', cell: '1', rowspan: 1, colspan: 1 },
569
+ },
570
+ insert: '\n',
571
+ },
572
+ { insert: '2' },
573
+ {
574
+ attributes: {
575
+ 'a-cell-inner': { tableId: '1', row: '1', cell: '2', rowspan: 1, colspan: 1 },
576
+ },
577
+ insert: '\n',
578
+ },
579
+ { insert: '3' },
580
+ {
581
+ attributes: {
582
+ 'a-cell-inner': { tableId: '1', row: '2', cell: '1', rowspan: 1, colspan: 1 },
583
+ },
584
+ insert: '\n',
585
+ },
586
+ { insert: '4' },
587
+ {
588
+ attributes: {
589
+ 'a-cell-inner': { tableId: '1', row: '2', cell: '2', rowspan: 1, colspan: 1 },
590
+ },
591
+ insert: '\n',
592
+ },
593
+ { insert: '\n' },
594
+ ]);
595
+ await vi.runAllTimersAsync();
596
+ expect(quill.getContents()).toMatchObject({
597
+ ops: [
598
+ {
599
+ insert: '\n',
600
+ },
601
+ {
602
+ insert: {
603
+ 'a-col': {
604
+ tableId: '1',
605
+ column: '1',
606
+ full: true,
607
+ width: 50,
608
+ },
609
+ },
610
+ },
611
+ {
612
+ insert: {
613
+ 'a-col': {
614
+ tableId: '1',
615
+ column: '2',
616
+ full: true,
617
+ width: 50,
618
+ },
619
+ },
620
+ },
621
+ { insert: '1' },
622
+ {
623
+ attributes: {
624
+ 'a-cell-inner': {
625
+ tableId: '1',
626
+ cell: '1',
627
+ row: '1',
628
+ rowspan: 1,
629
+ colspan: 1,
630
+ },
631
+ },
632
+ insert: '\n',
633
+ },
634
+ { insert: '2' },
635
+ {
636
+ attributes: {
637
+ 'a-cell-inner': {
638
+ tableId: '1',
639
+ cell: '2',
640
+ row: '1',
641
+ rowspan: 1,
642
+ colspan: 1,
643
+ },
644
+ },
645
+ insert: '\n',
646
+ },
647
+ { insert: '3' },
648
+ {
649
+ attributes: {
650
+ 'a-cell-inner': {
651
+ tableId: '1',
652
+ cell: '1',
653
+ row: '2',
654
+ rowspan: 1,
655
+ colspan: 1,
656
+ },
657
+ },
658
+ insert: '\n',
659
+ },
660
+ { insert: '4' },
661
+ {
662
+ attributes: {
663
+ 'a-cell-inner': {
664
+ tableId: '1',
665
+ cell: '2',
666
+ row: '2',
667
+ rowspan: 1,
668
+ colspan: 1,
669
+ },
670
+ },
671
+ insert: '\n',
672
+ },
673
+ {
674
+ insert: '\n',
675
+ },
676
+ ],
677
+ });
678
+ const colWidth = getColWidthStyle({ full: true, colNum: 2 });
679
+ expect(quill.root).toEqualHTML(
680
+ `
681
+ <p><br></p>
682
+ <div>
683
+ <table cellpadding="0" cellspacing="0"${datasetFull(true)}>
684
+ <colgroup${datasetFull(true)}>
685
+ ${new Array(2).fill(0).map((_, i) => `<col ${colWidth} data-col-id="${i + 1}"${datasetFull(true)} />`).join('\n')}
686
+ </colgroup>
687
+ <tbody>
688
+ ${
689
+ new Array(2).fill(0).map((_, i) => `
690
+ <tr data-row-id="${i + 1}">
691
+ ${
692
+ new Array(2).fill(0).map((_, j) => `<td rowspan="1" colspan="1" data-row="${i + 1}" data-cell="${j + 1}">
693
+ <div data-rowspan="1" data-colspan="1" data-row="${i + 1}" data-cell="${j + 1}">
694
+ <p>
695
+ ${i * 2 + j + 1}
696
+ </p>
697
+ </div>
698
+ </td>`).join('\n')
699
+ }
700
+ </tr>
701
+ `).join('\n')
702
+ }
703
+ </tbody>
704
+ </table>
705
+ </div>
706
+ <p><br></p>
707
+ `,
708
+ { ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'contenteditable'] },
709
+ );
710
+ });
711
+ });