@milkdown/preset-gfm 6.5.0 → 6.5.3

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.
Files changed (94) hide show
  1. package/lib/footnote/definition.d.ts +1 -1
  2. package/lib/footnote/definition.d.ts.map +1 -1
  3. package/lib/footnote/index.d.ts.map +1 -1
  4. package/lib/footnote/reference.d.ts +1 -1
  5. package/lib/footnote/reference.d.ts.map +1 -1
  6. package/lib/footnote/utils.d.ts.map +1 -1
  7. package/lib/index.d.ts +1 -1
  8. package/lib/index.d.ts.map +1 -1
  9. package/lib/index.es.js +1007 -863
  10. package/lib/index.es.js.map +1 -1
  11. package/lib/strike-through.d.ts +1 -1
  12. package/lib/strike-through.d.ts.map +1 -1
  13. package/lib/supported-keys.d.ts +1 -1
  14. package/lib/supported-keys.d.ts.map +1 -1
  15. package/lib/table/command.d.ts +2 -2
  16. package/lib/table/command.d.ts.map +1 -1
  17. package/lib/table/index.d.ts +1 -1
  18. package/lib/table/index.d.ts.map +1 -1
  19. package/lib/table/nodes/index.d.ts +1 -1
  20. package/lib/table/nodes/index.d.ts.map +1 -1
  21. package/lib/table/operator-plugin/actions.d.ts +5 -5
  22. package/lib/table/operator-plugin/actions.d.ts.map +1 -1
  23. package/lib/table/operator-plugin/calc-pos.d.ts +1 -1
  24. package/lib/table/operator-plugin/calc-pos.d.ts.map +1 -1
  25. package/lib/table/operator-plugin/constant.d.ts.map +1 -1
  26. package/lib/table/operator-plugin/helper.d.ts +3 -3
  27. package/lib/table/operator-plugin/helper.d.ts.map +1 -1
  28. package/lib/table/operator-plugin/index.d.ts +2 -2
  29. package/lib/table/operator-plugin/index.d.ts.map +1 -1
  30. package/lib/table/operator-plugin/style.d.ts +1 -1
  31. package/lib/table/operator-plugin/style.d.ts.map +1 -1
  32. package/lib/table/operator-plugin/widget.d.ts +2 -2
  33. package/lib/table/operator-plugin/widget.d.ts.map +1 -1
  34. package/lib/table/plugin/auto-insert-zero-space.d.ts.map +1 -1
  35. package/lib/table/plugin/cell-selection.d.ts +5 -3
  36. package/lib/table/plugin/cell-selection.d.ts.map +1 -1
  37. package/lib/table/plugin/column-resizing.d.ts +2 -1
  38. package/lib/table/plugin/column-resizing.d.ts.map +1 -1
  39. package/lib/table/plugin/commands.d.ts +2 -2
  40. package/lib/table/plugin/commands.d.ts.map +1 -1
  41. package/lib/table/plugin/copy-paste.d.ts +6 -5
  42. package/lib/table/plugin/copy-paste.d.ts.map +1 -1
  43. package/lib/table/plugin/fix-tables.d.ts +3 -2
  44. package/lib/table/plugin/fix-tables.d.ts.map +1 -1
  45. package/lib/table/plugin/index.d.ts.map +1 -1
  46. package/lib/table/plugin/schema.d.ts +1 -1
  47. package/lib/table/plugin/schema.d.ts.map +1 -1
  48. package/lib/table/plugin/table-editing.d.ts +1 -1
  49. package/lib/table/plugin/table-editing.d.ts.map +1 -1
  50. package/lib/table/plugin/table-map.d.ts +2 -2
  51. package/lib/table/plugin/table-map.d.ts.map +1 -1
  52. package/lib/table/plugin/table-view.d.ts +2 -2
  53. package/lib/table/plugin/table-view.d.ts.map +1 -1
  54. package/lib/table/plugin/types.d.ts +2 -2
  55. package/lib/table/plugin/types.d.ts.map +1 -1
  56. package/lib/table/plugin/util.d.ts +2 -2
  57. package/lib/table/plugin/util.d.ts.map +1 -1
  58. package/lib/table/utils.d.ts +5 -5
  59. package/lib/table/utils.d.ts.map +1 -1
  60. package/lib/task-list-item.d.ts +2 -2
  61. package/lib/task-list-item.d.ts.map +1 -1
  62. package/package.json +17 -17
  63. package/src/footnote/definition.ts +172 -166
  64. package/src/footnote/index.ts +2 -2
  65. package/src/footnote/reference.ts +166 -162
  66. package/src/footnote/utils.ts +2 -2
  67. package/src/index.ts +83 -83
  68. package/src/strike-through.ts +36 -36
  69. package/src/supported-keys.ts +9 -8
  70. package/src/table/command.ts +17 -16
  71. package/src/table/index.ts +9 -9
  72. package/src/table/nodes/index.ts +177 -174
  73. package/src/table/operator-plugin/actions.ts +103 -102
  74. package/src/table/operator-plugin/calc-pos.ts +31 -24
  75. package/src/table/operator-plugin/constant.ts +3 -3
  76. package/src/table/operator-plugin/helper.ts +31 -32
  77. package/src/table/operator-plugin/index.ts +104 -95
  78. package/src/table/operator-plugin/style.ts +10 -9
  79. package/src/table/operator-plugin/widget.ts +47 -45
  80. package/src/table/plugin/auto-insert-zero-space.ts +41 -41
  81. package/src/table/plugin/cell-selection.ts +325 -296
  82. package/src/table/plugin/column-resizing.ts +226 -198
  83. package/src/table/plugin/commands.ts +464 -421
  84. package/src/table/plugin/copy-paste.ts +256 -240
  85. package/src/table/plugin/fix-tables.ts +103 -88
  86. package/src/table/plugin/index.ts +3 -3
  87. package/src/table/plugin/schema.ts +100 -94
  88. package/src/table/plugin/table-editing.ts +324 -230
  89. package/src/table/plugin/table-map.ts +294 -229
  90. package/src/table/plugin/table-view.ts +66 -62
  91. package/src/table/plugin/types.ts +8 -8
  92. package/src/table/plugin/util.ts +78 -66
  93. package/src/table/utils.ts +141 -138
  94. package/src/task-list-item.ts +151 -146
@@ -1,400 +1,432 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
2
 
3
- import { Fragment, Node, NodeSpec, NodeType, ResolvedPos } from '@milkdown/prose/model';
4
- import { Command, EditorState, TextSelection, Transaction } from '@milkdown/prose/state';
5
-
6
- import { CellSelection } from './cell-selection';
7
- import { tableNodeTypes } from './schema';
8
- import { Rect, TableMap } from './table-map';
3
+ import type { Node, NodeSpec, NodeType, ResolvedPos } from '@milkdown/prose/model'
4
+ import { Fragment } from '@milkdown/prose/model'
5
+ import type { Command, EditorState, Transaction } from '@milkdown/prose/state'
6
+ import { TextSelection } from '@milkdown/prose/state'
7
+
8
+ import { CellSelection } from './cell-selection'
9
+ import { tableNodeTypes } from './schema'
10
+ import { Rect, TableMap } from './table-map'
9
11
  import {
10
- addColSpan,
11
- cellAround,
12
- cellWrapping,
13
- columnIsHeader,
14
- isInTable,
15
- moveCellForward,
16
- removeColSpan,
17
- selectionCell,
18
- setAttr,
19
- } from './util';
12
+ addColSpan,
13
+ cellAround,
14
+ cellWrapping,
15
+ columnIsHeader,
16
+ isInTable,
17
+ moveCellForward,
18
+ removeColSpan,
19
+ selectionCell,
20
+ setAttr,
21
+ } from './util'
20
22
 
21
23
  // Helper to get the selected rectangle in a table, if any. Adds table
22
24
  // map, table node, and table start offset to the object for
23
25
  // convenience.
24
26
  export function selectedRect(state: EditorState): Required<Rect> {
25
- const sel = state.selection,
26
- $pos = selectionCell(state) as ResolvedPos;
27
- const table = $pos.node(-1),
28
- tableStart = $pos.start(-1),
29
- map = TableMap.get(table);
30
- let rect;
31
- if (sel instanceof CellSelection)
32
- rect = map.rectBetween(sel.$anchorCell.pos - tableStart, sel.$headCell.pos - tableStart);
33
- else rect = map.findCell($pos.pos - tableStart);
34
- rect.tableStart = tableStart;
35
- rect.map = map;
36
- rect.table = table;
37
- return rect as Required<Rect>;
27
+ const sel = state.selection
28
+ const $pos = selectionCell(state) as ResolvedPos
29
+ const table = $pos.node(-1)
30
+ const tableStart = $pos.start(-1)
31
+ const map = TableMap.get(table)
32
+ let rect
33
+ if (sel instanceof CellSelection)
34
+ rect = map.rectBetween(sel.$anchorCell.pos - tableStart, sel.$headCell.pos - tableStart)
35
+ else rect = map.findCell($pos.pos - tableStart)
36
+ rect.tableStart = tableStart
37
+ rect.map = map
38
+ rect.table = table
39
+ return rect as Required<Rect>
38
40
  }
39
41
 
40
42
  // Add a column at the given position in a table.
41
43
  export function addColumn(tr: Transaction, { map, tableStart, table }: Rect, col: number) {
42
- map = map as TableMap;
43
- table = table as Node;
44
- tableStart = tableStart as number;
45
- let refColumn: number | null = col > 0 ? -1 : 0;
46
- if (columnIsHeader(map, table, col + refColumn)) refColumn = col == 0 || col == map.width ? null : 0;
47
-
48
- for (let row = 0; row < map.height; row++) {
49
- const index = row * map.width + col;
50
- // If this position falls inside a col-spanning cell
51
- if (col > 0 && col < map.width && map.map[index - 1] == map.map[index]) {
52
- const pos = map.map[index] as number,
53
- cell = table.nodeAt(pos) as Node;
54
- tr.setNodeMarkup(tr.mapping.map(tableStart + pos), null, addColSpan(cell.attrs, col - map.colCount(pos)));
55
- // Skip ahead if rowspan > 1
56
- row += cell.attrs['rowspan'] - 1;
57
- } else {
58
- const offset = map.map[index + (refColumn as number)] as number;
59
- const type =
60
- refColumn == null ? tableNodeTypes(table.type.schema).cell : (table.nodeAt(offset) as Node).type;
61
- const pos = map.positionAt(row, col, table);
62
- tr.insert(tr.mapping.map(tableStart + pos), type.createAndFill());
63
- }
44
+ map = map as TableMap
45
+ table = table as Node
46
+ tableStart = tableStart as number
47
+ let refColumn: number | null = col > 0 ? -1 : 0
48
+ if (columnIsHeader(map, table, col + refColumn))
49
+ refColumn = col == 0 || col == map.width ? null : 0
50
+
51
+ for (let row = 0; row < map.height; row++) {
52
+ const index = row * map.width + col
53
+ // If this position falls inside a col-spanning cell
54
+ if (col > 0 && col < map.width && map.map[index - 1] == map.map[index]) {
55
+ const pos = map.map[index] as number
56
+ const cell = table.nodeAt(pos) as Node
57
+ tr.setNodeMarkup(tr.mapping.map(tableStart + pos), null, addColSpan(cell.attrs, col - map.colCount(pos)))
58
+ // Skip ahead if rowspan > 1
59
+ row += cell.attrs.rowspan - 1
64
60
  }
65
- return tr;
61
+ else {
62
+ const offset = map.map[index + (refColumn as number)] as number
63
+ const type
64
+ = refColumn == null ? tableNodeTypes(table.type.schema).cell : (table.nodeAt(offset) as Node).type
65
+ const pos = map.positionAt(row, col, table)
66
+ tr.insert(tr.mapping.map(tableStart + pos), type.createAndFill())
67
+ }
68
+ }
69
+ return tr
66
70
  }
67
71
 
68
72
  // :: (EditorState, dispatch: ?(tr: Transaction)) → bool
69
73
  // Command to add a column before the column with the selection.
70
74
  export const addColumnBefore: Command = (state, dispatch) => {
71
- if (!isInTable(state)) return false;
72
- if (dispatch) {
73
- const rect = selectedRect(state);
74
- dispatch(addColumn(state.tr, rect, rect.left));
75
- }
76
- return true;
77
- };
75
+ if (!isInTable(state))
76
+ return false
77
+ if (dispatch) {
78
+ const rect = selectedRect(state)
79
+ dispatch(addColumn(state.tr, rect, rect.left))
80
+ }
81
+ return true
82
+ }
78
83
 
79
84
  // :: (EditorState, dispatch: ?(tr: Transaction)) → bool
80
85
  // Command to add a column after the column with the selection.
81
86
  export const addColumnAfter: Command = (state, dispatch) => {
82
- if (!isInTable(state)) return false;
83
- if (dispatch) {
84
- const rect = selectedRect(state);
85
- dispatch(addColumn(state.tr, rect, rect.right));
86
- }
87
- return true;
88
- };
87
+ if (!isInTable(state))
88
+ return false
89
+ if (dispatch) {
90
+ const rect = selectedRect(state)
91
+ dispatch(addColumn(state.tr, rect, rect.right))
92
+ }
93
+ return true
94
+ }
89
95
 
90
96
  export function removeColumn(tr: Transaction, { map, table, tableStart }: Rect, col: number) {
91
- map = map as TableMap;
92
- table = table as Node;
93
- tableStart = tableStart as number;
94
- const mapStart = tr.mapping.maps.length;
95
- for (let row = 0; row < map.height; ) {
96
- const index = row * map.width + col,
97
- pos = map.map[index] as number,
98
- cell = table.nodeAt(pos) as Node;
99
- // If this is part of a col-spanning cell
100
- if ((col > 0 && map.map[index - 1] == pos) || (col < map.width - 1 && map.map[index + 1] == pos)) {
101
- tr.setNodeMarkup(
102
- tr.mapping.slice(mapStart).map(tableStart + pos),
103
- null,
104
- removeColSpan(cell.attrs, col - map.colCount(pos)),
105
- );
106
- } else {
107
- const start = tr.mapping.slice(mapStart).map(tableStart + pos);
108
- tr.delete(start, start + cell.nodeSize);
109
- }
110
- row += cell.attrs['rowspan'];
97
+ map = map as TableMap
98
+ table = table as Node
99
+ tableStart = tableStart as number
100
+ const mapStart = tr.mapping.maps.length
101
+ for (let row = 0; row < map.height;) {
102
+ const index = row * map.width + col
103
+ const pos = map.map[index] as number
104
+ const cell = table.nodeAt(pos) as Node
105
+ // If this is part of a col-spanning cell
106
+ if ((col > 0 && map.map[index - 1] == pos) || (col < map.width - 1 && map.map[index + 1] == pos)) {
107
+ tr.setNodeMarkup(
108
+ tr.mapping.slice(mapStart).map(tableStart + pos),
109
+ null,
110
+ removeColSpan(cell.attrs, col - map.colCount(pos)),
111
+ )
111
112
  }
113
+ else {
114
+ const start = tr.mapping.slice(mapStart).map(tableStart + pos)
115
+ tr.delete(start, start + cell.nodeSize)
116
+ }
117
+ row += cell.attrs.rowspan
118
+ }
112
119
  }
113
120
 
114
121
  // :: (EditorState, dispatch: ?(tr: Transaction)) → bool
115
122
  // Command function that removes the selected columns from a table.
116
123
  export const deleteColumn: Command = (state, dispatch) => {
117
- if (!isInTable(state)) return false;
118
- if (dispatch) {
119
- const rect = selectedRect(state) as Required<Rect>,
120
- tr = state.tr;
121
- if (rect.left == 0 && rect.right == rect.map.width) return false;
122
- for (let i = rect.right - 1; ; i--) {
123
- removeColumn(tr, rect, i);
124
- if (i == rect.left) break;
125
- rect.table = (rect.tableStart ? tr.doc.nodeAt(rect.tableStart - 1) : tr.doc) as Node;
126
- rect.map = TableMap.get(rect.table);
127
- }
128
- dispatch(tr);
124
+ if (!isInTable(state))
125
+ return false
126
+ if (dispatch) {
127
+ const rect = selectedRect(state) as Required<Rect>
128
+ const tr = state.tr
129
+ if (rect.left == 0 && rect.right == rect.map.width)
130
+ return false
131
+ for (let i = rect.right - 1; ; i--) {
132
+ removeColumn(tr, rect, i)
133
+ if (i == rect.left)
134
+ break
135
+ rect.table = (rect.tableStart ? tr.doc.nodeAt(rect.tableStart - 1) : tr.doc) as Node
136
+ rect.map = TableMap.get(rect.table)
129
137
  }
130
- return true;
131
- };
138
+ dispatch(tr)
139
+ }
140
+ return true
141
+ }
132
142
 
133
143
  export function rowIsHeader(map: TableMap, table: Node, row: number) {
134
- const headerCell = tableNodeTypes(table.type.schema).header_cell;
135
- for (let col = 0; col < map.width; col++) {
136
- const offset = map.map[col + row * map.width] as number;
137
- if ((table.nodeAt(offset) as Node).type != headerCell) return false;
138
- }
139
- return true;
144
+ const headerCell = tableNodeTypes(table.type.schema).header_cell
145
+ for (let col = 0; col < map.width; col++) {
146
+ const offset = map.map[col + row * map.width] as number
147
+ if ((table.nodeAt(offset) as Node).type != headerCell)
148
+ return false
149
+ }
150
+ return true
140
151
  }
141
152
 
142
153
  export function addRow(tr: Transaction, { map, tableStart, table }: Rect, row: number) {
143
- map = map as TableMap;
144
- table = table as Node;
145
- tableStart = tableStart as number;
146
- let rowPos = tableStart;
147
- for (let i = 0; i < row; i++) rowPos += table.child(i).nodeSize;
148
- const cells = [];
149
- let refRow: number | null = row > 0 ? -1 : 0;
150
- if (rowIsHeader(map, table, row + refRow)) refRow = row == 0 || row == map.height ? null : 0;
151
- for (let col = 0, index = map.width * row; col < map.width; col++, index++) {
152
- // Covered by a rowspan cell
153
- if (row > 0 && row < map.height && map.map[index] == map.map[index - map.width]) {
154
- const pos = map.map[index] as number,
155
- attrs = (table.nodeAt(pos) as Node).attrs;
156
- tr.setNodeMarkup(tableStart + pos, null, setAttr(attrs, 'rowspan', attrs['rowspan'] + 1));
157
- col += attrs['colspan'] - 1;
158
- } else {
159
- const type =
160
- refRow == null
161
- ? tableNodeTypes(table.type.schema).cell
162
- : (table.nodeAt(map.map[index + refRow * map.width] as number) as Node).type;
163
- cells.push(type.createAndFill());
164
- }
154
+ map = map as TableMap
155
+ table = table as Node
156
+ tableStart = tableStart as number
157
+ let rowPos = tableStart
158
+ for (let i = 0; i < row; i++) rowPos += table.child(i).nodeSize
159
+ const cells = []
160
+ let refRow: number | null = row > 0 ? -1 : 0
161
+ if (rowIsHeader(map, table, row + refRow))
162
+ refRow = row == 0 || row == map.height ? null : 0
163
+ for (let col = 0, index = map.width * row; col < map.width; col++, index++) {
164
+ // Covered by a rowspan cell
165
+ if (row > 0 && row < map.height && map.map[index] == map.map[index - map.width]) {
166
+ const pos = map.map[index] as number
167
+ const attrs = (table.nodeAt(pos) as Node).attrs
168
+ tr.setNodeMarkup(tableStart + pos, null, setAttr(attrs, 'rowspan', attrs.rowspan + 1))
169
+ col += attrs.colspan - 1
170
+ }
171
+ else {
172
+ const type
173
+ = refRow == null
174
+ ? tableNodeTypes(table.type.schema).cell
175
+ : (table.nodeAt(map.map[index + refRow * map.width] as number) as Node).type
176
+ cells.push(type.createAndFill())
165
177
  }
166
- tr.insert(rowPos, tableNodeTypes(table.type.schema).row.create(null, cells));
167
- return tr;
178
+ }
179
+ tr.insert(rowPos, tableNodeTypes(table.type.schema).row.create(null, cells))
180
+ return tr
168
181
  }
169
182
 
170
183
  // :: (EditorState, dispatch: ?(tr: Transaction)) → bool
171
184
  // Add a table row before the selection.
172
185
  export function addRowBefore(state: EditorState, dispatch?: (tr: Transaction) => boolean) {
173
- if (!isInTable(state)) return false;
174
- if (dispatch) {
175
- const rect = selectedRect(state);
176
- dispatch(addRow(state.tr, rect, rect.top));
177
- }
178
- return true;
186
+ if (!isInTable(state))
187
+ return false
188
+ if (dispatch) {
189
+ const rect = selectedRect(state)
190
+ dispatch(addRow(state.tr, rect, rect.top))
191
+ }
192
+ return true
179
193
  }
180
194
 
181
195
  // :: (EditorState, dispatch: ?(tr: Transaction)) → bool
182
196
  // Add a table row after the selection.
183
197
  export function addRowAfter(state: EditorState, dispatch?: (tr: Transaction) => boolean) {
184
- if (!isInTable(state)) return false;
185
- if (dispatch) {
186
- const rect = selectedRect(state);
187
- dispatch(addRow(state.tr, rect, rect.bottom));
188
- }
189
- return true;
198
+ if (!isInTable(state))
199
+ return false
200
+ if (dispatch) {
201
+ const rect = selectedRect(state)
202
+ dispatch(addRow(state.tr, rect, rect.bottom))
203
+ }
204
+ return true
190
205
  }
191
206
 
192
207
  export function removeRow(tr: Transaction, { map, tableStart, table }: Rect, row: number) {
193
- map = map as TableMap;
194
- table = table as Node;
195
- tableStart = tableStart as number;
196
- let rowPos = 0;
197
- for (let i = 0; i < row; i++) rowPos += table.child(i).nodeSize;
198
- const nextRow = rowPos + table.child(row).nodeSize;
199
-
200
- const mapFrom = tr.mapping.maps.length;
201
- tr.delete(rowPos + tableStart, nextRow + tableStart);
202
-
203
- for (let col = 0, index = row * map.width; col < map.width; col++, index++) {
204
- const pos = map.map[index] as number;
205
- if (row > 0 && pos == map.map[index - map.width]) {
206
- // If this cell starts in the row above, simply reduce its rowspan
207
- const attrs = (table.nodeAt(pos) as Node).attrs;
208
- tr.setNodeMarkup(
209
- tr.mapping.slice(mapFrom).map(pos + tableStart),
210
- null,
211
- setAttr(attrs, 'rowspan', attrs['rowspan'] - 1),
212
- );
213
- col += attrs['colspan'] - 1;
214
- } else if (row < map.width && pos == map.map[index + map.width]) {
215
- // Else, if it continues in the row below, it has to be moved down
216
- const cell = table.nodeAt(pos) as Node;
217
- const copy = cell.type.create(setAttr(cell.attrs, 'rowspan', cell.attrs['rowspan'] - 1), cell.content);
218
- const newPos = map.positionAt(row + 1, col, table);
219
- tr.insert(tr.mapping.slice(mapFrom).map(tableStart + newPos), copy);
220
- col += cell.attrs['colspan'] - 1;
221
- }
208
+ map = map as TableMap
209
+ table = table as Node
210
+ tableStart = tableStart as number
211
+ let rowPos = 0
212
+ for (let i = 0; i < row; i++) rowPos += table.child(i).nodeSize
213
+ const nextRow = rowPos + table.child(row).nodeSize
214
+
215
+ const mapFrom = tr.mapping.maps.length
216
+ tr.delete(rowPos + tableStart, nextRow + tableStart)
217
+
218
+ for (let col = 0, index = row * map.width; col < map.width; col++, index++) {
219
+ const pos = map.map[index] as number
220
+ if (row > 0 && pos == map.map[index - map.width]) {
221
+ // If this cell starts in the row above, simply reduce its rowspan
222
+ const attrs = (table.nodeAt(pos) as Node).attrs
223
+ tr.setNodeMarkup(
224
+ tr.mapping.slice(mapFrom).map(pos + tableStart),
225
+ null,
226
+ setAttr(attrs, 'rowspan', attrs.rowspan - 1),
227
+ )
228
+ col += attrs.colspan - 1
222
229
  }
230
+ else if (row < map.width && pos == map.map[index + map.width]) {
231
+ // Else, if it continues in the row below, it has to be moved down
232
+ const cell = table.nodeAt(pos) as Node
233
+ const copy = cell.type.create(setAttr(cell.attrs, 'rowspan', cell.attrs.rowspan - 1), cell.content)
234
+ const newPos = map.positionAt(row + 1, col, table)
235
+ tr.insert(tr.mapping.slice(mapFrom).map(tableStart + newPos), copy)
236
+ col += cell.attrs.colspan - 1
237
+ }
238
+ }
223
239
  }
224
240
 
225
241
  // :: (EditorState, dispatch: ?(tr: Transaction)) → bool
226
242
  // Remove the selected rows from a table.
227
243
  export const deleteRow: Command = (state, dispatch) => {
228
- if (!isInTable(state)) return false;
229
- if (dispatch) {
230
- const rect = selectedRect(state) as Required<Rect>,
231
- tr = state.tr;
232
- if (rect.top == 0 && rect.bottom == rect.map.height) return false;
233
- for (let i = rect.bottom - 1; ; i--) {
234
- removeRow(tr, rect, i);
235
- if (i == rect.top) break;
236
- rect.table = rect.tableStart ? (tr.doc.nodeAt(rect.tableStart - 1) as Node) : tr.doc;
237
- rect.map = TableMap.get(rect.table);
238
- }
239
- dispatch(tr);
244
+ if (!isInTable(state))
245
+ return false
246
+ if (dispatch) {
247
+ const rect = selectedRect(state) as Required<Rect>
248
+ const tr = state.tr
249
+ if (rect.top == 0 && rect.bottom == rect.map.height)
250
+ return false
251
+ for (let i = rect.bottom - 1; ; i--) {
252
+ removeRow(tr, rect, i)
253
+ if (i == rect.top)
254
+ break
255
+ rect.table = rect.tableStart ? (tr.doc.nodeAt(rect.tableStart - 1) as Node) : tr.doc
256
+ rect.map = TableMap.get(rect.table)
240
257
  }
241
- return true;
242
- };
258
+ dispatch(tr)
259
+ }
260
+ return true
261
+ }
243
262
 
244
263
  function isEmpty(cell: Node) {
245
- const c = cell.content;
246
- return c.childCount == 1 && (c.firstChild as Node).isTextblock && (c.firstChild as Node).childCount == 0;
264
+ const c = cell.content
265
+ return c.childCount == 1 && (c.firstChild as Node).isTextblock && (c.firstChild as Node).childCount == 0
247
266
  }
248
267
 
249
268
  function cellsOverlapRectangle({ width, height, map }: TableMap, rect: Rect) {
250
- let indexTop = rect.top * width + rect.left,
251
- indexLeft = indexTop;
252
- let indexBottom = (rect.bottom - 1) * width + rect.left,
253
- indexRight = indexTop + (rect.right - rect.left - 1);
254
- for (let i = rect.top; i < rect.bottom; i++) {
255
- if (
256
- (rect.left > 0 && map[indexLeft] == map[indexLeft - 1]) ||
257
- (rect.right < width && map[indexRight] == map[indexRight + 1])
258
- )
259
- return true;
260
- indexLeft += width;
261
- indexRight += width;
262
- }
263
- for (let i = rect.left; i < rect.right; i++) {
264
- if (
265
- (rect.top > 0 && map[indexTop] == map[indexTop - width]) ||
266
- (rect.bottom < height && map[indexBottom] == map[indexBottom + width])
267
- )
268
- return true;
269
- indexTop++;
270
- indexBottom++;
271
- }
272
- return false;
269
+ let indexTop = rect.top * width + rect.left
270
+ let indexLeft = indexTop
271
+ let indexBottom = (rect.bottom - 1) * width + rect.left
272
+ let indexRight = indexTop + (rect.right - rect.left - 1)
273
+ for (let i = rect.top; i < rect.bottom; i++) {
274
+ if (
275
+ (rect.left > 0 && map[indexLeft] == map[indexLeft - 1])
276
+ || (rect.right < width && map[indexRight] == map[indexRight + 1])
277
+ )
278
+ return true
279
+ indexLeft += width
280
+ indexRight += width
281
+ }
282
+ for (let i = rect.left; i < rect.right; i++) {
283
+ if (
284
+ (rect.top > 0 && map[indexTop] == map[indexTop - width])
285
+ || (rect.bottom < height && map[indexBottom] == map[indexBottom + width])
286
+ )
287
+ return true
288
+ indexTop++
289
+ indexBottom++
290
+ }
291
+ return false
273
292
  }
274
293
 
275
294
  // :: (EditorState, dispatch: ?(tr: Transaction)) → bool
276
295
  // Merge the selected cells into a single cell. Only available when
277
296
  // the selected cells' outline forms a rectangle.
278
297
  export function mergeCells(state: EditorState, dispatch?: (tr: Transaction) => boolean) {
279
- const sel = state.selection;
280
- if (!(sel instanceof CellSelection) || sel.$anchorCell.pos == sel.$headCell.pos) return false;
281
- const rect = selectedRect(state) as Required<Rect>,
282
- { map } = rect;
283
- if (cellsOverlapRectangle(map as TableMap, rect)) return false;
284
- if (dispatch) {
285
- const tr = state.tr,
286
- seen: Record<number, boolean> = {};
287
- let content = Fragment.empty,
288
- mergedPos,
289
- mergedCell;
290
- for (let row = rect.top; row < rect.bottom; row++) {
291
- for (let col = rect.left; col < rect.right; col++) {
292
- const cellPos = map.map[row * map.width + col] as number,
293
- cell = rect.table.nodeAt(cellPos) as Node;
294
- if (seen[cellPos]) continue;
295
- seen[cellPos] = true;
296
- if (mergedPos == null) {
297
- mergedPos = cellPos;
298
- mergedCell = cell;
299
- } else {
300
- if (!isEmpty(cell)) content = content.append(cell.content);
301
- const mapped = tr.mapping.map(cellPos + rect.tableStart);
302
- tr.delete(mapped, mapped + cell.nodeSize);
303
- }
304
- }
298
+ const sel = state.selection
299
+ if (!(sel instanceof CellSelection) || sel.$anchorCell.pos == sel.$headCell.pos)
300
+ return false
301
+ const rect = selectedRect(state) as Required<Rect>
302
+ const { map } = rect
303
+ if (cellsOverlapRectangle(map as TableMap, rect))
304
+ return false
305
+ if (dispatch) {
306
+ const tr = state.tr
307
+ const seen: Record<number, boolean> = {}
308
+ let content = Fragment.empty
309
+ let mergedPos
310
+ let mergedCell
311
+ for (let row = rect.top; row < rect.bottom; row++) {
312
+ for (let col = rect.left; col < rect.right; col++) {
313
+ const cellPos = map.map[row * map.width + col] as number
314
+ const cell = rect.table.nodeAt(cellPos) as Node
315
+ if (seen[cellPos])
316
+ continue
317
+ seen[cellPos] = true
318
+ if (mergedPos == null) {
319
+ mergedPos = cellPos
320
+ mergedCell = cell
305
321
  }
306
- mergedCell = mergedCell as Node;
307
- mergedPos = mergedPos as number;
308
- tr.setNodeMarkup(
309
- mergedPos + rect.tableStart,
310
- null,
311
- setAttr(
312
- addColSpan(
313
- mergedCell.attrs,
314
- mergedCell.attrs['colspan'],
315
- rect.right - rect.left - mergedCell.attrs['colspan'],
316
- ),
317
- 'rowspan',
318
- rect.bottom - rect.top,
319
- ),
320
- );
321
- if (content.size) {
322
- const end = mergedPos + 1 + mergedCell.content.size;
323
- const start = isEmpty(mergedCell) ? mergedPos + 1 : end;
324
- tr.replaceWith(start + rect.tableStart, end + rect.tableStart, content);
322
+ else {
323
+ if (!isEmpty(cell))
324
+ content = content.append(cell.content)
325
+ const mapped = tr.mapping.map(cellPos + rect.tableStart)
326
+ tr.delete(mapped, mapped + cell.nodeSize)
325
327
  }
326
- tr.setSelection(new CellSelection(tr.doc.resolve(mergedPos + rect.tableStart)));
327
- dispatch(tr);
328
+ }
328
329
  }
329
- return true;
330
+ mergedCell = mergedCell as Node
331
+ mergedPos = mergedPos as number
332
+ tr.setNodeMarkup(
333
+ mergedPos + rect.tableStart,
334
+ null,
335
+ setAttr(
336
+ addColSpan(
337
+ mergedCell.attrs,
338
+ mergedCell.attrs.colspan,
339
+ rect.right - rect.left - mergedCell.attrs.colspan,
340
+ ),
341
+ 'rowspan',
342
+ rect.bottom - rect.top,
343
+ ),
344
+ )
345
+ if (content.size) {
346
+ const end = mergedPos + 1 + mergedCell.content.size
347
+ const start = isEmpty(mergedCell) ? mergedPos + 1 : end
348
+ tr.replaceWith(start + rect.tableStart, end + rect.tableStart, content)
349
+ }
350
+ tr.setSelection(new CellSelection(tr.doc.resolve(mergedPos + rect.tableStart)))
351
+ dispatch(tr)
352
+ }
353
+ return true
330
354
  }
331
355
  // :: (EditorState, dispatch: ?(tr: Transaction)) → bool
332
356
  // Split a selected cell, whose rowpan or colspan is greater than one,
333
357
  // into smaller cells. Use the first cell type for the new cells.
334
358
  export function splitCell(state: EditorState, dispatch?: (tr: Transaction) => boolean) {
335
- const nodeTypes = tableNodeTypes(state.schema);
336
- return splitCellWithType(({ node }) => {
337
- return nodeTypes[node.type.spec['tableRole']];
338
- })(state, dispatch);
359
+ const nodeTypes = tableNodeTypes(state.schema)
360
+ return splitCellWithType(({ node }) => {
361
+ return nodeTypes[node.type.spec.tableRole]
362
+ })(state, dispatch)
339
363
  }
340
364
 
341
365
  // :: (getCellType: ({ row: number, col: number, node: Node}) → NodeType) → (EditorState, dispatch: ?(tr: Transaction)) → bool
342
366
  // Split a selected cell, whose rowpan or colspan is greater than one,
343
367
  // into smaller cells with the cell type (th, td) returned by getType function.
344
368
  export function splitCellWithType(getCellType: (pos: { row: number; col: number; node: Node }) => NodeType) {
345
- return (state: EditorState, dispatch?: (tr: Transaction) => boolean) => {
346
- const sel = state.selection;
347
- let cellNode, cellPos;
348
- if (!(sel instanceof CellSelection)) {
349
- cellNode = cellWrapping(sel.$from);
350
- if (!cellNode) return false;
351
- cellPos = (cellAround(sel.$from) as ResolvedPos).pos;
352
- } else {
353
- if (sel.$anchorCell.pos != sel.$headCell.pos) return false;
354
- cellNode = sel.$anchorCell.nodeAfter as Node;
355
- cellPos = sel.$anchorCell.pos;
356
- }
357
- if (cellNode.attrs['colspan'] == 1 && cellNode.attrs['rowspan'] == 1) {
358
- return false;
359
- }
360
- if (dispatch) {
361
- let baseAttrs = cellNode.attrs;
362
- const attrs = [],
363
- colwidth = baseAttrs['colwidth'];
364
- if (baseAttrs['rowspan'] > 1) baseAttrs = setAttr(baseAttrs, 'rowspan', 1);
365
- if (baseAttrs['colspan'] > 1) baseAttrs = setAttr(baseAttrs, 'colspan', 1);
366
- const rect = selectedRect(state) as Required<Rect>,
367
- tr = state.tr;
368
- for (let i = 0; i < rect.right - rect.left; i++)
369
- attrs.push(
370
- colwidth
371
- ? setAttr(baseAttrs, 'colwidth', colwidth && colwidth[i] ? [colwidth[i]] : null)
372
- : baseAttrs,
373
- );
374
- let lastCell;
375
- for (let row = rect.top; row < rect.bottom; row++) {
376
- let pos = rect.map.positionAt(row, rect.left, rect.table);
377
- if (row == rect.top) pos += cellNode.nodeSize;
378
- for (let col = rect.left, i = 0; col < rect.right; col++, i++) {
379
- if (col == rect.left && row == rect.top) continue;
380
- tr.insert(
381
- (lastCell = tr.mapping.map(pos + rect.tableStart, 1)),
382
- getCellType({ node: cellNode, row, col }).createAndFill(attrs[i]) as Node,
383
- );
384
- }
385
- }
386
- tr.setNodeMarkup(cellPos, getCellType({ node: cellNode, row: rect.top, col: rect.left }), attrs[0]);
387
- if (sel instanceof CellSelection) {
388
- let pos: ResolvedPos | undefined = undefined;
389
- if (lastCell) {
390
- pos = tr.doc.resolve(lastCell);
391
- }
392
- tr.setSelection(new CellSelection(tr.doc.resolve(sel.$anchorCell.pos), pos));
393
- }
394
- dispatch(tr);
369
+ return (state: EditorState, dispatch?: (tr: Transaction) => boolean) => {
370
+ const sel = state.selection
371
+ let cellNode, cellPos
372
+ if (!(sel instanceof CellSelection)) {
373
+ cellNode = cellWrapping(sel.$from)
374
+ if (!cellNode)
375
+ return false
376
+ cellPos = (cellAround(sel.$from) as ResolvedPos).pos
377
+ }
378
+ else {
379
+ if (sel.$anchorCell.pos != sel.$headCell.pos)
380
+ return false
381
+ cellNode = sel.$anchorCell.nodeAfter as Node
382
+ cellPos = sel.$anchorCell.pos
383
+ }
384
+ if (cellNode.attrs.colspan == 1 && cellNode.attrs.rowspan == 1)
385
+ return false
386
+
387
+ if (dispatch) {
388
+ let baseAttrs = cellNode.attrs
389
+ const attrs = []
390
+ const colwidth = baseAttrs.colwidth
391
+ if (baseAttrs.rowspan > 1)
392
+ baseAttrs = setAttr(baseAttrs, 'rowspan', 1)
393
+ if (baseAttrs.colspan > 1)
394
+ baseAttrs = setAttr(baseAttrs, 'colspan', 1)
395
+ const rect = selectedRect(state) as Required<Rect>
396
+ const tr = state.tr
397
+ for (let i = 0; i < rect.right - rect.left; i++) {
398
+ attrs.push(
399
+ colwidth
400
+ ? setAttr(baseAttrs, 'colwidth', colwidth && colwidth[i] ? [colwidth[i]] : null)
401
+ : baseAttrs,
402
+ )
403
+ }
404
+ let lastCell
405
+ for (let row = rect.top; row < rect.bottom; row++) {
406
+ let pos = rect.map.positionAt(row, rect.left, rect.table)
407
+ if (row == rect.top)
408
+ pos += cellNode.nodeSize
409
+ for (let col = rect.left, i = 0; col < rect.right; col++, i++) {
410
+ if (col == rect.left && row == rect.top)
411
+ continue
412
+ tr.insert(
413
+ (lastCell = tr.mapping.map(pos + rect.tableStart, 1)),
414
+ getCellType({ node: cellNode, row, col }).createAndFill(attrs[i]) as Node,
415
+ )
395
416
  }
396
- return true;
397
- };
417
+ }
418
+ tr.setNodeMarkup(cellPos, getCellType({ node: cellNode, row: rect.top, col: rect.left }), attrs[0])
419
+ if (sel instanceof CellSelection) {
420
+ let pos: ResolvedPos | undefined
421
+ if (lastCell)
422
+ pos = tr.doc.resolve(lastCell)
423
+
424
+ tr.setSelection(new CellSelection(tr.doc.resolve(sel.$anchorCell.pos), pos))
425
+ }
426
+ dispatch(tr)
427
+ }
428
+ return true
429
+ }
398
430
  }
399
431
 
400
432
  // :: (string, any) → (EditorState, dispatch: ?(tr: Transaction)) → bool
@@ -402,150 +434,161 @@ export function splitCellWithType(getCellType: (pos: { row: number; col: number;
402
434
  // and is only available when the currently selected cell doesn't
403
435
  // already have that attribute set to that value.
404
436
  export function setCellAttr<T>(name: string, value: T): Command {
405
- return (state, dispatch) => {
406
- if (!isInTable(state)) return false;
407
- const $cell = selectionCell(state) as ResolvedPos;
408
- if (($cell.nodeAfter as Node).attrs[name] === value) return false;
409
- if (dispatch) {
410
- const tr = state.tr;
411
- if (state.selection instanceof CellSelection)
412
- state.selection.forEachCell((node, pos) => {
413
- if (node.attrs[name] !== value) tr.setNodeMarkup(pos, null, setAttr(node.attrs, name, value));
414
- });
415
- else tr.setNodeMarkup($cell.pos, null, setAttr(($cell.nodeAfter as Node).attrs, name, value));
416
- dispatch(tr);
417
- }
418
- return true;
419
- };
437
+ return (state, dispatch) => {
438
+ if (!isInTable(state))
439
+ return false
440
+ const $cell = selectionCell(state) as ResolvedPos
441
+ if (($cell.nodeAfter as Node).attrs[name] === value)
442
+ return false
443
+ if (dispatch) {
444
+ const tr = state.tr
445
+ if (state.selection instanceof CellSelection) {
446
+ state.selection.forEachCell((node, pos) => {
447
+ if (node.attrs[name] !== value)
448
+ tr.setNodeMarkup(pos, null, setAttr(node.attrs, name, value))
449
+ })
450
+ }
451
+ else { tr.setNodeMarkup($cell.pos, null, setAttr(($cell.nodeAfter as Node).attrs, name, value)) }
452
+ dispatch(tr)
453
+ }
454
+ return true
455
+ }
420
456
  }
421
457
 
422
458
  function isHeaderEnabledByType(type: string, rect: Required<Rect>, types: Record<string, NodeSpec>) {
423
- // Get cell positions for first row or first column
424
- const cellPositions = rect.map.cellsInRect({
425
- left: 0,
426
- top: 0,
427
- right: type == 'row' ? rect.map.width : 1,
428
- bottom: type == 'column' ? rect.map.height : 1,
429
- });
430
-
431
- for (let i = 0; i < cellPositions.length; i++) {
432
- const cell = rect.table.nodeAt(cellPositions[i] as number);
433
- if (cell && cell.type !== types['header_cell']) {
434
- return false;
435
- }
436
- }
437
-
438
- return true;
459
+ // Get cell positions for first row or first column
460
+ const cellPositions = rect.map.cellsInRect({
461
+ left: 0,
462
+ top: 0,
463
+ right: type == 'row' ? rect.map.width : 1,
464
+ bottom: type == 'column' ? rect.map.height : 1,
465
+ })
466
+
467
+ for (let i = 0; i < cellPositions.length; i++) {
468
+ const cell = rect.table.nodeAt(cellPositions[i] as number)
469
+ if (cell && cell.type !== types.header_cell)
470
+ return false
471
+ }
472
+
473
+ return true
439
474
  }
440
475
 
441
476
  // Toggles between row/column header and normal cells (Only applies to first row/column).
442
477
  // For deprecated behavior pass `useDeprecatedLogic` in options with true.
443
478
  export function toggleHeader(type: string) {
444
- return function (state: EditorState, dispatch?: (tr: Transaction) => boolean) {
445
- if (!isInTable(state)) return false;
446
- if (dispatch) {
447
- const types = tableNodeTypes(state.schema);
448
- const rect = selectedRect(state),
449
- tr = state.tr;
479
+ return function (state: EditorState, dispatch?: (tr: Transaction) => boolean) {
480
+ if (!isInTable(state))
481
+ return false
482
+ if (dispatch) {
483
+ const types = tableNodeTypes(state.schema)
484
+ const rect = selectedRect(state)
485
+ const tr = state.tr
450
486
 
451
- const isHeaderRowEnabled = isHeaderEnabledByType('row', rect, types);
452
- const isHeaderColumnEnabled = isHeaderEnabledByType('column', rect, types);
487
+ const isHeaderRowEnabled = isHeaderEnabledByType('row', rect, types)
488
+ const isHeaderColumnEnabled = isHeaderEnabledByType('column', rect, types)
453
489
 
454
- const isHeaderEnabled =
455
- type === 'column' ? isHeaderRowEnabled : type === 'row' ? isHeaderColumnEnabled : false;
490
+ const isHeaderEnabled
491
+ = type === 'column' ? isHeaderRowEnabled : type === 'row' ? isHeaderColumnEnabled : false
456
492
 
457
- const selectionStartsAt = isHeaderEnabled ? 1 : 0;
493
+ const selectionStartsAt = isHeaderEnabled ? 1 : 0
458
494
 
459
- const cellsRect =
460
- type == 'column'
461
- ? new Rect(0, selectionStartsAt, 1, rect.map.height)
462
- : type == 'row'
495
+ const cellsRect
496
+ = type == 'column'
497
+ ? new Rect(0, selectionStartsAt, 1, rect.map.height)
498
+ : type == 'row'
463
499
  ? new Rect(selectionStartsAt, 0, rect.map.width, 1)
464
- : rect;
465
-
466
- const newType =
467
- type == 'column'
468
- ? isHeaderColumnEnabled
469
- ? types.cell
470
- : types.header_cell
471
- : type == 'row'
500
+ : rect
501
+
502
+ const newType
503
+ = type == 'column'
504
+ ? isHeaderColumnEnabled
505
+ ? types.cell
506
+ : types.header_cell
507
+ : type == 'row'
472
508
  ? isHeaderRowEnabled
473
- ? types.cell
474
- : types.header_cell
475
- : types.cell;
509
+ ? types.cell
510
+ : types.header_cell
511
+ : types.cell
476
512
 
477
- rect.map.cellsInRect(cellsRect).forEach((relativeCellPos) => {
478
- const cellPos = relativeCellPos + rect.tableStart;
479
- const cell = tr.doc.nodeAt(cellPos);
513
+ rect.map.cellsInRect(cellsRect).forEach((relativeCellPos) => {
514
+ const cellPos = relativeCellPos + rect.tableStart
515
+ const cell = tr.doc.nodeAt(cellPos)
480
516
 
481
- if (cell) {
482
- tr.setNodeMarkup(cellPos, newType, cell.attrs);
483
- }
484
- });
517
+ if (cell)
518
+ tr.setNodeMarkup(cellPos, newType, cell.attrs)
519
+ })
485
520
 
486
- dispatch(tr);
487
- }
488
- return true;
489
- };
521
+ dispatch(tr)
522
+ }
523
+ return true
524
+ }
490
525
  }
491
526
 
492
527
  // :: (EditorState, dispatch: ?(tr: Transaction)) → bool
493
528
  // Toggles whether the selected row contains header cells.
494
- export const toggleHeaderRow = toggleHeader('row');
529
+ export const toggleHeaderRow = toggleHeader('row')
495
530
 
496
531
  // :: (EditorState, dispatch: ?(tr: Transaction)) → bool
497
532
  // Toggles whether the selected column contains header cells.
498
- export const toggleHeaderColumn = toggleHeader('column');
533
+ export const toggleHeaderColumn = toggleHeader('column')
499
534
 
500
535
  // :: (EditorState, dispatch: ?(tr: Transaction)) → bool
501
536
  // Toggles whether the selected cells are header cells.
502
- export const toggleHeaderCell = toggleHeader('cell');
537
+ export const toggleHeaderCell = toggleHeader('cell')
503
538
 
504
539
  function findNextCell($cell: ResolvedPos, dir: number) {
505
- if (dir < 0) {
506
- const before = $cell.nodeBefore;
507
- if (before) return $cell.pos - before.nodeSize;
508
- for (let row = $cell.index(-1) - 1, rowEnd = $cell.before(); row >= 0; row--) {
509
- const rowNode = $cell.node(-1).child(row);
510
- if (rowNode.childCount) return rowEnd - 1 - (rowNode.lastChild as Node).nodeSize;
511
- rowEnd -= rowNode.nodeSize;
512
- }
513
- } else {
514
- if ($cell.index() < $cell.parent.childCount - 1) return $cell.pos + ($cell.nodeAfter as Node).nodeSize;
515
- const table = $cell.node(-1);
516
- for (let row = $cell.indexAfter(-1), rowStart = $cell.after(); row < table.childCount; row++) {
517
- const rowNode = table.child(row);
518
- if (rowNode.childCount) return rowStart + 1;
519
- rowStart += rowNode.nodeSize;
520
- }
540
+ if (dir < 0) {
541
+ const before = $cell.nodeBefore
542
+ if (before)
543
+ return $cell.pos - before.nodeSize
544
+ for (let row = $cell.index(-1) - 1, rowEnd = $cell.before(); row >= 0; row--) {
545
+ const rowNode = $cell.node(-1).child(row)
546
+ if (rowNode.childCount)
547
+ return rowEnd - 1 - (rowNode.lastChild as Node).nodeSize
548
+ rowEnd -= rowNode.nodeSize
549
+ }
550
+ }
551
+ else {
552
+ if ($cell.index() < $cell.parent.childCount - 1)
553
+ return $cell.pos + ($cell.nodeAfter as Node).nodeSize
554
+ const table = $cell.node(-1)
555
+ for (let row = $cell.indexAfter(-1), rowStart = $cell.after(); row < table.childCount; row++) {
556
+ const rowNode = table.child(row)
557
+ if (rowNode.childCount)
558
+ return rowStart + 1
559
+ rowStart += rowNode.nodeSize
521
560
  }
522
- return;
561
+ }
562
+ return undefined
523
563
  }
524
564
 
525
565
  // Returns a command for selecting the next (direction=1) or previous
526
566
  // (direction=-1) cell in a table.
527
567
  export function goToNextCell(direction: number): Command {
528
- return (state, dispatch) => {
529
- if (!isInTable(state)) return false;
530
- const cell = findNextCell(selectionCell(state) as ResolvedPos, direction);
531
- if (cell == null) return false;
532
- if (dispatch) {
533
- const $cell = state.doc.resolve(cell);
534
- dispatch(state.tr.setSelection(TextSelection.between($cell, moveCellForward($cell))).scrollIntoView());
535
- }
536
- return true;
537
- };
568
+ return (state, dispatch) => {
569
+ if (!isInTable(state))
570
+ return false
571
+ const cell = findNextCell(selectionCell(state) as ResolvedPos, direction)
572
+ if (cell == null)
573
+ return false
574
+ if (dispatch) {
575
+ const $cell = state.doc.resolve(cell)
576
+ dispatch(state.tr.setSelection(TextSelection.between($cell, moveCellForward($cell))).scrollIntoView())
577
+ }
578
+ return true
579
+ }
538
580
  }
539
581
 
540
582
  // Deletes the table around the selection, if any.
541
583
  export const deleteTable: Command = (state, dispatch) => {
542
- const $pos = state.selection.$anchor;
543
- for (let d = $pos.depth; d > 0; d--) {
544
- const node = $pos.node(d);
545
- if (node.type.spec['tableRole'] == 'table') {
546
- if (dispatch) dispatch(state.tr.delete($pos.before(d), $pos.after(d)).scrollIntoView());
547
- return true;
548
- }
584
+ const $pos = state.selection.$anchor
585
+ for (let d = $pos.depth; d > 0; d--) {
586
+ const node = $pos.node(d)
587
+ if (node.type.spec.tableRole == 'table') {
588
+ if (dispatch)
589
+ dispatch(state.tr.delete($pos.before(d), $pos.after(d)).scrollIntoView())
590
+ return true
549
591
  }
550
- return false;
551
- };
592
+ }
593
+ return false
594
+ }