@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
|
@@ -4,7 +4,9 @@ import { drawCellSelection } from '../utils/draw-cell-selection';
|
|
|
4
4
|
import { fixTables } from '../utils/fix-tables';
|
|
5
5
|
import { normalizeSelection } from '../utils/normalize-selection';
|
|
6
6
|
import { handleKeyDown, handleMouseDown, handleTripleClick } from './input';
|
|
7
|
-
import { tableEditingKey } from './plugin-key';
|
|
7
|
+
import { tableEditingKey } from './plugin-key';
|
|
8
|
+
|
|
9
|
+
// :: () → Plugin
|
|
8
10
|
//
|
|
9
11
|
// Creates a [plugin](http://prosemirror.net/docs/ref/#state.Plugin)
|
|
10
12
|
// that, when added to an editor, enables cell-selection, handles
|
|
@@ -16,7 +18,6 @@ import { tableEditingKey } from './plugin-key'; // :: () → Plugin
|
|
|
16
18
|
// rather broadly, and other plugins, like the gap cursor or the
|
|
17
19
|
// column-width dragging plugin, might want to get a turn first to
|
|
18
20
|
// perform more specific behavior.
|
|
19
|
-
|
|
20
21
|
export function tableEditing({
|
|
21
22
|
allowTableNodeSelection = false,
|
|
22
23
|
reportFixedTable
|
|
@@ -30,49 +31,39 @@ export function tableEditing({
|
|
|
30
31
|
init() {
|
|
31
32
|
return null;
|
|
32
33
|
},
|
|
33
|
-
|
|
34
34
|
apply(unsafeTr, cur) {
|
|
35
35
|
const tr = unsafeTr;
|
|
36
36
|
const set = tr.getMeta(tableEditingKey);
|
|
37
|
-
|
|
38
37
|
if (set != null) {
|
|
39
38
|
return set === -1 ? null : set;
|
|
40
39
|
}
|
|
41
|
-
|
|
42
40
|
if (cur == null || !tr.docChanged) {
|
|
43
41
|
return cur;
|
|
44
42
|
}
|
|
45
|
-
|
|
46
43
|
const {
|
|
47
44
|
deleted,
|
|
48
45
|
pos
|
|
49
46
|
} = tr.mapping.mapResult(cur);
|
|
50
47
|
return deleted ? null : pos;
|
|
51
48
|
}
|
|
52
|
-
|
|
53
49
|
},
|
|
54
50
|
props: {
|
|
55
51
|
decorations: drawCellSelection,
|
|
56
52
|
handleDOMEvents: {
|
|
57
53
|
mousedown: handleMouseDown
|
|
58
54
|
},
|
|
59
|
-
|
|
60
55
|
createSelectionBetween(view) {
|
|
61
56
|
if (tableEditingKey.getState(view.state) != null) {
|
|
62
57
|
return view.state.selection;
|
|
63
58
|
}
|
|
64
|
-
|
|
65
59
|
return null;
|
|
66
60
|
},
|
|
67
|
-
|
|
68
61
|
handleTripleClick,
|
|
69
62
|
handleKeyDown,
|
|
70
63
|
handlePaste
|
|
71
64
|
},
|
|
72
|
-
|
|
73
65
|
appendTransaction(_, oldState, state) {
|
|
74
66
|
return normalizeSelection(state, fixTables(state, oldState, reportFixedTable), allowTableNodeSelection);
|
|
75
67
|
}
|
|
76
|
-
|
|
77
68
|
});
|
|
78
69
|
}
|
package/dist/es2019/table-map.js
CHANGED
|
@@ -8,14 +8,12 @@
|
|
|
8
8
|
// document-relative positions. So code that uses them will typically
|
|
9
9
|
// compute the start position of the table and offset positions passed
|
|
10
10
|
// to or gotten from this structure by that amount.
|
|
11
|
-
let readFromCache, addToCache;
|
|
11
|
+
let readFromCache, addToCache;
|
|
12
|
+
// Prefer using a weak map to cache table maps. Fall back on a
|
|
12
13
|
// fixed-size cache if that's not supported.
|
|
13
|
-
|
|
14
14
|
if (typeof WeakMap !== 'undefined') {
|
|
15
15
|
let cache = new WeakMap();
|
|
16
|
-
|
|
17
16
|
readFromCache = key => cache.get(key);
|
|
18
|
-
|
|
19
17
|
addToCache = (key, value) => {
|
|
20
18
|
cache.set(key, value);
|
|
21
19
|
return value;
|
|
@@ -24,7 +22,6 @@ if (typeof WeakMap !== 'undefined') {
|
|
|
24
22
|
let cache = [];
|
|
25
23
|
let cacheSize = 10;
|
|
26
24
|
let cachePos = 0;
|
|
27
|
-
|
|
28
25
|
readFromCache = key => {
|
|
29
26
|
for (let i = 0; i < cache.length; i += 2) {
|
|
30
27
|
if (cache[i] === key) {
|
|
@@ -32,17 +29,14 @@ if (typeof WeakMap !== 'undefined') {
|
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
31
|
};
|
|
35
|
-
|
|
36
32
|
addToCache = (key, value) => {
|
|
37
33
|
if (cachePos === cacheSize) {
|
|
38
34
|
cachePos = 0;
|
|
39
35
|
}
|
|
40
|
-
|
|
41
36
|
cache[cachePos++] = key;
|
|
42
37
|
return cache[cachePos++] = value;
|
|
43
38
|
};
|
|
44
39
|
}
|
|
45
|
-
|
|
46
40
|
export class Rect {
|
|
47
41
|
constructor(left, top, right, bottom) {
|
|
48
42
|
this.left = left;
|
|
@@ -50,102 +44,92 @@ export class Rect {
|
|
|
50
44
|
this.right = right;
|
|
51
45
|
this.bottom = bottom;
|
|
52
46
|
}
|
|
53
|
-
|
|
54
47
|
}
|
|
55
|
-
export let TableProblemTypes
|
|
56
|
-
|
|
57
|
-
(function (TableProblemTypes) {
|
|
48
|
+
export let TableProblemTypes = /*#__PURE__*/function (TableProblemTypes) {
|
|
58
49
|
TableProblemTypes["COLLISION"] = "collision";
|
|
59
50
|
TableProblemTypes["OVERLONG_ROWSPAN"] = "overlong_rowspan";
|
|
60
51
|
TableProblemTypes["MISSING"] = "missing";
|
|
61
52
|
TableProblemTypes["COLWIDTH_MISMATCH"] = "colwidth mismatch";
|
|
62
|
-
|
|
63
|
-
|
|
53
|
+
return TableProblemTypes;
|
|
54
|
+
}({});
|
|
64
55
|
// Ideally tableNewColumnMinWidth should be imported
|
|
65
56
|
// from '@atlaskit/editor-common/styles';
|
|
66
57
|
// We don't want to introduce a new dependency.
|
|
67
58
|
// Thus we define the constant here.
|
|
68
|
-
export const tableNewColumnMinWidth = 140;
|
|
59
|
+
export const tableNewColumnMinWidth = 140;
|
|
60
|
+
|
|
61
|
+
// ::- A table map describes the structore of a given table. To avoid
|
|
69
62
|
// recomputing them all the time, they are cached per table node. To
|
|
70
63
|
// be able to do that, positions saved in the map are relative to the
|
|
71
64
|
// start of the table, rather than the start of the document.
|
|
72
|
-
|
|
73
65
|
export class TableMap {
|
|
74
66
|
// The width of the table
|
|
67
|
+
|
|
75
68
|
// The table's height
|
|
69
|
+
|
|
76
70
|
constructor(width, height, map, problems) {
|
|
77
71
|
this.width = width;
|
|
78
|
-
this.height = height;
|
|
72
|
+
this.height = height;
|
|
73
|
+
// :: [number] A width * height array with the start position of
|
|
79
74
|
// the cell covering that part of the table in each slot
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
this.map = map;
|
|
76
|
+
// An optional array of problems (cell overlap or non-rectangular
|
|
82
77
|
// shape) for the table, used by the table normalizer.
|
|
83
|
-
|
|
84
78
|
this.problems = problems;
|
|
85
|
-
}
|
|
86
|
-
// Find the dimensions of the cell at the given position.
|
|
87
|
-
|
|
79
|
+
}
|
|
88
80
|
|
|
81
|
+
// :: (number) → Rect
|
|
82
|
+
// Find the dimensions of the cell at the given position.
|
|
89
83
|
findCell(pos) {
|
|
90
84
|
for (let i = 0; i < this.map.length; i++) {
|
|
91
85
|
let curPos = this.map[i];
|
|
92
|
-
|
|
93
86
|
if (curPos !== pos) {
|
|
94
87
|
continue;
|
|
95
88
|
}
|
|
96
|
-
|
|
97
89
|
let left = i % this.width;
|
|
98
90
|
let top = i / this.width | 0;
|
|
99
91
|
let right = left + 1;
|
|
100
92
|
let bottom = top + 1;
|
|
101
|
-
|
|
102
93
|
for (let j = 1; right < this.width && this.map[i + j] === curPos; j++) {
|
|
103
94
|
right++;
|
|
104
95
|
}
|
|
105
|
-
|
|
106
96
|
for (let j = 1; bottom < this.height && this.map[i + this.width * j] === curPos; j++) {
|
|
107
97
|
bottom++;
|
|
108
98
|
}
|
|
109
|
-
|
|
110
99
|
return new Rect(left, top, right, bottom);
|
|
111
100
|
}
|
|
112
|
-
|
|
113
101
|
throw new RangeError('No cell with offset ' + pos + ' found');
|
|
114
|
-
}
|
|
115
|
-
|
|
102
|
+
}
|
|
116
103
|
|
|
104
|
+
// Find the left side of the cell at the given position.
|
|
117
105
|
colCount(pos) {
|
|
118
106
|
for (let i = 0; i < this.map.length; i++) {
|
|
119
107
|
if (this.map[i] === pos) {
|
|
120
108
|
return i % this.width;
|
|
121
109
|
}
|
|
122
110
|
}
|
|
123
|
-
|
|
124
111
|
throw new RangeError('No cell with offset ' + pos + ' found');
|
|
125
|
-
}
|
|
126
|
-
|
|
112
|
+
}
|
|
127
113
|
|
|
114
|
+
// Find the top side of the cell at the given position.
|
|
128
115
|
rowCount(pos) {
|
|
129
116
|
if (this.width <= 0) {
|
|
130
117
|
throw new RangeError('Wrong table width found');
|
|
131
118
|
}
|
|
132
|
-
|
|
133
119
|
for (let i = 0; i < this.map.length; i++) {
|
|
134
120
|
if (this.map[i] === pos) {
|
|
135
121
|
return Math.floor(i / this.width);
|
|
136
122
|
}
|
|
137
123
|
}
|
|
138
|
-
|
|
139
124
|
throw new RangeError('No cell with offset ' + pos + ' found');
|
|
140
125
|
}
|
|
141
|
-
|
|
142
126
|
isPosMerged(pos) {
|
|
143
127
|
return this.map.filter(cellPos => cellPos === pos).length > 1;
|
|
144
|
-
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// :: (number, string, number) → ?number
|
|
145
131
|
// Find the next cell in the given direction, starting from the cell
|
|
146
132
|
// at `pos`, if any.
|
|
147
|
-
|
|
148
|
-
|
|
149
133
|
nextCell(pos, axis, dir) {
|
|
150
134
|
let {
|
|
151
135
|
left,
|
|
@@ -153,24 +137,21 @@ export class TableMap {
|
|
|
153
137
|
top,
|
|
154
138
|
bottom
|
|
155
139
|
} = this.findCell(pos);
|
|
156
|
-
|
|
157
140
|
if (axis === 'horiz') {
|
|
158
141
|
if (dir < 0 ? left === 0 : right === this.width) {
|
|
159
142
|
return null;
|
|
160
143
|
}
|
|
161
|
-
|
|
162
144
|
return this.map[top * this.width + (dir < 0 ? left - 1 : right)];
|
|
163
145
|
} else {
|
|
164
146
|
if (dir < 0 ? top === 0 : bottom === this.height) {
|
|
165
147
|
return null;
|
|
166
148
|
}
|
|
167
|
-
|
|
168
149
|
return this.map[left + this.width * (dir < 0 ? top - 1 : bottom)];
|
|
169
150
|
}
|
|
170
|
-
}
|
|
171
|
-
// Get the rectangle spanning the two given cells.
|
|
172
|
-
|
|
151
|
+
}
|
|
173
152
|
|
|
153
|
+
// :: (number, number) → Rect
|
|
154
|
+
// Get the rectangle spanning the two given cells.
|
|
174
155
|
rectBetween(a, b) {
|
|
175
156
|
let {
|
|
176
157
|
left: leftA,
|
|
@@ -185,109 +166,92 @@ export class TableMap {
|
|
|
185
166
|
bottom: bottomB
|
|
186
167
|
} = this.findCell(b);
|
|
187
168
|
return new Rect(Math.min(leftA, leftB), Math.min(topA, topB), Math.max(rightA, rightB), Math.max(bottomA, bottomB));
|
|
188
|
-
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// :: (Rect) → [number]
|
|
189
172
|
// Return the position of all cells that have the top left corner in
|
|
190
173
|
// the given rectangle.
|
|
191
|
-
|
|
192
|
-
|
|
193
174
|
cellsInRect(rect) {
|
|
194
175
|
let result = [];
|
|
195
176
|
let seen = {};
|
|
196
|
-
|
|
197
177
|
for (let row = rect.top; row < rect.bottom; row++) {
|
|
198
178
|
for (let col = rect.left; col < rect.right; col++) {
|
|
199
179
|
let index = row * this.width + col;
|
|
200
180
|
let pos = this.map[index];
|
|
201
|
-
|
|
202
181
|
if (seen[pos]) {
|
|
203
182
|
continue;
|
|
204
183
|
}
|
|
205
|
-
|
|
206
184
|
seen[pos] = true;
|
|
207
|
-
|
|
208
185
|
if ((col !== rect.left || !col || this.map[index - 1] !== pos) && (row !== rect.top || !row || this.map[index - this.width] !== pos)) {
|
|
209
186
|
result.push(pos);
|
|
210
187
|
}
|
|
211
188
|
}
|
|
212
189
|
}
|
|
213
|
-
|
|
214
190
|
return result;
|
|
215
|
-
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// :: (number, number, Node) → number
|
|
216
194
|
// Return the position at which the cell at the given row and column
|
|
217
195
|
// starts, or would start, if a cell started there.
|
|
218
|
-
|
|
219
|
-
|
|
220
196
|
positionAt(row, col, table) {
|
|
221
197
|
for (let i = 0, rowStart = 0;; i++) {
|
|
222
198
|
let rowEnd = rowStart + table.child(i).nodeSize;
|
|
223
|
-
|
|
224
199
|
if (i === row) {
|
|
225
200
|
let index = col + row * this.width;
|
|
226
|
-
let rowEndIndex = (row + 1) * this.width;
|
|
227
|
-
|
|
201
|
+
let rowEndIndex = (row + 1) * this.width;
|
|
202
|
+
// Skip past cells from previous rows (via rowspan)
|
|
228
203
|
while (index < rowEndIndex && this.map[index] < rowStart) {
|
|
229
204
|
index++;
|
|
230
205
|
}
|
|
231
|
-
|
|
232
206
|
return index === rowEndIndex ? rowEnd - 1 : this.map[index];
|
|
233
207
|
}
|
|
234
|
-
|
|
235
208
|
rowStart = rowEnd;
|
|
236
209
|
}
|
|
237
210
|
}
|
|
238
|
-
|
|
239
211
|
getMaxColInRow(pos) {
|
|
240
212
|
let parentRowNode = pos.parent;
|
|
241
|
-
|
|
242
213
|
if (parentRowNode.type.name === 'tableRow') {
|
|
243
214
|
return parentRowNode.childCount;
|
|
244
215
|
}
|
|
245
|
-
}
|
|
246
|
-
// Find the table map for the given table node.
|
|
247
|
-
|
|
216
|
+
}
|
|
248
217
|
|
|
218
|
+
// :: (Node) → TableMap
|
|
219
|
+
// Find the table map for the given table node.
|
|
249
220
|
static get(table) {
|
|
250
221
|
return readFromCache(table) || addToCache(table, computeMap(table));
|
|
251
222
|
}
|
|
223
|
+
}
|
|
252
224
|
|
|
253
|
-
|
|
254
|
-
|
|
225
|
+
// Compute a table map.
|
|
255
226
|
function computeMap(table) {
|
|
256
227
|
if (table.type.spec.tableRole !== 'table') {
|
|
257
228
|
throw new RangeError('Not a table node: ' + table.type.name);
|
|
258
229
|
}
|
|
259
|
-
|
|
260
230
|
let width = findWidth(table);
|
|
261
231
|
let height = table.childCount;
|
|
262
232
|
let map = [],
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
233
|
+
mapPos = 0,
|
|
234
|
+
problems = null,
|
|
235
|
+
colWidths = [];
|
|
267
236
|
for (let i = 0, e = width * height; i < e; i++) {
|
|
268
237
|
map[i] = 0;
|
|
269
238
|
}
|
|
270
|
-
|
|
271
239
|
for (let row = 0, pos = 0; row < height; row++) {
|
|
272
240
|
let rowNode = table.child(row);
|
|
273
241
|
pos++;
|
|
274
|
-
|
|
275
242
|
for (let i = 0;; i++) {
|
|
276
243
|
while (mapPos < map.length && map[mapPos] !== 0) {
|
|
277
244
|
mapPos++;
|
|
278
245
|
}
|
|
279
|
-
|
|
280
246
|
if (i === rowNode.childCount) {
|
|
281
247
|
break;
|
|
282
248
|
}
|
|
283
|
-
|
|
284
249
|
let cellNode = rowNode.child(i),
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
250
|
+
{
|
|
251
|
+
colspan,
|
|
252
|
+
rowspan,
|
|
253
|
+
colwidth
|
|
254
|
+
} = cellNode.attrs;
|
|
291
255
|
for (let h = 0; h < rowspan; h++) {
|
|
292
256
|
if (h + row >= height) {
|
|
293
257
|
(problems || (problems = [])).push({
|
|
@@ -297,9 +261,7 @@ function computeMap(table) {
|
|
|
297
261
|
});
|
|
298
262
|
break;
|
|
299
263
|
}
|
|
300
|
-
|
|
301
264
|
let start = mapPos + h * width;
|
|
302
|
-
|
|
303
265
|
for (let w = 0; w < colspan; w++) {
|
|
304
266
|
if (map[start + w] === 0) {
|
|
305
267
|
map[start + w] = pos;
|
|
@@ -311,13 +273,10 @@ function computeMap(table) {
|
|
|
311
273
|
n: colspan - w
|
|
312
274
|
});
|
|
313
275
|
}
|
|
314
|
-
|
|
315
276
|
let colW = colwidth && colwidth[w];
|
|
316
|
-
|
|
317
277
|
if (colW) {
|
|
318
278
|
let widthIndex = (start + w) % width * 2,
|
|
319
|
-
|
|
320
|
-
|
|
279
|
+
prev = colWidths[widthIndex];
|
|
321
280
|
if (prev == null || prev !== colW && colWidths[widthIndex + 1] === 1) {
|
|
322
281
|
colWidths[widthIndex] = colW;
|
|
323
282
|
colWidths[widthIndex + 1] = 1;
|
|
@@ -327,20 +286,16 @@ function computeMap(table) {
|
|
|
327
286
|
}
|
|
328
287
|
}
|
|
329
288
|
}
|
|
330
|
-
|
|
331
289
|
mapPos += colspan;
|
|
332
290
|
pos += cellNode.nodeSize;
|
|
333
291
|
}
|
|
334
|
-
|
|
335
292
|
let expectedPos = (row + 1) * width;
|
|
336
293
|
let missing = 0;
|
|
337
|
-
|
|
338
294
|
while (mapPos < expectedPos) {
|
|
339
295
|
if (map[mapPos++] === 0) {
|
|
340
296
|
missing++;
|
|
341
297
|
}
|
|
342
298
|
}
|
|
343
|
-
|
|
344
299
|
if (missing) {
|
|
345
300
|
(problems || (problems = [])).push({
|
|
346
301
|
type: TableProblemTypes.MISSING,
|
|
@@ -348,109 +303,88 @@ function computeMap(table) {
|
|
|
348
303
|
n: missing
|
|
349
304
|
});
|
|
350
305
|
}
|
|
351
|
-
|
|
352
306
|
pos++;
|
|
353
307
|
}
|
|
354
|
-
|
|
355
308
|
let tableMap = new TableMap(width, height, map, problems);
|
|
356
|
-
let badWidths = false;
|
|
309
|
+
let badWidths = false;
|
|
310
|
+
|
|
311
|
+
// For columns that have defined widths, but whose widths disagree
|
|
357
312
|
// between rows, fix up the cells whose width doesn't match the
|
|
358
313
|
// computed one.
|
|
359
|
-
|
|
360
314
|
for (let i = 0; !badWidths && i < colWidths.length; i += 2) {
|
|
361
315
|
if (colWidths[i] != null && colWidths[i + 1] < height) {
|
|
362
316
|
badWidths = true;
|
|
363
317
|
}
|
|
364
|
-
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// colWidths is an array of numbers, it can look like this
|
|
365
321
|
// const colWidths = [255, 3, 125, 3, 150, 2, 130, 1];
|
|
366
322
|
// 255 is a colWidth and 3 is a number of cells with this colwidth.
|
|
367
323
|
// This check exists to make sure that the table has been resized,
|
|
368
324
|
// which means there will be elements in the colWidths array.
|
|
369
|
-
|
|
370
|
-
|
|
371
325
|
if (colWidths.length > 0 && colWidths.length !== width * 2) {
|
|
372
326
|
for (let i = 0; i < width * 2 - colWidths.length; i++) {
|
|
373
327
|
colWidths.push(tableNewColumnMinWidth, 0);
|
|
374
328
|
}
|
|
375
|
-
|
|
376
329
|
badWidths = true;
|
|
377
330
|
}
|
|
378
|
-
|
|
379
331
|
if (badWidths) {
|
|
380
332
|
findBadColWidths(tableMap, colWidths, table);
|
|
381
333
|
}
|
|
382
|
-
|
|
383
334
|
return tableMap;
|
|
384
335
|
}
|
|
385
|
-
|
|
386
336
|
function findWidth(table) {
|
|
387
337
|
let width = -1;
|
|
388
338
|
let hasRowSpan = false;
|
|
389
|
-
|
|
390
339
|
for (let row = 0; row < table.childCount; row++) {
|
|
391
340
|
let rowNode = table.child(row);
|
|
392
341
|
let rowWidth = 0;
|
|
393
|
-
|
|
394
342
|
if (hasRowSpan) {
|
|
395
343
|
for (let j = 0; j < row; j++) {
|
|
396
344
|
let prevRow = table.child(j);
|
|
397
|
-
|
|
398
345
|
for (let i = 0; i < prevRow.childCount; i++) {
|
|
399
346
|
let cell = prevRow.child(i);
|
|
400
|
-
|
|
401
347
|
if (j + cell.attrs.rowspan > row) {
|
|
402
348
|
rowWidth += cell.attrs.colspan;
|
|
403
349
|
}
|
|
404
350
|
}
|
|
405
351
|
}
|
|
406
352
|
}
|
|
407
|
-
|
|
408
353
|
for (let i = 0; i < rowNode.childCount; i++) {
|
|
409
354
|
let cell = rowNode.child(i);
|
|
410
355
|
rowWidth += cell.attrs.colspan;
|
|
411
|
-
|
|
412
356
|
if (cell.attrs.rowspan > 1) {
|
|
413
357
|
hasRowSpan = true;
|
|
414
358
|
}
|
|
415
359
|
}
|
|
416
|
-
|
|
417
360
|
if (width === -1) {
|
|
418
361
|
width = rowWidth;
|
|
419
362
|
} else if (width !== rowWidth) {
|
|
420
363
|
width = Math.max(width, rowWidth);
|
|
421
364
|
}
|
|
422
365
|
}
|
|
423
|
-
|
|
424
366
|
return width;
|
|
425
367
|
}
|
|
426
|
-
|
|
427
368
|
function findBadColWidths(map, colWidths, table) {
|
|
428
369
|
if (!map.problems) {
|
|
429
370
|
map.problems = [];
|
|
430
371
|
}
|
|
431
|
-
|
|
432
372
|
let seen = {};
|
|
433
|
-
|
|
434
373
|
for (let i = 0; i < map.map.length; i++) {
|
|
435
374
|
let pos = map.map[i];
|
|
436
|
-
|
|
437
375
|
if (seen[pos]) {
|
|
438
376
|
continue;
|
|
439
377
|
}
|
|
440
|
-
|
|
441
378
|
seen[pos] = true;
|
|
442
379
|
let node = table.nodeAt(pos),
|
|
443
|
-
|
|
444
|
-
|
|
380
|
+
updated = null;
|
|
445
381
|
for (let j = 0; j < node.attrs.colspan; j++) {
|
|
446
382
|
let col = (i + j) % map.width,
|
|
447
|
-
|
|
448
|
-
|
|
383
|
+
colWidth = colWidths[col * 2];
|
|
449
384
|
if (colWidth != null && (!node.attrs.colwidth || node.attrs.colwidth[j] !== colWidth)) {
|
|
450
385
|
(updated || (updated = freshColWidth(node.attrs)))[j] = colWidth;
|
|
451
386
|
}
|
|
452
387
|
}
|
|
453
|
-
|
|
454
388
|
if (updated) {
|
|
455
389
|
map.problems.unshift({
|
|
456
390
|
type: TableProblemTypes.COLWIDTH_MISMATCH,
|
|
@@ -460,17 +394,13 @@ function findBadColWidths(map, colWidths, table) {
|
|
|
460
394
|
}
|
|
461
395
|
}
|
|
462
396
|
}
|
|
463
|
-
|
|
464
397
|
function freshColWidth(attrs) {
|
|
465
398
|
if (attrs.colwidth) {
|
|
466
399
|
return attrs.colwidth.slice();
|
|
467
400
|
}
|
|
468
|
-
|
|
469
401
|
let result = [];
|
|
470
|
-
|
|
471
402
|
for (let i = 0; i < attrs.colspan; i++) {
|
|
472
403
|
result.push(0);
|
|
473
404
|
}
|
|
474
|
-
|
|
475
405
|
return result;
|
|
476
406
|
}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { TableMap } from '../table-map';
|
|
2
2
|
import { addColumn } from './add-column';
|
|
3
3
|
import { cloneTr } from './clone-tr';
|
|
4
|
-
import { findTable } from './find';
|
|
4
|
+
import { findTable } from './find';
|
|
5
5
|
|
|
6
|
+
// Returns a new transaction that adds a new column at index `columnIndex`.
|
|
6
7
|
export const addColumnAt = columnIndex => tr => {
|
|
7
8
|
const table = findTable(tr.selection);
|
|
8
|
-
|
|
9
9
|
if (table) {
|
|
10
10
|
const map = TableMap.get(table.node);
|
|
11
|
-
|
|
12
11
|
if (columnIndex >= 0 && columnIndex <= map.width) {
|
|
13
12
|
return cloneTr(addColumn(tr, {
|
|
14
13
|
map,
|
|
@@ -17,6 +16,5 @@ export const addColumnAt = columnIndex => tr => {
|
|
|
17
16
|
}, columnIndex));
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
|
-
|
|
21
19
|
return tr;
|
|
22
20
|
};
|
|
@@ -2,65 +2,55 @@ import { addColSpan, assertColspan } from './colspan';
|
|
|
2
2
|
import { tableNodeTypes } from './table-node-types';
|
|
3
3
|
export function columnIsHeader(map, table, col) {
|
|
4
4
|
const headerCell = tableNodeTypes(table.type.schema).header_cell;
|
|
5
|
-
|
|
6
5
|
for (let row = 0; row < map.height; row++) {
|
|
7
6
|
const cell = table.nodeAt(map.map[col + row * map.width]);
|
|
8
|
-
|
|
9
7
|
if (cell && cell.type !== headerCell) {
|
|
10
8
|
return false;
|
|
11
9
|
}
|
|
12
10
|
}
|
|
13
|
-
|
|
14
11
|
return true;
|
|
15
|
-
}
|
|
12
|
+
}
|
|
16
13
|
|
|
14
|
+
// Add a column at the given position in a table.
|
|
17
15
|
export function addColumn(tr, {
|
|
18
16
|
map,
|
|
19
17
|
tableStart,
|
|
20
18
|
table
|
|
21
19
|
}, col) {
|
|
22
20
|
let refColumn = col > 0 ? -1 : 0;
|
|
23
|
-
|
|
24
21
|
if (columnIsHeader(map, table, col + refColumn)) {
|
|
25
22
|
refColumn = col === 0 || col === map.width ? null : 0;
|
|
26
23
|
}
|
|
27
|
-
|
|
28
24
|
for (let row = 0; row < map.height; row++) {
|
|
29
|
-
const index = row * map.width + col;
|
|
25
|
+
const index = row * map.width + col;
|
|
30
26
|
|
|
27
|
+
// If this position falls inside a col-spanning cell
|
|
31
28
|
if (col > 0 && col < map.width && map.map[index - 1] === map.map[index]) {
|
|
32
29
|
const pos = map.map[index];
|
|
33
30
|
const cell = table.nodeAt(pos);
|
|
34
|
-
|
|
35
31
|
if (!cell) {
|
|
36
32
|
throw new Error(`addColumn: invalid cell for pos ${pos}`);
|
|
37
33
|
}
|
|
38
|
-
|
|
39
34
|
const attributes = cell.attrs;
|
|
40
35
|
assertColspan(attributes);
|
|
41
|
-
tr.setNodeMarkup(tr.mapping.map(tableStart + pos), undefined, addColSpan(attributes, col - map.colCount(pos)));
|
|
42
|
-
|
|
36
|
+
tr.setNodeMarkup(tr.mapping.map(tableStart + pos), undefined, addColSpan(attributes, col - map.colCount(pos)));
|
|
37
|
+
// Skip ahead if rowspan > 1
|
|
43
38
|
row += attributes.rowspan - 1;
|
|
44
39
|
} else {
|
|
45
40
|
let type;
|
|
46
|
-
|
|
47
41
|
if (refColumn === null) {
|
|
48
42
|
type = tableNodeTypes(table.type.schema).cell;
|
|
49
43
|
} else {
|
|
50
44
|
const mappedPos = map.map[index + refColumn];
|
|
51
45
|
const cell = table.nodeAt(mappedPos);
|
|
52
|
-
|
|
53
46
|
if (!cell) {
|
|
54
47
|
throw new Error(`addColumn: invalid node at mapped pos ${mappedPos}`);
|
|
55
48
|
}
|
|
56
|
-
|
|
57
49
|
type = cell.type;
|
|
58
50
|
}
|
|
59
|
-
|
|
60
51
|
const pos = map.positionAt(row, col, table);
|
|
61
52
|
tr.insert(tr.mapping.map(tableStart + pos), type.createAndFill());
|
|
62
53
|
}
|
|
63
54
|
}
|
|
64
|
-
|
|
65
55
|
return tr;
|
|
66
56
|
}
|