@atlaskit/editor-tables 2.2.4 → 2.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/cell-bookmark.js +0 -10
- package/dist/cjs/cell-selection.js +37 -102
- package/dist/cjs/index.js +0 -4
- package/dist/cjs/pm-plugins/input.js +17 -83
- package/dist/cjs/pm-plugins/plugin-key.js +0 -2
- package/dist/cjs/pm-plugins/table-editing.js +17 -18
- package/dist/cjs/pm-plugins.js +0 -2
- package/dist/cjs/table-map.js +67 -138
- package/dist/cjs/utils/add-column-at.js +0 -9
- package/dist/cjs/utils/add-column.js +8 -24
- package/dist/cjs/utils/add-row-at.js +8 -37
- package/dist/cjs/utils/add-row.js +2 -23
- package/dist/cjs/utils/analytics-helpers.js +4 -15
- package/dist/cjs/utils/cells.js +0 -12
- package/dist/cjs/utils/clone-tr.js +0 -2
- package/dist/cjs/utils/colspan.js +2 -18
- package/dist/cjs/utils/copy-paste.js +51 -139
- package/dist/cjs/utils/create-table.js +14 -28
- package/dist/cjs/utils/draw-cell-selection.js +0 -4
- package/dist/cjs/utils/empty-cells.js +0 -6
- package/dist/cjs/utils/find.js +6 -18
- package/dist/cjs/utils/fix-tables.js +13 -56
- package/dist/cjs/utils/for-each-cell.js +3 -17
- package/dist/cjs/utils/get-cell-selection-ranges.js +2 -9
- package/dist/cjs/utils/get-cells-in-column.js +0 -7
- package/dist/cjs/utils/get-cells-in-row.js +0 -7
- package/dist/cjs/utils/get-cells-in-table.js +0 -8
- package/dist/cjs/utils/get-selection-range-in-column.js +6 -27
- package/dist/cjs/utils/get-selection-range-in-row.js +6 -27
- package/dist/cjs/utils/get-selection-rect.js +0 -7
- package/dist/cjs/utils/go-to-next-cell.js +3 -22
- package/dist/cjs/utils/handle-paste.js +5 -34
- package/dist/cjs/utils/is-selected.js +6 -23
- package/dist/cjs/utils/is-selection-type.js +0 -2
- package/dist/cjs/utils/move-column.js +0 -12
- package/dist/cjs/utils/move-row.js +0 -11
- package/dist/cjs/utils/normalize-selection.js +3 -27
- package/dist/cjs/utils/remove-column.js +10 -46
- package/dist/cjs/utils/remove-row.js +8 -49
- package/dist/cjs/utils/remove-table.js +0 -6
- package/dist/cjs/utils/reorder-utils.js +13 -37
- package/dist/cjs/utils/replace-table.js +0 -8
- package/dist/cjs/utils/select-nodes.js +11 -31
- package/dist/cjs/utils/selection-cell.js +0 -5
- package/dist/cjs/utils/selection-rect.js +0 -10
- package/dist/cjs/utils/set-cell-attrs.js +0 -4
- package/dist/cjs/utils/split-cell-with-type.js +2 -35
- package/dist/cjs/utils/split-cell.js +0 -4
- package/dist/cjs/utils/table-node-types.js +4 -8
- package/dist/cjs/utils/tables.js +0 -4
- package/dist/cjs/utils/test-utils.js +9 -26
- package/dist/cjs/utils/toggle-header.js +3 -16
- package/dist/cjs/utils/uuid.js +0 -3
- package/dist/cjs/utils.js +0 -42
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/cell-bookmark.js +0 -5
- package/dist/es2019/cell-selection.js +37 -81
- package/dist/es2019/index.js +1 -0
- package/dist/es2019/pm-plugins/input.js +15 -67
- package/dist/es2019/pm-plugins/table-editing.js +3 -12
- package/dist/es2019/table-map.js +57 -127
- package/dist/es2019/utils/add-column-at.js +2 -4
- package/dist/es2019/utils/add-column.js +6 -16
- package/dist/es2019/utils/add-row-at.js +8 -22
- package/dist/es2019/utils/add-row.js +2 -17
- package/dist/es2019/utils/analytics-helpers.js +0 -5
- package/dist/es2019/utils/cells.js +4 -9
- package/dist/es2019/utils/colspan.js +6 -11
- package/dist/es2019/utils/copy-paste.js +41 -115
- package/dist/es2019/utils/create-table.js +3 -12
- package/dist/es2019/utils/draw-cell-selection.js +0 -1
- package/dist/es2019/utils/empty-cells.js +2 -3
- package/dist/es2019/utils/find.js +8 -8
- package/dist/es2019/utils/fix-tables.js +17 -47
- package/dist/es2019/utils/for-each-cell.js +6 -11
- package/dist/es2019/utils/get-cell-selection-ranges.js +2 -4
- package/dist/es2019/utils/get-cells-in-column.js +2 -3
- package/dist/es2019/utils/get-cells-in-row.js +2 -3
- package/dist/es2019/utils/get-cells-in-table.js +2 -4
- package/dist/es2019/utils/get-selection-range-in-column.js +8 -22
- package/dist/es2019/utils/get-selection-range-in-row.js +8 -22
- package/dist/es2019/utils/get-selection-rect.js +2 -2
- package/dist/es2019/utils/go-to-next-cell.js +3 -19
- package/dist/es2019/utils/handle-paste.js +3 -14
- package/dist/es2019/utils/is-selected.js +8 -10
- package/dist/es2019/utils/is-selection-type.js +0 -1
- package/dist/es2019/utils/move-column.js +3 -8
- package/dist/es2019/utils/move-row.js +3 -7
- package/dist/es2019/utils/normalize-selection.js +0 -16
- package/dist/es2019/utils/remove-column.js +10 -27
- package/dist/es2019/utils/remove-row.js +12 -32
- package/dist/es2019/utils/remove-table.js +2 -4
- package/dist/es2019/utils/reorder-utils.js +11 -26
- package/dist/es2019/utils/replace-table.js +0 -2
- package/dist/es2019/utils/select-nodes.js +9 -20
- package/dist/es2019/utils/selection-cell.js +0 -2
- package/dist/es2019/utils/selection-rect.js +0 -4
- package/dist/es2019/utils/set-cell-attrs.js +2 -2
- package/dist/es2019/utils/split-cell-with-type.js +8 -28
- package/dist/es2019/utils/split-cell.js +3 -2
- package/dist/es2019/utils/table-node-types.js +4 -7
- package/dist/es2019/utils/tables.js +0 -2
- package/dist/es2019/utils/test-utils.js +12 -16
- package/dist/es2019/utils/toggle-header.js +3 -10
- package/dist/es2019/utils/uuid.js +0 -2
- package/dist/es2019/version.json +1 -1
- package/dist/esm/cell-bookmark.js +0 -5
- package/dist/esm/cell-selection.js +37 -79
- package/dist/esm/index.js +1 -0
- package/dist/esm/pm-plugins/input.js +17 -71
- package/dist/esm/pm-plugins/table-editing.js +8 -13
- package/dist/esm/table-map.js +68 -133
- package/dist/esm/utils/add-column-at.js +2 -4
- package/dist/esm/utils/add-column.js +8 -20
- package/dist/esm/utils/add-row-at.js +8 -23
- package/dist/esm/utils/add-row.js +2 -21
- package/dist/esm/utils/analytics-helpers.js +4 -10
- package/dist/esm/utils/cells.js +0 -5
- package/dist/esm/utils/colspan.js +2 -14
- package/dist/esm/utils/copy-paste.js +44 -125
- package/dist/esm/utils/create-table.js +14 -25
- package/dist/esm/utils/draw-cell-selection.js +0 -1
- package/dist/esm/utils/empty-cells.js +2 -3
- package/dist/esm/utils/find.js +8 -8
- package/dist/esm/utils/fix-tables.js +13 -49
- package/dist/esm/utils/for-each-cell.js +6 -11
- package/dist/esm/utils/get-cell-selection-ranges.js +2 -4
- package/dist/esm/utils/get-cells-in-column.js +2 -3
- package/dist/esm/utils/get-cells-in-row.js +2 -3
- package/dist/esm/utils/get-cells-in-table.js +2 -4
- package/dist/esm/utils/get-selection-range-in-column.js +8 -24
- package/dist/esm/utils/get-selection-range-in-row.js +8 -24
- package/dist/esm/utils/get-selection-rect.js +2 -2
- package/dist/esm/utils/go-to-next-cell.js +3 -19
- package/dist/esm/utils/handle-paste.js +5 -23
- package/dist/esm/utils/is-selected.js +8 -10
- package/dist/esm/utils/is-selection-type.js +0 -1
- package/dist/esm/utils/move-column.js +3 -8
- package/dist/esm/utils/move-row.js +3 -7
- package/dist/esm/utils/normalize-selection.js +3 -22
- package/dist/esm/utils/remove-column.js +10 -31
- package/dist/esm/utils/remove-row.js +8 -35
- package/dist/esm/utils/remove-table.js +2 -4
- package/dist/esm/utils/reorder-utils.js +11 -26
- package/dist/esm/utils/replace-table.js +0 -2
- package/dist/esm/utils/select-nodes.js +11 -22
- package/dist/esm/utils/selection-cell.js +0 -2
- package/dist/esm/utils/selection-rect.js +0 -4
- package/dist/esm/utils/set-cell-attrs.js +2 -2
- package/dist/esm/utils/split-cell-with-type.js +2 -28
- package/dist/esm/utils/split-cell.js +3 -2
- package/dist/esm/utils/table-node-types.js +4 -7
- package/dist/esm/utils/tables.js +0 -2
- package/dist/esm/utils/test-utils.js +12 -16
- package/dist/esm/utils/toggle-header.js +3 -10
- package/dist/esm/version.json +1 -1
- package/package.json +6 -4
|
@@ -2,7 +2,6 @@ import { fixTablesKey } from '../pm-plugins/plugin-key';
|
|
|
2
2
|
import { TableMap, TableProblemTypes } from '../table-map';
|
|
3
3
|
import { removeColSpan } from './colspan';
|
|
4
4
|
import { tableNodeTypes } from './table-node-types';
|
|
5
|
-
|
|
6
5
|
// Helper for iterating through the nodes in a document that changed
|
|
7
6
|
// compared to the given previous document. Useful for avoiding
|
|
8
7
|
// duplicate work on each transaction.
|
|
@@ -10,80 +9,68 @@ function changedDescendants(old, cur, offsetStart, f) {
|
|
|
10
9
|
let offset = offsetStart;
|
|
11
10
|
const oldSize = old.childCount;
|
|
12
11
|
const curSize = cur.childCount;
|
|
13
|
-
|
|
14
12
|
outer: for (let i = 0, j = 0; i < curSize; i++) {
|
|
15
13
|
const child = cur.child(i);
|
|
16
|
-
|
|
17
14
|
for (let scan = j, e = Math.min(oldSize, i + 3); scan < e; scan++) {
|
|
18
15
|
if (old.child(scan) === child) {
|
|
19
16
|
j = scan + 1;
|
|
20
|
-
offset += child.nodeSize;
|
|
21
|
-
|
|
17
|
+
offset += child.nodeSize;
|
|
18
|
+
// eslint-disable-next-line no-continue
|
|
22
19
|
continue outer;
|
|
23
20
|
}
|
|
24
21
|
}
|
|
25
|
-
|
|
26
22
|
f(child, offset);
|
|
27
|
-
|
|
28
23
|
if (j < oldSize && old.child(j).sameMarkup(child)) {
|
|
29
24
|
changedDescendants(old.child(j), child, offset + 1, f);
|
|
30
25
|
} else {
|
|
31
26
|
child.nodesBetween(0, child.content.size, f, offset + 1);
|
|
32
27
|
}
|
|
33
|
-
|
|
34
28
|
offset += child.nodeSize;
|
|
35
29
|
}
|
|
36
|
-
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// :: (EditorState, ?EditorState) → ?Transaction
|
|
37
33
|
// Inspect all tables in the given state's document and return a
|
|
38
34
|
// transaction that fixes them, if necessary. If `oldState` was
|
|
39
35
|
// provided, that is assumed to hold a previous, known-good state,
|
|
40
36
|
// which will be used to avoid re-scanning unchanged parts of the
|
|
41
37
|
// document.
|
|
42
|
-
|
|
43
|
-
|
|
44
38
|
export function fixTables(state, oldState, reportFixedTable) {
|
|
45
39
|
let tr;
|
|
46
|
-
|
|
47
40
|
const check = (node, pos) => {
|
|
48
41
|
if (node.type.spec.tableRole === 'table') {
|
|
49
42
|
tr = fixTable(state, node, pos, tr, reportFixedTable);
|
|
50
43
|
}
|
|
51
44
|
};
|
|
52
|
-
|
|
53
45
|
if (!oldState) {
|
|
54
46
|
state.doc.descendants(check);
|
|
55
47
|
} else if (oldState.doc !== state.doc) {
|
|
56
48
|
changedDescendants(oldState.doc, state.doc, 0, check);
|
|
57
49
|
}
|
|
58
|
-
|
|
59
50
|
return tr;
|
|
60
|
-
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// : (EditorState, Node, number, ?Transaction) → ?Transaction
|
|
61
54
|
// Fix the given table, if necessary. Will append to the transaction
|
|
62
55
|
// it was given, if non-null, or create a new one if necessary.
|
|
63
|
-
|
|
64
56
|
export function fixTable(state, table, tablePos, transaction, reportFixedTable) {
|
|
65
57
|
let tr = transaction;
|
|
66
58
|
const map = TableMap.get(table);
|
|
67
|
-
|
|
68
59
|
if (!map.problems) {
|
|
69
60
|
return tr;
|
|
70
61
|
}
|
|
71
|
-
|
|
72
62
|
if (!tr) {
|
|
73
63
|
tr = state.tr;
|
|
74
|
-
}
|
|
75
|
-
// when fixing collisions.
|
|
76
|
-
|
|
64
|
+
}
|
|
77
65
|
|
|
66
|
+
// Track which rows we must add cells to, so that we can adjust that
|
|
67
|
+
// when fixing collisions.
|
|
78
68
|
const mustAdd = [];
|
|
79
|
-
|
|
80
69
|
for (let i = 0; i < map.height; i++) {
|
|
81
70
|
mustAdd.push(0);
|
|
82
71
|
}
|
|
83
|
-
|
|
84
72
|
for (let i = 0; i < map.problems.length; i++) {
|
|
85
73
|
const prob = map.problems[i];
|
|
86
|
-
|
|
87
74
|
if (reportFixedTable) {
|
|
88
75
|
reportFixedTable({
|
|
89
76
|
state,
|
|
@@ -91,19 +78,15 @@ export function fixTable(state, table, tablePos, transaction, reportFixedTable)
|
|
|
91
78
|
reason: prob.type || 'unknown'
|
|
92
79
|
});
|
|
93
80
|
}
|
|
94
|
-
|
|
95
81
|
if (prob.type === TableProblemTypes.COLLISION) {
|
|
96
82
|
const collision = prob;
|
|
97
83
|
const cell = table.nodeAt(prob.pos);
|
|
98
|
-
|
|
99
84
|
if (!cell) {
|
|
100
85
|
throw new Error(`fixTable: unable to find cell at pos ${prob.pos}`);
|
|
101
86
|
}
|
|
102
|
-
|
|
103
87
|
for (let j = 0; j < cell.attrs.rowspan; j++) {
|
|
104
88
|
mustAdd[collision.row + j] += collision.n;
|
|
105
89
|
}
|
|
106
|
-
|
|
107
90
|
tr.setNodeMarkup(tr.mapping.map(tablePos + 1 + prob.pos), undefined, removeColSpan(cell.attrs, cell.attrs.colspan - collision.n, collision.n));
|
|
108
91
|
} else if (prob.type === TableProblemTypes.MISSING) {
|
|
109
92
|
const missing = prob;
|
|
@@ -111,69 +94,56 @@ export function fixTable(state, table, tablePos, transaction, reportFixedTable)
|
|
|
111
94
|
} else if (prob.type === TableProblemTypes.OVERLONG_ROWSPAN) {
|
|
112
95
|
const overlong = prob;
|
|
113
96
|
const cell = table.nodeAt(overlong.pos);
|
|
114
|
-
|
|
115
97
|
if (!cell) {
|
|
116
98
|
throw new Error(`fixTable: unable to find cell at pos ${prob.pos}`);
|
|
117
99
|
}
|
|
118
|
-
|
|
119
|
-
|
|
100
|
+
tr.setNodeMarkup(tr.mapping.map(tablePos + 1 + overlong.pos), undefined, {
|
|
101
|
+
...cell.attrs,
|
|
120
102
|
rowspan: cell.attrs.rowspan - overlong.n
|
|
121
103
|
});
|
|
122
104
|
} else if (prob.type === TableProblemTypes.COLWIDTH_MISMATCH) {
|
|
123
105
|
const cell = table.nodeAt(prob.pos);
|
|
124
|
-
|
|
125
106
|
if (!cell) {
|
|
126
107
|
throw new Error(`fixTable: unable to find cell at pos ${prob.pos}`);
|
|
127
108
|
}
|
|
128
|
-
|
|
129
|
-
|
|
109
|
+
tr.setNodeMarkup(tr.mapping.map(tablePos + 1 + prob.pos), undefined, {
|
|
110
|
+
...cell.attrs,
|
|
130
111
|
colwidth: prob.colwidth
|
|
131
112
|
});
|
|
132
113
|
}
|
|
133
114
|
}
|
|
134
|
-
|
|
135
115
|
let first;
|
|
136
116
|
let last;
|
|
137
|
-
|
|
138
117
|
for (let i = 0; i < mustAdd.length; i++) {
|
|
139
118
|
if (mustAdd[i]) {
|
|
140
119
|
if (first == null) {
|
|
141
120
|
first = i;
|
|
142
121
|
}
|
|
143
|
-
|
|
144
122
|
last = i;
|
|
145
123
|
}
|
|
146
|
-
}
|
|
124
|
+
}
|
|
125
|
+
// Add the necessary cells, using a heuristic for whether to add the
|
|
147
126
|
// cells at the start or end of the rows (if it looks like a 'bite'
|
|
148
127
|
// was taken out of the table, add cells at the start of the row
|
|
149
128
|
// after the bite. Otherwise add them at the end).
|
|
150
|
-
|
|
151
|
-
|
|
152
129
|
for (let i = 0, pos = tablePos + 1; i < map.height; i++) {
|
|
153
130
|
const row = table.child(i);
|
|
154
131
|
const end = pos + row.nodeSize;
|
|
155
132
|
const add = mustAdd[i];
|
|
156
|
-
|
|
157
133
|
if (add > 0) {
|
|
158
134
|
let tableNodeType = 'cell';
|
|
159
|
-
|
|
160
135
|
if (row.firstChild) {
|
|
161
136
|
tableNodeType = row.firstChild.type.spec.tableRole;
|
|
162
137
|
}
|
|
163
|
-
|
|
164
138
|
const nodes = [];
|
|
165
|
-
|
|
166
139
|
for (let j = 0; j < add; j++) {
|
|
167
140
|
nodes.push(tableNodeTypes(state.schema)[tableNodeType].createAndFill());
|
|
168
141
|
}
|
|
169
|
-
|
|
170
142
|
const side = (i === 0 || first === i - 1) && last === i ? pos + 1 : end - 1;
|
|
171
143
|
tr.insert(tr.mapping.map(side), nodes);
|
|
172
144
|
}
|
|
173
|
-
|
|
174
145
|
pos = end;
|
|
175
146
|
}
|
|
176
|
-
|
|
177
147
|
return tr.setMeta(fixTablesKey, {
|
|
178
148
|
fixTables: true
|
|
179
149
|
});
|
|
@@ -1,42 +1,37 @@
|
|
|
1
1
|
import { Selection } from 'prosemirror-state';
|
|
2
2
|
import { cloneTr } from './clone-tr';
|
|
3
3
|
import { getCellsInColumn } from './get-cells-in-column';
|
|
4
|
-
import { getCellsInRow } from './get-cells-in-row';
|
|
5
|
-
// It will set the selection into the last cell of the column if `setCursorToLastCell` param is set to `true`.
|
|
4
|
+
import { getCellsInRow } from './get-cells-in-row';
|
|
6
5
|
|
|
6
|
+
// Returns a new transaction that maps a given `cellTransform` function to each cell in a column at a given `columnIndex`.
|
|
7
|
+
// It will set the selection into the last cell of the column if `setCursorToLastCell` param is set to `true`.
|
|
7
8
|
export const forEachCellInColumn = (columnIndex, cellTransform, setCursorToLastCell) => tr => {
|
|
8
9
|
const cells = getCellsInColumn(columnIndex)(tr.selection);
|
|
9
|
-
|
|
10
10
|
if (cells) {
|
|
11
11
|
for (let i = cells.length - 1; i >= 0; i--) {
|
|
12
12
|
tr = cellTransform(cells[i], tr);
|
|
13
13
|
}
|
|
14
|
-
|
|
15
14
|
if (setCursorToLastCell) {
|
|
16
15
|
const $pos = tr.doc.resolve(tr.mapping.map(cells[cells.length - 1].pos));
|
|
17
16
|
tr.setSelection(Selection.near($pos));
|
|
18
17
|
}
|
|
19
|
-
|
|
20
18
|
return cloneTr(tr);
|
|
21
19
|
}
|
|
22
|
-
|
|
23
20
|
return tr;
|
|
24
|
-
};
|
|
25
|
-
// It will set the selection into the last cell of the row if `setCursorToLastCell` param is set to `true`.
|
|
21
|
+
};
|
|
26
22
|
|
|
23
|
+
// Returns a new transaction that maps a given `cellTransform` function to each cell in a row at a given `rowIndex`.
|
|
24
|
+
// It will set the selection into the last cell of the row if `setCursorToLastCell` param is set to `true`.
|
|
27
25
|
export const forEachCellInRow = (rowIndex, cellTransform, setCursorToLastCell) => tr => {
|
|
28
26
|
const cells = getCellsInRow(rowIndex)(tr.selection);
|
|
29
|
-
|
|
30
27
|
if (cells) {
|
|
31
28
|
for (let i = cells.length - 1; i >= 0; i--) {
|
|
32
29
|
tr = cellTransform(cells[i], tr);
|
|
33
30
|
}
|
|
34
|
-
|
|
35
31
|
if (setCursorToLastCell) {
|
|
36
32
|
const $pos = tr.doc.resolve(tr.mapping.map(cells[cells.length - 1].pos));
|
|
37
33
|
tr.setSelection(Selection.near($pos));
|
|
38
34
|
}
|
|
39
35
|
}
|
|
40
|
-
|
|
41
36
|
return tr;
|
|
42
37
|
};
|
|
@@ -6,17 +6,15 @@ export function getCellSelectionRanges($anchorCell, $headCell) {
|
|
|
6
6
|
const start = $anchorCell.start(-1);
|
|
7
7
|
const rect = map.rectBetween($anchorCell.pos - start, $headCell.pos - start);
|
|
8
8
|
const doc = $anchorCell.node(0);
|
|
9
|
-
const cells = map.cellsInRect(rect).filter(p => p !== $headCell.pos - start);
|
|
9
|
+
const cells = map.cellsInRect(rect).filter(p => p !== $headCell.pos - start);
|
|
10
|
+
// Make the head cell the first range, so that it counts as the
|
|
10
11
|
// primary part of the selection
|
|
11
|
-
|
|
12
12
|
cells.unshift($headCell.pos - start);
|
|
13
13
|
return cells.map(pos => {
|
|
14
14
|
const cell = table.nodeAt(pos);
|
|
15
|
-
|
|
16
15
|
if (cell === null) {
|
|
17
16
|
throw new Error(`No cell at position ${pos}`);
|
|
18
17
|
}
|
|
19
|
-
|
|
20
18
|
const from = pos + start + 1;
|
|
21
19
|
return new SelectionRange(doc.resolve(from), doc.resolve(from + cell.content.size));
|
|
22
20
|
});
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { TableMap } from '../table-map';
|
|
2
|
-
import { findTable } from './find';
|
|
2
|
+
import { findTable } from './find';
|
|
3
3
|
|
|
4
|
+
// Returns an array of cells in a column(s), where `columnIndex` could be a column index or an array of column indexes.
|
|
4
5
|
export const getCellsInColumn = columnIndexes => selection => {
|
|
5
6
|
const table = findTable(selection);
|
|
6
|
-
|
|
7
7
|
if (!table) {
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
10
|
const map = TableMap.get(table.node);
|
|
12
11
|
const indexes = Array.isArray(columnIndexes) ? columnIndexes : [columnIndexes];
|
|
13
12
|
return indexes.filter(index => index >= 0 && index <= map.width - 1).reduce((acc, index) => {
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { TableMap } from '../table-map';
|
|
2
|
-
import { findTable } from './find';
|
|
2
|
+
import { findTable } from './find';
|
|
3
3
|
|
|
4
|
+
// Returns an array of cells in a row(s), where `rowIndex` could be a row index or an array of row indexes.
|
|
4
5
|
export const getCellsInRow = rowIndex => selection => {
|
|
5
6
|
const table = findTable(selection);
|
|
6
|
-
|
|
7
7
|
if (!table) {
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
10
|
const map = TableMap.get(table.node);
|
|
12
11
|
const indexes = Array.isArray(rowIndex) ? rowIndex : [rowIndex];
|
|
13
12
|
return indexes.filter(index => index >= 0 && index <= map.height - 1).reduce((acc, index) => {
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { TableMap } from '../table-map';
|
|
2
|
-
import { findTable } from './find';
|
|
2
|
+
import { findTable } from './find';
|
|
3
3
|
|
|
4
|
+
// Returns an array of all cells in a table.
|
|
4
5
|
export const getCellsInTable = selection => {
|
|
5
6
|
const table = findTable(selection);
|
|
6
|
-
|
|
7
7
|
if (!table) {
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
10
|
const map = TableMap.get(table.node);
|
|
12
11
|
const positions = map.cellsInRect({
|
|
13
12
|
left: 0,
|
|
@@ -17,7 +16,6 @@ export const getCellsInTable = selection => {
|
|
|
17
16
|
});
|
|
18
17
|
return positions.map(cellPos => {
|
|
19
18
|
const node = table.node.nodeAt(cellPos);
|
|
20
|
-
|
|
21
19
|
if (node) {
|
|
22
20
|
const pos = cellPos + table.start;
|
|
23
21
|
return {
|
|
@@ -1,69 +1,58 @@
|
|
|
1
1
|
import { getCellsInColumn } from './get-cells-in-column';
|
|
2
|
-
import { getCellsInRow } from './get-cells-in-row';
|
|
2
|
+
import { getCellsInRow } from './get-cells-in-row';
|
|
3
3
|
|
|
4
|
+
// Returns a range of rectangular selection spanning all merged cells around a column at index `columnIndex`.
|
|
4
5
|
export const getSelectionRangeInColumn = columnIndex => tr => {
|
|
5
6
|
let startIndex = columnIndex;
|
|
6
|
-
let endIndex = columnIndex;
|
|
7
|
+
let endIndex = columnIndex;
|
|
7
8
|
|
|
9
|
+
// looking for selection start column (startIndex)
|
|
8
10
|
for (let i = columnIndex; i >= 0; i--) {
|
|
9
11
|
const cells = getCellsInColumn(i)(tr.selection);
|
|
10
|
-
|
|
11
12
|
if (cells) {
|
|
12
13
|
cells.forEach(cell => {
|
|
13
14
|
let maybeEndIndex = cell.node.attrs.colspan + i - 1;
|
|
14
|
-
|
|
15
15
|
if (maybeEndIndex >= startIndex) {
|
|
16
16
|
startIndex = i;
|
|
17
17
|
}
|
|
18
|
-
|
|
19
18
|
if (maybeEndIndex > endIndex) {
|
|
20
19
|
endIndex = maybeEndIndex;
|
|
21
20
|
}
|
|
22
21
|
});
|
|
23
22
|
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
}
|
|
24
|
+
// looking for selection end column (endIndex)
|
|
27
25
|
for (let i = columnIndex; i <= endIndex; i++) {
|
|
28
26
|
const cells = getCellsInColumn(i)(tr.selection);
|
|
29
|
-
|
|
30
27
|
if (cells) {
|
|
31
28
|
cells.forEach(cell => {
|
|
32
29
|
let maybeEndIndex = cell.node.attrs.colspan + i - 1;
|
|
33
|
-
|
|
34
30
|
if (cell.node.attrs.colspan > 1 && maybeEndIndex > endIndex) {
|
|
35
31
|
endIndex = maybeEndIndex;
|
|
36
32
|
}
|
|
37
33
|
});
|
|
38
34
|
}
|
|
39
|
-
}
|
|
40
|
-
|
|
35
|
+
}
|
|
41
36
|
|
|
37
|
+
// filter out columns without cells (where all rows have colspan > 1 in the same column)
|
|
42
38
|
const indexes = [];
|
|
43
|
-
|
|
44
39
|
for (let i = startIndex; i <= endIndex; i++) {
|
|
45
40
|
const maybeCells = getCellsInColumn(i)(tr.selection);
|
|
46
|
-
|
|
47
41
|
if (maybeCells && maybeCells.length) {
|
|
48
42
|
indexes.push(i);
|
|
49
43
|
}
|
|
50
44
|
}
|
|
51
|
-
|
|
52
45
|
startIndex = indexes[0];
|
|
53
46
|
endIndex = indexes[indexes.length - 1];
|
|
54
47
|
const firstSelectedColumnCells = getCellsInColumn(startIndex)(tr.selection);
|
|
55
48
|
const firstRowCells = getCellsInRow(0)(tr.selection);
|
|
56
|
-
|
|
57
49
|
if (!firstSelectedColumnCells || !firstRowCells) {
|
|
58
50
|
return;
|
|
59
51
|
}
|
|
60
|
-
|
|
61
52
|
const $anchor = tr.doc.resolve(firstSelectedColumnCells[firstSelectedColumnCells.length - 1].pos);
|
|
62
53
|
let headCell;
|
|
63
|
-
|
|
64
54
|
for (let i = endIndex; i >= startIndex; i--) {
|
|
65
55
|
const columnCells = getCellsInColumn(i)(tr.selection);
|
|
66
|
-
|
|
67
56
|
if (columnCells && columnCells.length) {
|
|
68
57
|
for (let j = firstRowCells.length - 1; j >= 0; j--) {
|
|
69
58
|
if (firstRowCells[j].pos === columnCells[0].pos) {
|
|
@@ -71,17 +60,14 @@ export const getSelectionRangeInColumn = columnIndex => tr => {
|
|
|
71
60
|
break;
|
|
72
61
|
}
|
|
73
62
|
}
|
|
74
|
-
|
|
75
63
|
if (headCell) {
|
|
76
64
|
break;
|
|
77
65
|
}
|
|
78
66
|
}
|
|
79
67
|
}
|
|
80
|
-
|
|
81
68
|
if (!headCell) {
|
|
82
69
|
return;
|
|
83
70
|
}
|
|
84
|
-
|
|
85
71
|
const $head = tr.doc.resolve(headCell.pos);
|
|
86
72
|
return {
|
|
87
73
|
$anchor,
|
|
@@ -1,69 +1,58 @@
|
|
|
1
1
|
import { getCellsInColumn } from './get-cells-in-column';
|
|
2
|
-
import { getCellsInRow } from './get-cells-in-row';
|
|
2
|
+
import { getCellsInRow } from './get-cells-in-row';
|
|
3
3
|
|
|
4
|
+
// Returns a range of rectangular selection spanning all merged cells around a row at index `rowIndex`.
|
|
4
5
|
export const getSelectionRangeInRow = rowIndex => tr => {
|
|
5
6
|
let startIndex = rowIndex;
|
|
6
|
-
let endIndex = rowIndex;
|
|
7
|
+
let endIndex = rowIndex;
|
|
7
8
|
|
|
9
|
+
// looking for selection start row (startIndex)
|
|
8
10
|
for (let i = rowIndex; i >= 0; i--) {
|
|
9
11
|
const cells = getCellsInRow(i)(tr.selection);
|
|
10
|
-
|
|
11
12
|
if (cells) {
|
|
12
13
|
cells.forEach(cell => {
|
|
13
14
|
let maybeEndIndex = cell.node.attrs.rowspan + i - 1;
|
|
14
|
-
|
|
15
15
|
if (maybeEndIndex >= startIndex) {
|
|
16
16
|
startIndex = i;
|
|
17
17
|
}
|
|
18
|
-
|
|
19
18
|
if (maybeEndIndex > endIndex) {
|
|
20
19
|
endIndex = maybeEndIndex;
|
|
21
20
|
}
|
|
22
21
|
});
|
|
23
22
|
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
}
|
|
24
|
+
// looking for selection end row (endIndex)
|
|
27
25
|
for (let i = rowIndex; i <= endIndex; i++) {
|
|
28
26
|
const cells = getCellsInRow(i)(tr.selection);
|
|
29
|
-
|
|
30
27
|
if (cells) {
|
|
31
28
|
cells.forEach(cell => {
|
|
32
29
|
let maybeEndIndex = cell.node.attrs.rowspan + i - 1;
|
|
33
|
-
|
|
34
30
|
if (cell.node.attrs.rowspan > 1 && maybeEndIndex > endIndex) {
|
|
35
31
|
endIndex = maybeEndIndex;
|
|
36
32
|
}
|
|
37
33
|
});
|
|
38
34
|
}
|
|
39
|
-
}
|
|
40
|
-
|
|
35
|
+
}
|
|
41
36
|
|
|
37
|
+
// filter out rows without cells (where all columns have rowspan > 1 in the same row)
|
|
42
38
|
const indexes = [];
|
|
43
|
-
|
|
44
39
|
for (let i = startIndex; i <= endIndex; i++) {
|
|
45
40
|
const maybeCells = getCellsInRow(i)(tr.selection);
|
|
46
|
-
|
|
47
41
|
if (maybeCells && maybeCells.length) {
|
|
48
42
|
indexes.push(i);
|
|
49
43
|
}
|
|
50
44
|
}
|
|
51
|
-
|
|
52
45
|
startIndex = indexes[0];
|
|
53
46
|
endIndex = indexes[indexes.length - 1];
|
|
54
47
|
const firstSelectedRowCells = getCellsInRow(startIndex)(tr.selection);
|
|
55
48
|
const firstColumnCells = getCellsInColumn(0)(tr.selection);
|
|
56
|
-
|
|
57
49
|
if (!firstSelectedRowCells || !firstColumnCells) {
|
|
58
50
|
return;
|
|
59
51
|
}
|
|
60
|
-
|
|
61
52
|
const $anchor = tr.doc.resolve(firstSelectedRowCells[firstSelectedRowCells.length - 1].pos);
|
|
62
53
|
let headCell;
|
|
63
|
-
|
|
64
54
|
for (let i = endIndex; i >= startIndex; i--) {
|
|
65
55
|
const rowCells = getCellsInRow(i)(tr.selection);
|
|
66
|
-
|
|
67
56
|
if (rowCells && rowCells.length) {
|
|
68
57
|
for (let j = firstColumnCells.length - 1; j >= 0; j--) {
|
|
69
58
|
if (firstColumnCells[j].pos === rowCells[0].pos) {
|
|
@@ -71,17 +60,14 @@ export const getSelectionRangeInRow = rowIndex => tr => {
|
|
|
71
60
|
break;
|
|
72
61
|
}
|
|
73
62
|
}
|
|
74
|
-
|
|
75
63
|
if (headCell) {
|
|
76
64
|
break;
|
|
77
65
|
}
|
|
78
66
|
}
|
|
79
67
|
}
|
|
80
|
-
|
|
81
68
|
if (!headCell) {
|
|
82
69
|
return;
|
|
83
70
|
}
|
|
84
|
-
|
|
85
71
|
const $head = tr.doc.resolve(headCell.pos);
|
|
86
72
|
return {
|
|
87
73
|
$anchor,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { TableMap } from '../table-map';
|
|
2
|
-
import { isSelectionType } from './is-selection-type';
|
|
2
|
+
import { isSelectionType } from './is-selection-type';
|
|
3
3
|
|
|
4
|
+
// Get the selection rectangle. Returns `undefined` if selection is not a CellSelection.
|
|
4
5
|
export const getSelectionRect = selection => {
|
|
5
6
|
if (!isSelectionType(selection, 'cell')) {
|
|
6
7
|
return;
|
|
7
8
|
}
|
|
8
|
-
|
|
9
9
|
const start = selection.$anchorCell.start(-1);
|
|
10
10
|
const map = TableMap.get(selection.$anchorCell.node(-1));
|
|
11
11
|
return map.rectBetween(selection.$anchorCell.pos - start, selection.$headCell.pos - start);
|
|
@@ -1,72 +1,56 @@
|
|
|
1
1
|
import { TextSelection } from 'prosemirror-state';
|
|
2
2
|
import { selectionCell } from './selection-cell';
|
|
3
3
|
import { isInTable } from './tables';
|
|
4
|
-
|
|
5
4
|
function moveCellForward($pos) {
|
|
6
5
|
const nextNodeSize = $pos.nodeAfter ? $pos.nodeAfter.nodeSize : 0;
|
|
7
6
|
return $pos.node(0).resolve($pos.pos + nextNodeSize);
|
|
8
|
-
}
|
|
9
|
-
// (direction=-1) cell in a table.
|
|
10
|
-
|
|
7
|
+
}
|
|
11
8
|
|
|
9
|
+
// Returns a command for selecting the next (direction=1) or previous
|
|
10
|
+
// (direction=-1) cell in a table.
|
|
12
11
|
export function goToNextCell(direction) {
|
|
13
12
|
return function (state, dispatch) {
|
|
14
13
|
if (!isInTable(state)) {
|
|
15
14
|
return false;
|
|
16
15
|
}
|
|
17
|
-
|
|
18
16
|
const cellSelection = selectionCell(state.selection);
|
|
19
|
-
|
|
20
17
|
if (!cellSelection) {
|
|
21
18
|
return false;
|
|
22
19
|
}
|
|
23
|
-
|
|
24
20
|
const cell = findNextCell(cellSelection, direction);
|
|
25
|
-
|
|
26
21
|
if (cell === undefined) {
|
|
27
22
|
return false;
|
|
28
23
|
}
|
|
29
|
-
|
|
30
24
|
if (dispatch) {
|
|
31
25
|
const $cell = state.doc.resolve(cell);
|
|
32
26
|
dispatch(state.tr.setSelection(TextSelection.between($cell, moveCellForward($cell))).scrollIntoView());
|
|
33
27
|
}
|
|
34
|
-
|
|
35
28
|
return true;
|
|
36
29
|
};
|
|
37
30
|
}
|
|
38
|
-
|
|
39
31
|
function findNextCell($cell, direction) {
|
|
40
32
|
if (direction === -1) {
|
|
41
33
|
const before = $cell.nodeBefore;
|
|
42
|
-
|
|
43
34
|
if (before) {
|
|
44
35
|
return $cell.pos - before.nodeSize;
|
|
45
36
|
}
|
|
46
|
-
|
|
47
37
|
for (let row = $cell.index(-1) - 1, rowEnd = $cell.before(); row >= 0; row--) {
|
|
48
38
|
const rowNode = $cell.node(-1).child(row);
|
|
49
|
-
|
|
50
39
|
if (rowNode.childCount && rowNode.lastChild) {
|
|
51
40
|
return rowEnd - 1 - rowNode.lastChild.nodeSize;
|
|
52
41
|
}
|
|
53
|
-
|
|
54
42
|
rowEnd -= rowNode.nodeSize;
|
|
55
43
|
}
|
|
56
44
|
} else {
|
|
57
45
|
if ($cell.index() < $cell.parent.childCount - 1 && $cell.nodeAfter) {
|
|
58
46
|
return $cell.pos + $cell.nodeAfter.nodeSize;
|
|
59
47
|
}
|
|
60
|
-
|
|
61
48
|
const table = $cell.node(-1);
|
|
62
|
-
|
|
63
49
|
for (let row = $cell.indexAfter(-1), rowStart = $cell.after(); row < table.childCount; row++) {
|
|
64
50
|
const rowNode = table.child(row);
|
|
65
|
-
|
|
66
51
|
if (rowNode.childCount) {
|
|
67
52
|
return rowStart + 1;
|
|
68
53
|
}
|
|
69
|
-
|
|
70
54
|
rowStart += rowNode.nodeSize;
|
|
71
55
|
}
|
|
72
56
|
}
|
|
@@ -9,10 +9,8 @@ export function handlePaste(view, event, slice) {
|
|
|
9
9
|
if (!isInTable(view.state)) {
|
|
10
10
|
return false;
|
|
11
11
|
}
|
|
12
|
-
|
|
13
12
|
let cells = pastedCells(slice);
|
|
14
13
|
const sel = view.state.selection;
|
|
15
|
-
|
|
16
14
|
if (sel instanceof CellSelection) {
|
|
17
15
|
if (!cells) {
|
|
18
16
|
cells = {
|
|
@@ -21,7 +19,6 @@ export function handlePaste(view, event, slice) {
|
|
|
21
19
|
rows: [Fragment.from(fitSlice(tableNodeTypes(view.state.schema).cell, slice))]
|
|
22
20
|
};
|
|
23
21
|
}
|
|
24
|
-
|
|
25
22
|
const table = sel.$anchorCell.node(-1);
|
|
26
23
|
const start = sel.$anchorCell.start(-1);
|
|
27
24
|
const tableMap = TableMap.get(table);
|
|
@@ -30,37 +27,31 @@ export function handlePaste(view, event, slice) {
|
|
|
30
27
|
insertCells(view.state, view.dispatch, start, rect, clearColumnWidthOfCells(cells, rect, tableMap));
|
|
31
28
|
return true;
|
|
32
29
|
}
|
|
33
|
-
|
|
34
30
|
if (cells) {
|
|
35
31
|
const $cell = selectionCell(sel);
|
|
36
|
-
|
|
37
32
|
if (!$cell) {
|
|
38
33
|
throw new Error(`handlePaste: no cell found`);
|
|
39
34
|
}
|
|
40
|
-
|
|
41
35
|
const start = $cell.start(-1);
|
|
42
36
|
const rect = TableMap.get($cell.node(-1)).findCell($cell.pos - start);
|
|
43
37
|
const tableMap = TableMap.get($cell.node(-1));
|
|
44
38
|
insertCells(view.state, view.dispatch, start, rect, clearColumnWidthOfCells(cells, rect, tableMap));
|
|
45
39
|
return true;
|
|
46
40
|
}
|
|
47
|
-
|
|
48
41
|
return false;
|
|
49
|
-
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Clear the pasted cells column widths so that it maintains
|
|
50
45
|
// the column widths of the destination table only if the pasted
|
|
51
46
|
// cells overlap with existing cells in the destination table.
|
|
52
47
|
// If the table grows on paste, keep the column widhts of the
|
|
53
48
|
// original table.
|
|
54
|
-
|
|
55
49
|
const clearColumnWidthOfCells = (cells, rect, table) => {
|
|
56
50
|
const overlappingCells = [];
|
|
57
|
-
|
|
58
51
|
for (const row of cells.rows) {
|
|
59
52
|
let colNum = rect.left;
|
|
60
|
-
|
|
61
53
|
for (let index = 0; index < row.childCount; index++) {
|
|
62
54
|
const cell = row.child(index);
|
|
63
|
-
|
|
64
55
|
if (colNum + cell.attrs.colspan <= table.width) {
|
|
65
56
|
overlappingCells.push(cell);
|
|
66
57
|
colNum += cell.attrs.colspan;
|
|
@@ -69,10 +60,8 @@ const clearColumnWidthOfCells = (cells, rect, table) => {
|
|
|
69
60
|
}
|
|
70
61
|
}
|
|
71
62
|
}
|
|
72
|
-
|
|
73
63
|
for (const cell of overlappingCells) {
|
|
74
64
|
cell.attrs.colwidth = null;
|
|
75
65
|
}
|
|
76
|
-
|
|
77
66
|
return cells;
|
|
78
67
|
};
|