import Quill from 'quill';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { TableCellInnerFormat } from '../../formats';
import { TableUp } from '../../table-up';
import { createQuillWithTableModule, createTableBodyHTML, createTableCaptionHTML, createTableDeltaOps, createTableHTML, createTaleColHTML, datasetTag, expectDelta, replaceAttrEmptyRow, simulatePasteHTML } from './utils';
const Delta = Quill.import('delta');
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
describe('clipboard cell structure', () => {
it('clipboard convert table', async () => {
Quill.register({ [`modules/${TableUp.moduleName}`]: TableUp }, true);
const container = document.body.appendChild(document.createElement('div'));
const quill = new Quill(container);
quill.setContents(
quill.clipboard.convert({
html: '
',
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTableHTML(3, 3, { width: 100, full: false }, undefined, { isEmpty: false })}
`,
{ ignoreAttrs: ['class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'contenteditable'] },
);
});
it('clipboard convert simple row merged cell', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: '',
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'contenteditable'] },
);
});
it('clipboard convert multiple merged cell', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: '',
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(6, { width: 92, full: false })}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'contenteditable'] },
);
});
it('clipboard convert multiple merged cell 2', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: '',
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(7, { width: 145, full: false })}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'contenteditable'] },
);
});
it('clipboard convert multiple merged cell 3', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: '',
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(4, { width: 100, full: false })}
|
|
|
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'contenteditable'] },
);
});
it('clipboard convert table without new line', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: '123
123
',
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
123
${createTableHTML(3, 3, { width: 100, full: false }, undefined, { isEmpty: false })}
123
`,
{ ignoreAttrs: ['class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'contenteditable'] },
);
});
it('clipboard convert cell border', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: ``,
}),
);
await vi.runAllTimersAsync();
// string convert html style have different behavior. in node will merge same attribute
// like: border-left-color:;border-right-color:;border-top-color:;border-bottom-color:; will merge to border-color:;
expect(quill.root).toEqualHTML(
`
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('clipboard convert cell border with different cell', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: ``,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(3, { full: false, width: 211 })}
|
|
|
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('clipboard convert cell background', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: ``,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(3, { full: false, width: 211 })}
|
|
|
|
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('clipboard convert cell height', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: ``,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(2, { full: false, width: 317 })}
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('clipboard convert empty cell should not ignore', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: ``,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(3, { full: false, width: 100 })}
|
|
|
|
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('clipboard convert cell background with default background', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: ``,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(2, { full: false, width: 121 })}
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 121 } } },
{ insert: { 'table-up-col': { full: false, width: 121 } } },
{ attributes: { background: '#e60000' }, insert: '123' },
{ insert: '456' },
{ attributes: { background: '#008a00' }, insert: '789' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, style: 'background-color: rgb(41, 114, 244);' } }, insert: '\n' },
{ insert: 'h' },
{ attributes: { background: '#000000' }, insert: 'ea' },
{ insert: 'd' },
{ attributes: { 'header': 1, 'table-up-cell-inner': { rowspan: 1, colspan: 1, style: 'background-color: rgb(41, 114, 244);' } }, insert: '\n' },
{ insert: '2' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('clipboard convert cell background if text background equal cell background then clean text background', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: ``,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(1, { full: false, width: 100 })}
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('convert background on table/tbody/tr/td', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: `
`,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(2, { full: false, width: 100 })}
|
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('clipboard convert should generate colgroup at correct position', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: '',
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTableCaptionHTML({ text: 'title' })}
${createTaleColHTML(3, { full: false, width: 100 })}
${createTableBodyHTML(1, 3, { isEmpty: false })}
`,
{ ignoreAttrs: ['class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
expectDelta(
new Delta([
{ insert: '\ntitle' },
{ attributes: { 'table-up-caption': { side: 'top' } }, insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 100 } } },
{ insert: { 'table-up-col': { full: false, width: 100 } } },
{ insert: { 'table-up-col': { full: false, width: 100 } } },
{ insert: '1' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '2' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '3' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('clipboard convert rowspan and struct have empty tr', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: `
`,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(2, { full: false, width: 63 })}
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'data-style', 'style', 'contenteditable'] },
);
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 63 } } },
{ insert: { 'table-up-col': { full: false, width: 63 } } },
{ insert: '合并1' },
{ attributes: { 'table-up-cell-inner': { rowspan: 3, colspan: 1 } }, insert: '\n' },
{ insert: '合并2' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '合并3' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '合并4' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('clipboard convert empty multiple tr to `emptyRow`', async () => {
const quill = createQuillWithTableModule('
', { autoMergeCell: false });
quill.setContents(
quill.clipboard.convert({
html: ``,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(3, { full: false, width: 100 })}
|
|
|
|
|
|
`,
{
ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'data-style', 'style', 'contenteditable'],
replaceAttrs: {
'data-empty-row': replaceAttrEmptyRow,
},
},
);
});
it('clipboard convert `emptyRow` cell', async () => {
const quill = createQuillWithTableModule('
', { autoMergeCell: false });
quill.setContents(
quill.clipboard.convert({
html: ``,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(3, { full: false, width: 100 })}
|
|
|
|
|
|
`,
{
ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'data-style', 'style', 'contenteditable'],
replaceAttrs: {
'data-empty-row': replaceAttrEmptyRow,
},
},
);
});
it('clipboard convert continuous `emptyRow`', async () => {
const quill = createQuillWithTableModule('
', { autoMergeCell: false });
quill.setContents(
quill.clipboard.convert({
html: ``,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(3, { full: false, width: 100 })}
|
|
|
|
|
|
|
|
`,
{
ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'data-style', 'style', 'contenteditable'],
replaceAttrs: {
'data-empty-row': replaceAttrEmptyRow,
},
},
);
});
it('clipboard convert empty tr to `emptyRow` in thead', async () => {
const quill = createQuillWithTableModule(`
`, { autoMergeCell: false });
quill.setContents(
quill.clipboard.convert({
html: ``,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(2, { full: false, width: 100 })}
|
|
|
|
|
|
|
|
`,
{
ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'data-style', 'style', 'contenteditable'],
replaceAttrs: {
'data-empty-row': replaceAttrEmptyRow,
},
},
);
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 100 } } },
{ insert: { 'table-up-col': { full: false, width: 100 } } },
{ insert: '1' },
{ attributes: { 'table-up-cell-inner': { rowspan: 2, colspan: 2, wrapTag: 'thead' } }, insert: '\n' },
{ insert: '1' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '2' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '1' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '2' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('clipboard convert col with span attribute', async () => {
const quill = createQuillWithTableModule(`
`, { autoMergeCell: false });
quill.setContents(
quill.clipboard.convert({
html: `
`,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(4, { full: false, width: 63 })}
|
|
|
|
|
|
|
`,
{
ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'data-style', 'style', 'contenteditable'],
replaceAttrs: {
'data-empty-row': replaceAttrEmptyRow,
},
},
);
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 63 } } },
{ insert: { 'table-up-col': { full: false, width: 63 } } },
{ insert: { 'table-up-col': { full: false, width: 63 } } },
{ insert: { 'table-up-col': { full: false, width: 63 } } },
{ insert: '1' },
{ attributes: { 'table-up-cell-inner': { rowspan: 6, colspan: 2 } }, insert: '\n' },
{ insert: '2' },
{ attributes: { 'table-up-cell-inner': { rowspan: 2, colspan: 2 } }, insert: '\n' },
{ insert: '3' },
{ attributes: { 'table-up-cell-inner': { rowspan: 2, colspan: 2 } }, insert: '\n' },
{ insert: '4' },
{ attributes: { 'table-up-cell-inner': { rowspan: 2, colspan: 2 } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('clipboard convert th correctly', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: `
| Company |
Contact |
Country |
| Alfreds Futterkiste |
Maria Anders |
Germany |
| Centro comercial Moctezuma |
Francisco Chang |
Mexico |
`,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(3, { full: false, width: 100 })}
|
|
|
|
|
|
|
|
Centro comercial Moctezuma
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('convert thead and tfoot correctly', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: `
| head1 |
head2 |
head3 |
| body1 |
body2 |
body3 |
| body4 |
body5 |
body6 |
| foot1 |
foot2 |
foot3 |
`,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(3, { full: false, width: 100 })}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('convert thead rowspan to tbody', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: `
`,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(2, { full: false, width: 100 })}
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
});
describe('clipboard content format', () => {
it('should convert html code-block correctly', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({ html: '' }),
);
await vi.runAllTimersAsync();
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 121 } } },
{ insert: { 'table-up-col': { full: false, width: 121 } } },
{ insert: { 'table-up-col': { full: false, width: 121 } } },
{ insert: '1' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '2' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '3' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '4' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '5' },
{ attributes: { 'code-block': 'plain', 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '5' },
{ attributes: { 'code-block': 'plain', 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '5' },
{ attributes: { 'code-block': 'plain', 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '5' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '5' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '5' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '6' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '7' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '8' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '9' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('should convert html header correctly', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({ html: '' }),
);
await vi.runAllTimersAsync();
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 583 } } },
{ insert: { 'table-up-col': { full: false, width: 583 } } },
{ insert: 'header1' },
{ attributes: { 'header': 1, 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: 'header3' },
{ attributes: { 'header': 3, 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('should convert html image correctly', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({ html: '' }),
);
await vi.runAllTimersAsync();
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: true, width: 100 } } },
{ insert: { image: 'https://upload-bbs.miyoushe.com/upload/2024/06/18/5556092/73b7bae28fded7a72d93a35d5559b24c_3979852353547906724.png' } },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('should convert html video correctly', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({ html: '' }),
);
await vi.runAllTimersAsync();
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: true, width: 100 } } },
{ insert: { video: 'http://127.0.0.1:5500/docs/index.html' } },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('should convert html list correctly', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({ html: ' | |
- list checkbox
- checkbox checked
| |
' }),
);
await vi.runAllTimersAsync();
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 583 } } },
{ insert: { 'table-up-col': { full: false, width: 583 } } },
{ insert: 'list order' },
{ attributes: { 'list': 'ordered', 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: 'aaa' },
{ attributes: { 'indent': 1, 'list': 'ordered', 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: 'list bullet' },
{ attributes: { 'list': 'bullet', 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: 'list checkbox' },
{ attributes: { 'list': 'unchecked', 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: 'checkbox checked' },
{ attributes: { 'list': 'checked', 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('should convert html blockquote correctly', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(quill.clipboard.convert({
html: '',
}));
await vi.runAllTimersAsync();
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 583 } } },
{ insert: { 'table-up-col': { full: false, width: 583 } } },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: 'blockquote' },
{ attributes: { 'blockquote': true, 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n\n' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('clipboard convert cell with block format html', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: '',
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(5, { width: 233, full: false })}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'contenteditable'] },
);
});
it('clipboard conver multiple formats and attributes', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(
quill.clipboard.convert({
html: ``,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(3, { full: false, width: 100 })}
|
|
|
|
|
|
|
|
|
|
`,
{
ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'],
},
);
});
it('clipboard convert cell with background on tr', async () => {
const quill = createQuillWithTableModule(`
`);
// color convert hex in quill internal
quill.setContents(
quill.clipboard.convert({
html: `
`,
}),
);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(3, { width: 100, full: false })}
|
|
|
|
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'colspan', 'rowspan', 'data-colspan', 'data-rowspan', 'data-table-id', 'data-row-id', 'data-col-id', 'contenteditable'] },
);
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 100 } } },
{ insert: { 'table-up-col': { full: false, width: 100 } } },
{ insert: { 'table-up-col': { full: false, width: 100 } } },
{ attributes: { background: '#edeef2' }, insert: '1' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, style: 'background-color: rgb(237, 238, 242);' } }, insert: '\n' },
{ attributes: { background: '#edeef2' }, insert: '2' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, style: 'background-color: rgb(237, 238, 242);' } }, insert: '\n' },
{ attributes: { background: '#edeef2' }, insert: '3' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, style: 'background-color: rgb(237, 238, 242);' } }, insert: '\n' },
{ insert: '4' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '5' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '6' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ attributes: { background: '#edeef2' }, insert: '7' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, style: 'background-color: rgb(237, 238, 242);' } }, insert: '\n' },
{ attributes: { background: '#edeef2' }, insert: '8' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, style: 'background-color: rgb(237, 238, 242);' } }, insert: '\n' },
{ attributes: { background: '#edeef2' }, insert: '9' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1, style: 'background-color: rgb(237, 238, 242);' } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
});
describe('clipboard cell in cell', () => {
it('paste simple text into table', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(createTableDeltaOps(1, 1, { full: false, width: 100 }, {}, { isEmpty: true }));
await vi.runAllTimersAsync();
await simulatePasteHTML(
quill,
{ index: 2, length: 0 },
'text
123
',
);
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 100 } } },
{ insert: 'text' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '123' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('paste format text into table', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(createTableDeltaOps(1, 1, { full: false, width: 100 }, {}, { isEmpty: true }));
await vi.runAllTimersAsync();
await simulatePasteHTML(
quill,
{ index: 2, length: 0 },
'\r\n\r\n\u003C!--StartFragment-->123
123qwe
\u003C!--EndFragment-->\r\n\r\n',
);
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 100 } } },
{ insert: '123' },
{ attributes: { 'header': 1, 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ attributes: { underline: true, strike: true, italic: true, background: '#000000', color: '#e60000', bold: true }, insert: '123' },
{ attributes: { underline: true, strike: true, italic: true, bold: true, background: '#000000', color: '#e60000', script: 'sub' }, insert: 'qwe' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('paste cell text into table', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(createTableDeltaOps(1, 1, { full: false, width: 100 }, {}, { isEmpty: true }));
await vi.runAllTimersAsync();
const range = { index: 2, length: 0 };
quill.setSelection(range);
quill.clipboard.onPaste(
range,
{ html: '\r\n\r\n\u003C!--StartFragment-->\u003C!--EndFragment-->\r\n\r\n' },
);
await vi.runAllTimersAsync();
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 100 } } },
{ insert: '5' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n\n' },
{ insert: 'q' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
it('paste cell with format text into table', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(createTableDeltaOps(1, 1, { full: false, width: 100 }, {}, { isEmpty: true }));
await vi.runAllTimersAsync();
const range = { index: 2, length: 0 };
quill.setSelection(range);
quill.clipboard.onPaste(
range,
{ html: '\r\n\r\n\u003C!--StartFragment-->\u003C!--EndFragment-->\r\n\r\n' },
);
await vi.runAllTimersAsync();
expectDelta(
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { full: false, width: 100 } } },
{ insert: '123' },
{ attributes: { 'header': 1, 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n' },
{ attributes: { underline: true, strike: true, italic: true, bold: true }, insert: '123' },
{ attributes: { underline: true, strike: true, italic: true, bold: true, script: 'sub' }, insert: 'qwe' },
{ attributes: { underline: true, strike: true, italic: true, bold: true, script: 'super' }, insert: 'qwe' },
{ attributes: { 'table-up-cell-inner': { rowspan: 1, colspan: 1 } }, insert: '\n\n' },
{ insert: '\n' },
]),
quill.getContents(),
);
});
});
describe('test TableUp `getHTMLByCell`', () => {
it('getHTMLByCell return cell html', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(createTableDeltaOps(4, 4, { full: true }, {}, { isEmpty: false }));
const tableModule = quill.getModule(TableUp.moduleName) as TableUp;
const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
tableModule.mergeCells([tds[0], tds[1], tds[4], tds[5]]);
await vi.runAllTimersAsync();
const html = tableModule.getHTMLByCell([tds[0], tds[2], tds[6]]);
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
const htmlCols = Array.from(doc.querySelectorAll('col'));
const htmlTds = Array.from(doc.querySelectorAll('td'));
expect(htmlCols.length).toBe(3);
expect(htmlTds.length).toBe(3);
for (const col of htmlCols) {
expect(col.getAttribute('width')).toBe('33%');
}
});
});