import type { TableMainFormat } from '../../formats';
import Quill from 'quill';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { TableCellInnerFormat } from '../../formats';
import { TableUp } from '../../table-up';
import { createQuillWithTableModule, createTable, createTableBodyHTML, createTableDeltaOps, createTableHTML, createTaleColHTML, datasetAlign, datasetFull, expectDelta } from './utils';
const Delta = Quill.import('delta');
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
describe('insert embed blot', () => {
it('insert image', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '1', colId: '1', full: 'true', width: 100 } } },
{ insert: { image: 'https://live.mdnplay.dev/en-US/docs/Web/HTML/Element/img/favicon144.png' } },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
});
describe('insert block blot', () => {
it('insert list', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '1', colId: '1', full: 'true', width: 100 } } },
{ insert: 'text' },
{ attributes: { 'list': 'bullet', 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('insert header', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '1', colId: '1', full: 'true', width: 100 } } },
{ insert: 'text' },
{ attributes: { 'header': 2, 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('insert blockquote', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '1', colId: '1', full: 'true', width: 100 } } },
{ insert: 'text' },
{ attributes: { 'blockquote': true, 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('insert code-block', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '1', colId: '1', full: 'true', width: 100 } } },
{ insert: 'text' },
{ attributes: { 'code-block': 'plain', 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: 'br' },
{ attributes: { 'code-block': 'plain', 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
});
describe('insert block embed blot', () => {
it('insert video', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '1', colId: '1', full: 'true', width: 100 } } },
{ insert: { video: 'https://quilljs.com/' } },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('BlockEmbed should at correct position in cell', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '2l7117zsa6r', colId: 'd962746f4w8', full: false, width: 100 } } },
{ insert: '1' },
{ attributes: { 'table-up-cell-inner': { tableId: '2l7117zsa6r', rowId: 'a9r52q9z4l', colId: 'd962746f4w8', rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: { video: 'http://localhost:5500/docs/index.html' } },
{ insert: 'bbb' },
{ attributes: { 'table-up-cell-inner': { tableId: '2l7117zsa6r', rowId: 'a9r52q9z4l', colId: 'd962746f4w8', rowspan: 1, colspan: 1 } }, insert: '\n' },
{ insert: '\n' },
]);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(1, { full: false, width: 100 })}
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('makesure the text delta order is correct', () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '1', colId: '1', full: 'true', width: 100 } } },
{ insert: { video: 'https://quilljs.com/' } },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1 } }, insert: '\n\n' },
{ insert: '\n' },
]);
quill.insertText(4, '123');
expect(quill.root).toEqualHTML(
`
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
expectDelta(
quill.getContents(),
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '1', colId: '1', full: true, width: 100 } } },
{ insert: { video: 'https://quilljs.com/' } },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '123' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '\n' },
]),
);
});
});
describe('set contents', () => {
it('should optimize correctly', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(createTableDeltaOps(3, 3));
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTableHTML(3, 3)}
`,
{ ignoreAttrs: ['class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('should get correct prop', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(createTableDeltaOps(3, 3, { full: false, width: 200, align: 'center' }));
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTableHTML(3, 3, { full: false, width: 200, align: 'center' })}
`,
{ ignoreAttrs: ['class', 'contenteditable'] },
);
});
it('should display an empty table', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(createTableDeltaOps(2, 2, {}, {}, { isEmpty: true }));
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTableHTML(2, 2, {}, undefined, { isEmpty: true })}
`,
{ ignoreAttrs: ['class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('delta should render save construct', async () => {
const quill = await createTable(3, 2);
const tableModule = quill.getModule(TableUp.moduleName) as TableUp;
const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
tableModule.setCellAttrs([tds[0], tds[1]], 'background-color', 'red', true);
tableModule.setCellAttrs([tds[2], tds[3]], 'border-color', 'red', true);
tableModule.setCellAttrs([tds[4], tds[5]], 'height', '50px', true);
await vi.runAllTimersAsync();
const delta = quill.getContents();
expectDelta(
quill.getContents(),
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '1', colId: '1', full: true, width: 50 } } },
{ insert: { 'table-up-col': { tableId: '1', colId: '2', full: true, width: 50 } } },
{ insert: '1' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'background-color: red; border-bottom-color: red;' } }, insert: '\n' },
{ insert: '2' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '2', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'background-color: red; border-bottom-color: red;' } }, insert: '\n' },
{ insert: '3' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '2', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-color: red;' } }, insert: '\n' },
{ insert: '4' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '2', colId: '2', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-color: red;' } }, insert: '\n' },
{ insert: '5' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '3', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'height: 50px;' } }, insert: '\n' },
{ insert: '6' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '3', colId: '2', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'height: 50px;' } }, insert: '\n' },
{ insert: '\n' },
]),
);
quill.setContents([{ insert: '\n' }]);
quill.setContents(delta);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(2, { width: 50, full: true })}
|
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'rowspan', 'colspan', 'data-full', 'data-style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
});
describe('column width calculate', () => {
it('should calculate correct width', async () => {
const quill = createQuillWithTableModule(`
`);
quill.setContents(createTableDeltaOps(3, 3, { full: false }));
await vi.runAllTimersAsync();
expect(quill.root.querySelectorAll('table')[0].style.width).toBe('300px');
});
});
describe('insert row into table', () => {
it('insert row top', async () => {
const quill = createQuillWithTableModule(`
`);
const tableModule = quill.getModule(TableUp.moduleName) as TableUp;
tableModule.insertTable(2, 2);
await vi.runAllTimersAsync();
const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
tableModule.appendRow([tds[0]], false);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${
new Array(3).fill(0).map(() => `
${new Array(2).fill(0).map(() => ` | `).join('\n')}
`).join('\n')
}
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('insert row top and index is inside rowspan cell', async () => {
const quill = createQuillWithTableModule(`
`);
const tableModule = quill.getModule(TableUp.moduleName) as TableUp;
tableModule.insertTable(3, 5);
await vi.runAllTimersAsync();
const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
tableModule.mergeCells([tds[0], tds[1], tds[2], tds[5], tds[6], tds[7]]);
await vi.runAllTimersAsync();
tableModule.mergeCells([tds[9], tds[14]]);
await vi.runAllTimersAsync();
tableModule.appendRow([tds[8]], false);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${new Array(5).fill(0).map(() => ``).join('\n')}
|
|
|
|
|
|
|
|
|
|
|
|
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('insert row bottom', async () => {
const quill = createQuillWithTableModule(`
`);
const tableModule = quill.getModule(TableUp.moduleName) as TableUp;
tableModule.insertTable(2, 2);
await vi.runAllTimersAsync();
const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
tableModule.appendRow([tds[2]], true);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${
new Array(3).fill(0).map(() => `
${new Array(2).fill(0).map(() => ` | `).join('\n')}
`).join('\n')
}
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
it('insert row bottom and index is inside rowspan cell', async () => {
const quill = createQuillWithTableModule(`
`);
const tableModule = quill.getModule(TableUp.moduleName) as TableUp;
tableModule.insertTable(2, 5);
await vi.runAllTimersAsync();
const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
tableModule.mergeCells([tds[1], tds[2], tds[3], tds[6], tds[7], tds[8]]);
tableModule.appendRow([tds[0]], true);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'style', 'data-table-id', 'data-row-id', 'data-col-id', 'data-rowspan', 'data-colspan', 'contenteditable'] },
);
});
});
describe('set cell attribute', () => {
it('set bg color', async () => {
const quill = await createTable(3, 3);
const tableModule = quill.getModule(TableUp.moduleName) as TableUp;
const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
tableModule.setCellAttrs([tds[0], tds[1], tds[2]], 'background-color', 'rgb(253, 235, 255)', true);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(3)}
${
new Array(3).fill(0).map((_, i) => `
${
new Array(3).fill(0).map((_, j) => `|
| `).join('\n')
}
`).join('\n')
}
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'contenteditable'] },
);
});
it('set border color', async () => {
const quill = await createTable(2, 2);
const tableModule = quill.getModule(TableUp.moduleName) as TableUp;
const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
tableModule.setCellAttrs([tds[0], tds[1]], 'border-color', 'red', true);
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
`,
{ ignoreAttrs: ['data-wrap-tag', 'data-tag', 'class', 'data-table-id', 'contenteditable'] },
);
expectDelta(
quill.getContents(),
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '1', colId: '1', full: true, width: 50 } } },
{ insert: { 'table-up-col': { tableId: '1', colId: '2', full: true, width: 50 } } },
{ insert: '1' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-color: red;' } }, insert: '\n' },
{ insert: '2' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '2', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-color: red;' } }, insert: '\n' },
{ insert: '3' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '2', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '4' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '2', colId: '2', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '\n' },
]),
);
});
it('set table align change', async () => {
const quill = await createTable(3, 3, { full: false, width: 100 });
const table = quill.root.querySelector('table')!;
const tableBlot = Quill.find(table) as TableMainFormat;
const cols = tableBlot.getCols();
for (const col of cols) {
col.align = 'center';
}
await vi.runAllTimersAsync();
expect(quill.root).toEqualHTML(
`
${createTaleColHTML(3, { align: 'center', full: false, width: 100 })}
${createTableBodyHTML(3, 3)}
`,
{ ignoreAttrs: ['class', 'data-table-id', 'contenteditable'] },
);
});
it('set span cell border color', async () => {
const quill = await createTable(5, 5, {}, {}, { isEmpty: true });
const tableModule = quill.getModule(TableUp.moduleName) as TableUp;
const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
tableModule.mergeCells([tds[6], tds[7], tds[8], tds[11], tds[12], tds[13], tds[16], tds[17], tds[18]]);
const mergedTds = quill.scroll.descendants(TableCellInnerFormat, 0);
tableModule.setCellAttrs([mergedTds[6]], 'border-color', 'red', true);
await vi.runAllTimersAsync();
expectDelta(
quill.getContents(),
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '1', colId: '1', full: true, width: 20 } } },
{ insert: { 'table-up-col': { tableId: '1', colId: '2', full: true, width: 20 } } },
{ insert: { 'table-up-col': { tableId: '1', colId: '3', full: true, width: 20 } } },
{ insert: { 'table-up-col': { tableId: '1', colId: '4', full: true, width: 20 } } },
{ insert: { 'table-up-col': { tableId: '1', colId: '5', full: true, width: 20 } } },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '2', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-bottom-color: red;' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '3', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-bottom-color: red;' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '4', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-bottom-color: red;' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '5', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '2', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-right-color: red;' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '2', colId: '2', rowspan: 3, colspan: 3, tag: 'td', wrapTag: 'tbody', style: 'border-color: red;' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '2', colId: '5', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '3', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-right-color: red;' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '3', colId: '5', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '4', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-right-color: red;' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '4', colId: '5', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '5', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '5', colId: '2', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '5', colId: '3', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '5', colId: '4', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '5', colId: '5', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '\n' },
]),
);
});
it('set rowspan and colspan cell border color', async () => {
const quill = await createTable(6, 4, {}, {}, { isEmpty: true });
const tableModule = quill.getModule(TableUp.moduleName) as TableUp;
const tds = quill.scroll.descendants(TableCellInnerFormat, 0);
tableModule.mergeCells([tds[4], tds[5], tds[8], tds[9]]);
await vi.runAllTimersAsync();
tableModule.mergeCells([tds[13], tds[14], tds[17], tds[18]]);
await vi.runAllTimersAsync();
const mergedTds = quill.scroll.descendants(TableCellInnerFormat, 0);
tableModule.setCellAttrs([mergedTds[10]], 'border-color', 'red', true);
await vi.runAllTimersAsync();
expectDelta(
quill.getContents(),
new Delta([
{ insert: '\n' },
{ insert: { 'table-up-col': { tableId: '1', colId: '1', full: true, width: 25 } } },
{ insert: { 'table-up-col': { tableId: '1', colId: '2', full: true, width: 25 } } },
{ insert: { 'table-up-col': { tableId: '1', colId: '3', full: true, width: 25 } } },
{ insert: { 'table-up-col': { tableId: '1', colId: '4', full: true, width: 25 } } },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '2', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '3', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '1', colId: '4', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '2', colId: '1', rowspan: 2, colspan: 2, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '2', colId: '3', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '2', colId: '4', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '3', colId: '3', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-bottom-color: red;' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '3', colId: '4', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '4', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-right-color: red;' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '4', colId: '2', rowspan: 2, colspan: 2, tag: 'td', wrapTag: 'tbody', style: 'border-color: red;' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '4', colId: '4', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '5', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody', style: 'border-right-color: red;' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '5', colId: '4', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '6', colId: '1', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '6', colId: '2', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '6', colId: '3', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ attributes: { 'table-up-cell-inner': { tableId: '1', rowId: '6', colId: '4', rowspan: 1, colspan: 1, tag: 'td', wrapTag: 'tbody' } }, insert: '\n' },
{ insert: '\n' },
]),
);
});
});
describe('cell editable', () => {
it('quill enable hack should useable when initial readOnly `false`', async () => {
const quill = await createTable(3, 3);
const inners = quill.root.querySelectorAll('.ql-table-cell-inner');
expect(inners.length).toBe(9);
for (const inner of Array.from(inners)) {
expect(inner.getAttribute('contenteditable')).toBe('true');
}
quill.disable();
const disabledInners = quill.root.querySelectorAll('.ql-table-cell-inner');
expect(disabledInners.length).toBe(9);
for (const inner of Array.from(disabledInners)) {
expect(inner.getAttribute('contenteditable')).toBe('false');
}
quill.enable(true);
const enabledInners = quill.root.querySelectorAll('.ql-table-cell-inner');
expect(enabledInners.length).toBe(9);
for (const inner of Array.from(enabledInners)) {
expect(inner.getAttribute('contenteditable')).toBe('true');
}
});
it('quill enable hack should useable when initial readOnly `true`', async () => {
const quill = createQuillWithTableModule(`
`, {}, {}, { readOnly: true });
quill.setContents(createTableDeltaOps(3, 3));
await vi.runAllTimersAsync();
const disabledInners = quill.root.querySelectorAll('.ql-table-cell-inner');
expect(disabledInners.length).toBe(9);
for (const inner of Array.from(disabledInners)) {
expect(inner.getAttribute('contenteditable')).toBe('false');
}
quill.enable(true);
const enabledInners = quill.root.querySelectorAll('.ql-table-cell-inner');
expect(enabledInners.length).toBe(9);
for (const inner of Array.from(enabledInners)) {
expect(inner.getAttribute('contenteditable')).toBe('true');
}
});
it('multiple quill editor table cell should effect each other', async () => {
const quill1 = createQuillWithTableModule(`
`, {}, {}, { readOnly: true });
quill1.setContents(createTableDeltaOps(3, 3));
await vi.runAllTimersAsync();
const quill2 = createQuillWithTableModule(`
`, {}, {}, { readOnly: false });
quill2.setContents(createTableDeltaOps(3, 3));
await vi.runAllTimersAsync();
const disabledInners1 = quill1.root.querySelectorAll('.ql-table-cell-inner');
expect(disabledInners1.length).toBe(9);
for (const inner of Array.from(disabledInners1)) {
expect(inner.getAttribute('contenteditable')).toBe('false');
}
const enabledInners2 = quill2.root.querySelectorAll('.ql-table-cell-inner');
expect(enabledInners2.length).toBe(9);
for (const inner of Array.from(enabledInners2)) {
expect(inner.getAttribute('contenteditable')).toBe('true');
}
quill1.enable(true);
const enabledInners1 = quill1.root.querySelectorAll('.ql-table-cell-inner');
expect(enabledInners1.length).toBe(9);
for (const inner of Array.from(enabledInners1)) {
expect(inner.getAttribute('contenteditable')).toBe('true');
}
quill2.enable(false);
const disabledInners2 = quill2.root.querySelectorAll('.ql-table-cell-inner');
expect(disabledInners2.length).toBe(9);
for (const inner of Array.from(disabledInners2)) {
expect(inner.getAttribute('contenteditable')).toBe('false');
}
});
});