import { EditorState, TextSelection } from "prosemirror-state"; import { buildNode } from "../../__specs__/buildEditorState"; import "../../__specs__/expect.toMatchNode"; import { RefsNode } from "../../composing"; import { TableNode, TableStart } from "../../types"; import { CellSelection } from "../CellSelection"; import { fixTables, toggleTableSelection } from "../operations"; const cw100 = buildNode(({ td_, p }) => td_({ colwidth: [100] })(p("x"))); const cw200 = buildNode(({ td_, p }) => td_({ colwidth: [200] })(p("x"))); describe("fixTable", () => { function fix(table: RefsNode) { const state = EditorState.create({ doc: buildNode(({ doc }) => doc(table.node)).node }); const tr = fixTables(state); return tr !== undefined ? tr.doc.firstChild : null; } it("doesn't touch correct tables", () => expect(fix(buildNode(({ table, tr, c11, c }) => table(tr(c11, c11, c(1, 2)), tr(c11, c11))))).toBe(null)); it("adds trivially missing cells", () => expect(fix(buildNode(({ table, tr, c11, c }) => table(tr(c11, c11, c(1, 2)), tr(c11))))).toMatchNode( buildNode(({ table, tr, c11, c, cEmpty }) => table(tr(c11, c11, c(1, 2)), tr(c11, cEmpty))).node )); it("can add to multiple rows", () => expect(fix(buildNode(({ table, tr, c11, c }) => table(tr(c11), tr(c11, c11), tr(c(3, 1)))))).toMatchNode( buildNode(({ table, tr, c11, c, cEmpty }) => table(tr(c11, cEmpty, cEmpty), tr(cEmpty, c11, c11), tr(c(3, 1)))).node )); it("will default to adding at the start of the first row", () => expect(fix(buildNode(({ table, tr, c11 }) => table(tr(c11), tr(c11, c11))))).toMatchNode( buildNode(({ table, tr, c11, cEmpty }) => table(tr(cEmpty, c11), tr(c11, c11))).node )); it("will default to adding at the end of the non-first row", () => expect(fix(buildNode(({ table, tr, c11 }) => table(tr(c11, c11), tr(c11))))).toMatchNode( buildNode(({ table, tr, c11, cEmpty }) => table(tr(c11, c11), tr(c11, cEmpty))).node )); it("will fix overlapping cells", () => expect(fix(buildNode(({ table, tr, c11, c }) => table(tr(c11, c(1, 2), c11), tr(c(2, 1)))))).toMatchNode( buildNode(({ table, tr, c11, c, cEmpty }) => table(tr(c11, c(1, 2), c11), tr(c11, cEmpty, cEmpty))).node )); it("will fix a rowspan that sticks out of the table", () => expect(fix(buildNode(({ table, tr, c11, c }) => table(tr(c11, c11), tr(c(1, 2), c11))))).toMatchNode( buildNode(({ table, tr, c11 }) => table(tr(c11, c11), tr(c11, c11))).node )); it("makes sure column widths are coherent", () => expect(fix(buildNode(({ table, tr, c11 }) => table(tr(c11, c11, cw200), tr(cw100, c11, c11))))).toMatchNode( buildNode(({ table, tr, c11 }) => table(tr(cw100, c11, cw200), tr(cw100, c11, cw200))).node )); it("can update column widths on colspan cells", () => expect(fix(buildNode(({ table, tr, c11, c }) => table(tr(c11, c11, cw200), tr(c(3, 2)), tr())))).toMatchNode( buildNode(({ table, tr, c11, td_, p }) => table(tr(c11, c11, cw200), tr(td_({ colspan: 3, rowspan: 2, colwidth: [0, 0, 200] })(p("x"))), tr()) ).node )); it("will update the odd one out when column widths disagree", () => expect( fix(buildNode(({ table, tr }) => table(tr(cw100, cw100, cw100), tr(cw200, cw200, cw100), tr(cw100, cw200, cw200)))) ).toMatchNode( buildNode(({ table, tr }) => table(tr(cw100, cw200, cw100), tr(cw100, cw200, cw100), tr(cw100, cw200, cw100))).node )); }); describe("toggleTableSelection", () => { const doc = buildNode(({ doc, table, tr, cEmpty }) => doc( table( /* 1 */ tr(/* 2 */ cEmpty, /* 6 */ cEmpty, /* 10 */ cEmpty), /* 15 */ tr(/* 16 */ cEmpty, /* 20 */ cEmpty, /* 24 */ cEmpty), /* 29 */ tr(/* 30 */ cEmpty, /* 34 */ cEmpty, /* 38 */ cEmpty) ) ) ).node; function toggle(anchorCell: number, headCell: number): EditorState { const state = EditorState.create({ doc: doc, selection: CellSelection.create(doc, anchorCell, headCell) }); const tr = state.tr; const table = doc.resolve(0).nodeAfter! as TableNode; toggleTableSelection(tr, table, 1 as TableStart); return state.apply(tr); } it("will select an entire table when one cell is selected", () => { const sel = toggle(2, 2).selection; expect(sel).toBeInstanceOf(CellSelection); const cellSel = sel as CellSelection; expect(cellSel.$anchorCell.pos).toBe(2); expect(cellSel.$headCell.pos).toBe(38); }); it("will deselect the entire table if it is entirely selected", () => { const sel = toggle(2, 38).selection; expect(sel).toBeInstanceOf(TextSelection); const textSel = sel as TextSelection; expect(textSel.anchor).toBe(39); }); });