@milkdown/preset-gfm 6.5.2 → 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 +649 -607
  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 -34
  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,19 +1,22 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
2
 
3
- import { Fragment, Node, ResolvedPos, Slice } from '@milkdown/prose/model';
3
+ import type { Node, ResolvedPos } from '@milkdown/prose/model'
4
+ import { Fragment, Slice } from '@milkdown/prose/model'
5
+ import type {
6
+ EditorState,
7
+ Transaction,
8
+ } from '@milkdown/prose/state'
4
9
  import {
5
- EditorState,
6
- NodeSelection,
7
- Selection,
8
- SelectionRange,
9
- TextSelection,
10
- Transaction,
11
- } from '@milkdown/prose/state';
12
- import { Mappable } from '@milkdown/prose/transform';
13
- import { Decoration, DecorationSet } from '@milkdown/prose/view';
14
-
15
- import { TableMap } from './table-map';
16
- import { inSameTable, pointsAtCell, removeColSpan, setAttr } from './util';
10
+ NodeSelection,
11
+ Selection,
12
+ SelectionRange,
13
+ TextSelection,
14
+ } from '@milkdown/prose/state'
15
+ import type { Mappable } from '@milkdown/prose/transform'
16
+ import { Decoration, DecorationSet } from '@milkdown/prose/view'
17
+
18
+ import { TableMap } from './table-map'
19
+ import { inSameTable, pointsAtCell, removeColSpan, setAttr } from './util'
17
20
 
18
21
  // ::- A [`Selection`](http://prosemirror.net/docs/ref/#state.Selection)
19
22
  // subclass that represents a cell selection spanning part of a table.
@@ -21,332 +24,358 @@ import { inSameTable, pointsAtCell, removeColSpan, setAttr } from './util';
21
24
  // selects across cells, and will be drawn by giving selected cells a
22
25
  // `selectedCell` CSS class.
23
26
  export class CellSelection extends Selection {
24
- // :: (ResolvedPos, ?ResolvedPos)
25
- // A table selection is identified by its anchor and head cells. The
26
- // positions given to this constructor should point _before_ two
27
- // cells in the same table. They may be the same, to select a single
28
- // cell.
29
- constructor(public $anchorCell: ResolvedPos, public $headCell = $anchorCell) {
30
- const table = $anchorCell.node(-1),
31
- map = TableMap.get(table),
32
- start = $anchorCell.start(-1);
33
- const rect = map.rectBetween($anchorCell.pos - start, $headCell.pos - start);
34
- const doc = $anchorCell.node(0);
35
- const cells = map.cellsInRect(rect).filter((p) => p != $headCell.pos - start);
36
- // Make the head cell the first range, so that it counts as the
37
- // primary part of the selection
38
- cells.unshift($headCell.pos - start);
39
- const ranges = cells.map((pos) => {
40
- const cell = table.nodeAt(pos) as Node,
41
- from = pos + start + 1;
42
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
- return new (SelectionRange as any)(doc.resolve(from), doc.resolve(from + cell.content.size));
44
- });
45
- super(ranges[0].$from, ranges[0].$to, ranges);
46
- // :: ResolvedPos
47
- // A resolved position pointing _in front of_ the anchor cell (the one
48
- // that doesn't move when extending the selection).
49
- this.$anchorCell = $anchorCell;
50
- // :: ResolvedPos
51
- // A resolved position pointing in front of the head cell (the one
52
- // moves when extending the selection).
53
- this.$headCell = $headCell;
27
+ // :: (ResolvedPos, ?ResolvedPos)
28
+ // A table selection is identified by its anchor and head cells. The
29
+ // positions given to this constructor should point _before_ two
30
+ // cells in the same table. They may be the same, to select a single
31
+ // cell.
32
+ constructor(public $anchorCell: ResolvedPos, public $headCell = $anchorCell) {
33
+ const table = $anchorCell.node(-1)
34
+ const map = TableMap.get(table)
35
+ const start = $anchorCell.start(-1)
36
+ const rect = map.rectBetween($anchorCell.pos - start, $headCell.pos - start)
37
+ const doc = $anchorCell.node(0)
38
+ const cells = map.cellsInRect(rect).filter(p => p != $headCell.pos - start)
39
+ // Make the head cell the first range, so that it counts as the
40
+ // primary part of the selection
41
+ cells.unshift($headCell.pos - start)
42
+ const ranges = cells.map((pos) => {
43
+ const cell = table.nodeAt(pos) as Node
44
+ const from = pos + start + 1
45
+
46
+ return new (SelectionRange as any)(doc.resolve(from), doc.resolve(from + cell.content.size))
47
+ })
48
+ super(ranges[0].$from, ranges[0].$to, ranges)
49
+ // :: ResolvedPos
50
+ // A resolved position pointing _in front of_ the anchor cell (the one
51
+ // that doesn't move when extending the selection).
52
+ this.$anchorCell = $anchorCell
53
+ // :: ResolvedPos
54
+ // A resolved position pointing in front of the head cell (the one
55
+ // moves when extending the selection).
56
+ this.$headCell = $headCell
57
+ }
58
+
59
+ map(doc: Node, mapping: Mappable): Selection {
60
+ const $anchorCell = doc.resolve(mapping.map(this.$anchorCell.pos))
61
+ const $headCell = doc.resolve(mapping.map(this.$headCell.pos))
62
+ if (pointsAtCell($anchorCell) && pointsAtCell($headCell) && inSameTable($anchorCell, $headCell)) {
63
+ const tableChanged = this.$anchorCell.node(-1) != $anchorCell.node(-1)
64
+ if (tableChanged && this.isRowSelection())
65
+ return CellSelection.rowSelection($anchorCell, $headCell)
66
+ else if (tableChanged && this.isColSelection())
67
+ return CellSelection.colSelection($anchorCell, $headCell)
68
+ else return new CellSelection($anchorCell, $headCell)
54
69
  }
70
+ return TextSelection.between($anchorCell, $headCell)
71
+ }
55
72
 
56
- map(doc: Node, mapping: Mappable): Selection {
57
- const $anchorCell = doc.resolve(mapping.map(this.$anchorCell.pos));
58
- const $headCell = doc.resolve(mapping.map(this.$headCell.pos));
59
- if (pointsAtCell($anchorCell) && pointsAtCell($headCell) && inSameTable($anchorCell, $headCell)) {
60
- const tableChanged = this.$anchorCell.node(-1) != $anchorCell.node(-1);
61
- if (tableChanged && this.isRowSelection()) return CellSelection.rowSelection($anchorCell, $headCell);
62
- else if (tableChanged && this.isColSelection()) return CellSelection.colSelection($anchorCell, $headCell);
63
- else return new CellSelection($anchorCell, $headCell);
73
+ // :: () Slice
74
+ // Returns a rectangular slice of table rows containing the selected
75
+ // cells.
76
+ override content(): Slice {
77
+ const table = this.$anchorCell.node(-1)
78
+ const map = TableMap.get(table)
79
+ const start = this.$anchorCell.start(-1)
80
+ const rect = map.rectBetween(this.$anchorCell.pos - start, this.$headCell.pos - start)
81
+ const seen: Record<number, boolean> = {}
82
+ const rows = []
83
+ for (let row = rect.top; row < rect.bottom; row++) {
84
+ const rowContent = []
85
+ for (let index = row * map.width + rect.left, col = rect.left; col < rect.right; col++, index++) {
86
+ const pos = map.map[index] as number
87
+ if (!seen[pos]) {
88
+ seen[pos] = true
89
+ const cellRect = map.findCell(pos)
90
+ let cell = table.nodeAt(pos) as Node
91
+ const extraLeft = rect.left - cellRect.left
92
+ const extraRight = cellRect.right - rect.right
93
+ if (extraLeft > 0 || extraRight > 0) {
94
+ let attrs = cell.attrs
95
+ if (extraLeft > 0)
96
+ attrs = removeColSpan(attrs, 0, extraLeft)
97
+ if (extraRight > 0)
98
+ attrs = removeColSpan(attrs, attrs.colspan - extraRight, extraRight)
99
+ if (cellRect.left < rect.left)
100
+ cell = cell.type.createAndFill(attrs) as Node
101
+ else cell = cell.type.create(attrs, cell.content)
102
+ }
103
+ if (cellRect.top < rect.top || cellRect.bottom > rect.bottom) {
104
+ const attrs = setAttr(
105
+ cell.attrs,
106
+ 'rowspan',
107
+ Math.min(cellRect.bottom, rect.bottom) - Math.max(cellRect.top, rect.top),
108
+ )
109
+ if (cellRect.top < rect.top)
110
+ cell = cell.type.createAndFill(attrs) as Node
111
+ else cell = cell.type.create(attrs, cell.content)
112
+ }
113
+ rowContent.push(cell)
64
114
  }
65
- return TextSelection.between($anchorCell, $headCell);
115
+ }
116
+ rows.push(table.child(row).copy(Fragment.from(rowContent)))
66
117
  }
67
118
 
68
- // :: () Slice
69
- // Returns a rectangular slice of table rows containing the selected
70
- // cells.
71
- override content(): Slice {
72
- const table = this.$anchorCell.node(-1),
73
- map = TableMap.get(table),
74
- start = this.$anchorCell.start(-1);
75
- const rect = map.rectBetween(this.$anchorCell.pos - start, this.$headCell.pos - start);
76
- const seen: Record<number, boolean> = {},
77
- rows = [];
78
- for (let row = rect.top; row < rect.bottom; row++) {
79
- const rowContent = [];
80
- for (let index = row * map.width + rect.left, col = rect.left; col < rect.right; col++, index++) {
81
- const pos = map.map[index] as number;
82
- if (!seen[pos]) {
83
- seen[pos] = true;
84
- const cellRect = map.findCell(pos);
85
- let cell = table.nodeAt(pos) as Node;
86
- const extraLeft = rect.left - cellRect.left,
87
- extraRight = cellRect.right - rect.right;
88
- if (extraLeft > 0 || extraRight > 0) {
89
- let attrs = cell.attrs;
90
- if (extraLeft > 0) attrs = removeColSpan(attrs, 0, extraLeft);
91
- if (extraRight > 0) attrs = removeColSpan(attrs, attrs['colspan'] - extraRight, extraRight);
92
- if (cellRect.left < rect.left) cell = cell.type.createAndFill(attrs) as Node;
93
- else cell = cell.type.create(attrs, cell.content);
94
- }
95
- if (cellRect.top < rect.top || cellRect.bottom > rect.bottom) {
96
- const attrs = setAttr(
97
- cell.attrs,
98
- 'rowspan',
99
- Math.min(cellRect.bottom, rect.bottom) - Math.max(cellRect.top, rect.top),
100
- );
101
- if (cellRect.top < rect.top) cell = cell.type.createAndFill(attrs) as Node;
102
- else cell = cell.type.create(attrs, cell.content);
103
- }
104
- rowContent.push(cell);
105
- }
106
- }
107
- rows.push(table.child(row).copy(Fragment.from(rowContent)));
108
- }
119
+ const fragment = this.isColSelection() && this.isRowSelection() ? table : rows
120
+ return new Slice(Fragment.from(fragment), 1, 1)
121
+ }
109
122
 
110
- const fragment = this.isColSelection() && this.isRowSelection() ? table : rows;
111
- return new Slice(Fragment.from(fragment), 1, 1);
123
+ override replace(tr: Transaction, content = Slice.empty) {
124
+ const mapFrom = tr.steps.length
125
+ const ranges = this.ranges
126
+ for (let i = 0; i < ranges.length; i++) {
127
+ const { $from, $to } = ranges[i] as SelectionRange
128
+ const mapping = tr.mapping.slice(mapFrom)
129
+ tr.replace(mapping.map($from.pos), mapping.map($to.pos), i ? Slice.empty : content)
112
130
  }
131
+ const sel = Selection.findFrom(tr.doc.resolve(tr.mapping.slice(mapFrom).map(this.to)), -1)
132
+ if (sel)
133
+ tr.setSelection(sel)
134
+ }
113
135
 
114
- override replace(tr: Transaction, content = Slice.empty) {
115
- const mapFrom = tr.steps.length,
116
- ranges = this.ranges;
117
- for (let i = 0; i < ranges.length; i++) {
118
- const { $from, $to } = ranges[i] as SelectionRange,
119
- mapping = tr.mapping.slice(mapFrom);
120
- tr.replace(mapping.map($from.pos), mapping.map($to.pos), i ? Slice.empty : content);
121
- }
122
- const sel = Selection.findFrom(tr.doc.resolve(tr.mapping.slice(mapFrom).map(this.to)), -1);
123
- if (sel) tr.setSelection(sel);
124
- }
136
+ override replaceWith(tr: Transaction, node: Node) {
137
+ this.replace(tr, new Slice(Fragment.from(node), 0, 0))
138
+ }
125
139
 
126
- override replaceWith(tr: Transaction, node: Node) {
127
- this.replace(tr, new Slice(Fragment.from(node), 0, 0));
128
- }
140
+ forEachCell(f: (node: Node, index: number) => void) {
141
+ const table = this.$anchorCell.node(-1)
142
+ const map = TableMap.get(table)
143
+ const start = this.$anchorCell.start(-1)
144
+ const cells = map.cellsInRect(map.rectBetween(this.$anchorCell.pos - start, this.$headCell.pos - start))
145
+ for (let i = 0; i < cells.length; i++)
146
+ f(table.nodeAt(cells[i] as number) as Node, start + (cells[i] as number))
147
+ }
129
148
 
130
- forEachCell(f: (node: Node, index: number) => void) {
131
- const table = this.$anchorCell.node(-1),
132
- map = TableMap.get(table),
133
- start = this.$anchorCell.start(-1);
134
- const cells = map.cellsInRect(map.rectBetween(this.$anchorCell.pos - start, this.$headCell.pos - start));
135
- for (let i = 0; i < cells.length; i++)
136
- f(table.nodeAt(cells[i] as number) as Node, start + (cells[i] as number));
137
- }
149
+ // :: () bool
150
+ // True if this selection goes all the way from the top to the
151
+ // bottom of the table.
152
+ isColSelection() {
153
+ const anchorTop = this.$anchorCell.index(-1)
154
+ const headTop = this.$headCell.index(-1)
155
+ if (Math.min(anchorTop, headTop) > 0)
156
+ return false
157
+ const anchorBot = anchorTop + (this.$anchorCell.nodeAfter as Node).attrs.rowspan
158
+ const headBot = headTop + (this.$headCell.nodeAfter as Node).attrs.rowspan
159
+ return Math.max(anchorBot, headBot) == this.$headCell.node(-1).childCount
160
+ }
138
161
 
139
- // :: () → bool
140
- // True if this selection goes all the way from the top to the
141
- // bottom of the table.
142
- isColSelection() {
143
- const anchorTop = this.$anchorCell.index(-1),
144
- headTop = this.$headCell.index(-1);
145
- if (Math.min(anchorTop, headTop) > 0) return false;
146
- const anchorBot = anchorTop + (this.$anchorCell.nodeAfter as Node).attrs['rowspan'],
147
- headBot = headTop + (this.$headCell.nodeAfter as Node).attrs['rowspan'];
148
- return Math.max(anchorBot, headBot) == this.$headCell.node(-1).childCount;
162
+ // :: (ResolvedPos, ?ResolvedPos) → CellSelection
163
+ // Returns the smallest column selection that covers the given anchor
164
+ // and head cell.
165
+ static colSelection($anchorCell: ResolvedPos, $headCell = $anchorCell) {
166
+ const map = TableMap.get($anchorCell.node(-1))
167
+ const start = $anchorCell.start(-1)
168
+ const anchorRect = map.findCell($anchorCell.pos - start)
169
+ const headRect = map.findCell($headCell.pos - start)
170
+ const doc = $anchorCell.node(0)
171
+ if (anchorRect.top <= headRect.top) {
172
+ if (anchorRect.top > 0) {
173
+ const left = map.map[anchorRect.left] as number
174
+ $anchorCell = doc.resolve(start + left)
175
+ }
176
+ if (headRect.bottom < map.height) {
177
+ const pos = map.map[map.width * (map.height - 1) + headRect.right - 1] as number
178
+ $headCell = doc.resolve(start + pos)
179
+ }
149
180
  }
150
-
151
- // :: (ResolvedPos, ?ResolvedPos) → CellSelection
152
- // Returns the smallest column selection that covers the given anchor
153
- // and head cell.
154
- static colSelection($anchorCell: ResolvedPos, $headCell = $anchorCell) {
155
- const map = TableMap.get($anchorCell.node(-1)),
156
- start = $anchorCell.start(-1);
157
- const anchorRect = map.findCell($anchorCell.pos - start),
158
- headRect = map.findCell($headCell.pos - start);
159
- const doc = $anchorCell.node(0);
160
- if (anchorRect.top <= headRect.top) {
161
- if (anchorRect.top > 0) {
162
- const left = map.map[anchorRect.left] as number;
163
- $anchorCell = doc.resolve(start + left);
164
- }
165
- if (headRect.bottom < map.height) {
166
- const pos = map.map[map.width * (map.height - 1) + headRect.right - 1] as number;
167
- $headCell = doc.resolve(start + pos);
168
- }
169
- } else {
170
- if (headRect.top > 0) {
171
- const left = map.map[anchorRect.left] as number;
172
- $headCell = doc.resolve(start + left);
173
- }
174
- if (anchorRect.bottom < map.height) {
175
- const pos = map.map[map.width * (map.height - 1) + anchorRect.right - 1] as number;
176
- $anchorCell = doc.resolve(start + pos);
177
- }
178
- }
179
- return new CellSelection($anchorCell, $headCell);
181
+ else {
182
+ if (headRect.top > 0) {
183
+ const left = map.map[anchorRect.left] as number
184
+ $headCell = doc.resolve(start + left)
185
+ }
186
+ if (anchorRect.bottom < map.height) {
187
+ const pos = map.map[map.width * (map.height - 1) + anchorRect.right - 1] as number
188
+ $anchorCell = doc.resolve(start + pos)
189
+ }
180
190
  }
191
+ return new CellSelection($anchorCell, $headCell)
192
+ }
181
193
 
182
- // :: () → bool
183
- // True if this selection goes all the way from the left to the
184
- // right of the table.
185
- isRowSelection() {
186
- const map = TableMap.get(this.$anchorCell.node(-1)),
187
- start = this.$anchorCell.start(-1);
188
- const anchorLeft = map.colCount(this.$anchorCell.pos - start),
189
- headLeft = map.colCount(this.$headCell.pos - start);
190
- if (Math.min(anchorLeft, headLeft) > 0) return false;
191
- const anchorRight = anchorLeft + (this.$anchorCell.nodeAfter as Node).attrs['colspan'],
192
- headRight = headLeft + (this.$headCell.nodeAfter as Node).attrs['colspan'];
193
- return Math.max(anchorRight, headRight) == map.width;
194
- }
194
+ // :: () → bool
195
+ // True if this selection goes all the way from the left to the
196
+ // right of the table.
197
+ isRowSelection() {
198
+ const map = TableMap.get(this.$anchorCell.node(-1))
199
+ const start = this.$anchorCell.start(-1)
200
+ const anchorLeft = map.colCount(this.$anchorCell.pos - start)
201
+ const headLeft = map.colCount(this.$headCell.pos - start)
202
+ if (Math.min(anchorLeft, headLeft) > 0)
203
+ return false
204
+ const anchorRight = anchorLeft + (this.$anchorCell.nodeAfter as Node).attrs.colspan
205
+ const headRight = headLeft + (this.$headCell.nodeAfter as Node).attrs.colspan
206
+ return Math.max(anchorRight, headRight) == map.width
207
+ }
195
208
 
196
- eq(other: Selection): boolean {
197
- return (
198
- other instanceof CellSelection &&
199
- other.$anchorCell.pos == this.$anchorCell.pos &&
200
- other.$headCell.pos == this.$headCell.pos
201
- );
202
- }
209
+ eq(other: Selection): boolean {
210
+ return (
211
+ other instanceof CellSelection
212
+ && other.$anchorCell.pos == this.$anchorCell.pos
213
+ && other.$headCell.pos == this.$headCell.pos
214
+ )
215
+ }
203
216
 
204
- // :: (ResolvedPos, ?ResolvedPos) → CellSelection
205
- // Returns the smallest row selection that covers the given anchor
206
- // and head cell.
207
- static rowSelection($anchorCell: ResolvedPos, $headCell = $anchorCell) {
208
- const map = TableMap.get($anchorCell.node(-1)),
209
- start = $anchorCell.start(-1);
210
- const anchorRect = map.findCell($anchorCell.pos - start),
211
- headRect = map.findCell($headCell.pos - start);
212
- const doc = $anchorCell.node(0);
213
- if (anchorRect.left <= headRect.left) {
214
- if (anchorRect.left > 0) {
215
- const pos = map.map[anchorRect.top * map.width] as number;
216
- $anchorCell = doc.resolve(start + pos);
217
- }
218
- if (headRect.right < map.width) {
219
- const pos = map.map[map.width * (headRect.top + 1) - 1] as number;
220
- $headCell = doc.resolve(start + pos);
221
- }
222
- } else {
223
- if (headRect.left > 0) {
224
- const pos = map.map[headRect.top * map.width] as number;
225
- $headCell = doc.resolve(start + pos);
226
- }
227
- if (anchorRect.right < map.width) {
228
- const pos = map.map[map.width * (anchorRect.top + 1) - 1] as number;
229
-
230
- $anchorCell = doc.resolve(start + pos);
231
- }
232
- }
233
- return new CellSelection($anchorCell, $headCell);
217
+ // :: (ResolvedPos, ?ResolvedPos) → CellSelection
218
+ // Returns the smallest row selection that covers the given anchor
219
+ // and head cell.
220
+ static rowSelection($anchorCell: ResolvedPos, $headCell = $anchorCell) {
221
+ const map = TableMap.get($anchorCell.node(-1))
222
+ const start = $anchorCell.start(-1)
223
+ const anchorRect = map.findCell($anchorCell.pos - start)
224
+ const headRect = map.findCell($headCell.pos - start)
225
+ const doc = $anchorCell.node(0)
226
+ if (anchorRect.left <= headRect.left) {
227
+ if (anchorRect.left > 0) {
228
+ const pos = map.map[anchorRect.top * map.width] as number
229
+ $anchorCell = doc.resolve(start + pos)
230
+ }
231
+ if (headRect.right < map.width) {
232
+ const pos = map.map[map.width * (headRect.top + 1) - 1] as number
233
+ $headCell = doc.resolve(start + pos)
234
+ }
234
235
  }
236
+ else {
237
+ if (headRect.left > 0) {
238
+ const pos = map.map[headRect.top * map.width] as number
239
+ $headCell = doc.resolve(start + pos)
240
+ }
241
+ if (anchorRect.right < map.width) {
242
+ const pos = map.map[map.width * (anchorRect.top + 1) - 1] as number
235
243
 
236
- toJSON() {
237
- return {
238
- type: 'cell',
239
- anchor: this.$anchorCell.pos,
240
- head: this.$headCell.pos,
241
- };
244
+ $anchorCell = doc.resolve(start + pos)
245
+ }
242
246
  }
247
+ return new CellSelection($anchorCell, $headCell)
248
+ }
243
249
 
244
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
245
- static override fromJSON(doc: Node, json: any) {
246
- return new CellSelection(doc.resolve(json.anchor), doc.resolve(json.head));
250
+ toJSON() {
251
+ return {
252
+ type: 'cell',
253
+ anchor: this.$anchorCell.pos,
254
+ head: this.$headCell.pos,
247
255
  }
256
+ }
248
257
 
249
- // :: (Node, number, ?number) → CellSelection
250
- static create(doc: Node, anchorCell: number, headCell = anchorCell) {
251
- return new CellSelection(doc.resolve(anchorCell), doc.resolve(headCell));
252
- }
258
+ static override fromJSON(doc: Node, json: any) {
259
+ return new CellSelection(doc.resolve(json.anchor), doc.resolve(json.head))
260
+ }
253
261
 
254
- override getBookmark() {
255
- return new CellBookmark(this.$anchorCell.pos, this.$headCell.pos);
256
- }
262
+ // :: (Node, number, ?number) → CellSelection
263
+ static create(doc: Node, anchorCell: number, headCell = anchorCell) {
264
+ return new CellSelection(doc.resolve(anchorCell), doc.resolve(headCell))
265
+ }
266
+
267
+ override getBookmark() {
268
+ return new CellBookmark(this.$anchorCell.pos, this.$headCell.pos)
269
+ }
257
270
  }
258
271
 
259
- CellSelection.prototype.visible = false;
272
+ CellSelection.prototype.visible = false
260
273
 
261
- Selection.jsonID('cell', CellSelection);
274
+ Selection.jsonID('cell', CellSelection)
262
275
 
263
276
  class CellBookmark {
264
- constructor(public anchor: number, public head: number) {
265
- this.anchor = anchor;
266
- this.head = head;
267
- }
268
- map(mapping: Mappable) {
269
- return new CellBookmark(mapping.map(this.anchor), mapping.map(this.head));
270
- }
271
- resolve(doc: Node): Selection {
272
- const $anchorCell = doc.resolve(this.anchor),
273
- $headCell = doc.resolve(this.head);
274
- if (
275
- $anchorCell.parent.type.spec['tableRole'] == 'row' &&
276
- $headCell.parent.type.spec['tableRole'] == 'row' &&
277
- $anchorCell.index() < $anchorCell.parent.childCount &&
278
- $headCell.index() < $headCell.parent.childCount &&
279
- inSameTable($anchorCell, $headCell)
280
- )
281
- return new CellSelection($anchorCell, $headCell);
282
- else return Selection.near($headCell, 1);
283
- }
277
+ constructor(public anchor: number, public head: number) {
278
+ this.anchor = anchor
279
+ this.head = head
280
+ }
281
+
282
+ map(mapping: Mappable) {
283
+ return new CellBookmark(mapping.map(this.anchor), mapping.map(this.head))
284
+ }
285
+
286
+ resolve(doc: Node): Selection {
287
+ const $anchorCell = doc.resolve(this.anchor)
288
+ const $headCell = doc.resolve(this.head)
289
+ if (
290
+ $anchorCell.parent.type.spec.tableRole == 'row'
291
+ && $headCell.parent.type.spec.tableRole == 'row'
292
+ && $anchorCell.index() < $anchorCell.parent.childCount
293
+ && $headCell.index() < $headCell.parent.childCount
294
+ && inSameTable($anchorCell, $headCell)
295
+ )
296
+ return new CellSelection($anchorCell, $headCell)
297
+ else return Selection.near($headCell, 1)
298
+ }
284
299
  }
285
300
 
286
301
  export function drawCellSelection(state: EditorState) {
287
- if (!(state.selection instanceof CellSelection)) return null;
288
- const cells: Decoration[] = [];
289
- state.selection.forEachCell((node, pos) => {
290
- cells.push(Decoration.node(pos, pos + node.nodeSize, { class: 'selectedCell' }));
291
- });
292
- return DecorationSet.create(state.doc, cells);
302
+ if (!(state.selection instanceof CellSelection))
303
+ return null
304
+ const cells: Decoration[] = []
305
+ state.selection.forEachCell((node, pos) => {
306
+ cells.push(Decoration.node(pos, pos + node.nodeSize, { class: 'selectedCell' }))
307
+ })
308
+ return DecorationSet.create(state.doc, cells)
293
309
  }
294
310
 
295
311
  function isCellBoundarySelection({ $from, $to }: Selection) {
296
- if ($from.pos == $to.pos || $from.pos < $from.pos - 6) return false; // Cheap elimination
297
- let afterFrom = $from.pos,
298
- beforeTo = $to.pos,
299
- depth = $from.depth;
300
- for (; depth >= 0; depth--, afterFrom++) if ($from.after(depth + 1) < $from.end(depth)) break;
301
- for (let d = $to.depth; d >= 0; d--, beforeTo--) if ($to.before(d + 1) > $to.start(d)) break;
302
- return afterFrom == beforeTo && /row|table/.test($from.node(depth).type.spec['tableRole']);
312
+ if ($from.pos == $to.pos || $from.pos < $from.pos - 6)
313
+ return false // Cheap elimination
314
+ let afterFrom = $from.pos
315
+ let beforeTo = $to.pos
316
+ let depth = $from.depth
317
+ for (; depth >= 0; depth--, afterFrom++) {
318
+ if ($from.after(depth + 1) < $from.end(depth))
319
+ break
320
+ }
321
+ for (let d = $to.depth; d >= 0; d--, beforeTo--) {
322
+ if ($to.before(d + 1) > $to.start(d))
323
+ break
324
+ }
325
+ return afterFrom == beforeTo && /row|table/.test($from.node(depth).type.spec.tableRole)
303
326
  }
304
327
 
305
328
  function isTextSelectionAcrossCells({ $from, $to }: Selection) {
306
- let fromCellBoundaryNode;
307
- let toCellBoundaryNode;
308
-
309
- for (let i = $from.depth; i > 0; i--) {
310
- const node = $from.node(i);
311
- if (node.type.spec['tableRole'] === 'cell' || node.type.spec['tableRole'] === 'header_cell') {
312
- fromCellBoundaryNode = node;
313
- break;
314
- }
329
+ let fromCellBoundaryNode
330
+ let toCellBoundaryNode
331
+
332
+ for (let i = $from.depth; i > 0; i--) {
333
+ const node = $from.node(i)
334
+ if (node.type.spec.tableRole === 'cell' || node.type.spec.tableRole === 'header_cell') {
335
+ fromCellBoundaryNode = node
336
+ break
315
337
  }
338
+ }
316
339
 
317
- for (let i = $to.depth; i > 0; i--) {
318
- const node = $to.node(i);
319
- if (node.type.spec['tableRole'] === 'cell' || node.type.spec['tableRole'] === 'header_cell') {
320
- toCellBoundaryNode = node;
321
- break;
322
- }
340
+ for (let i = $to.depth; i > 0; i--) {
341
+ const node = $to.node(i)
342
+ if (node.type.spec.tableRole === 'cell' || node.type.spec.tableRole === 'header_cell') {
343
+ toCellBoundaryNode = node
344
+ break
323
345
  }
346
+ }
324
347
 
325
- return fromCellBoundaryNode !== toCellBoundaryNode && $to.parentOffset === 0;
348
+ return fromCellBoundaryNode !== toCellBoundaryNode && $to.parentOffset === 0
326
349
  }
327
350
 
328
351
  export function normalizeSelection(state: EditorState, tr: Transaction | undefined, allowTableNodeSelection: boolean) {
329
- const sel = (tr || state).selection,
330
- doc = (tr || state).doc;
331
- let normalize, role;
332
- if (sel instanceof NodeSelection && (role = sel.node.type.spec['tableRole'])) {
333
- if (role == 'cell' || role == 'header_cell') {
334
- normalize = CellSelection.create(doc, sel.from);
335
- } else if (role == 'row') {
336
- const $cell = doc.resolve(sel.from + 1);
337
- normalize = CellSelection.rowSelection($cell, $cell);
338
- } else if (!allowTableNodeSelection) {
339
- const map = TableMap.get(sel.node),
340
- start = sel.from + 1;
341
- const pos = map.map[map.width * map.height - 1] as number;
342
- const lastCell = start + pos;
343
- normalize = CellSelection.create(doc, start + 1, lastCell);
344
- }
345
- } else if (sel instanceof TextSelection && isCellBoundarySelection(sel)) {
346
- normalize = TextSelection.create(doc, sel.from);
347
- } else if (sel instanceof TextSelection && isTextSelectionAcrossCells(sel)) {
348
- normalize = TextSelection.create(doc, sel.$from.start(), sel.$from.end());
352
+ const sel = (tr || state).selection
353
+ const doc = (tr || state).doc
354
+ let normalize, role
355
+ // eslint-disable-next-line no-cond-assign
356
+ if (sel instanceof NodeSelection && (role = sel.node.type.spec.tableRole)) {
357
+ if (role == 'cell' || role == 'header_cell') {
358
+ normalize = CellSelection.create(doc, sel.from)
359
+ }
360
+ else if (role == 'row') {
361
+ const $cell = doc.resolve(sel.from + 1)
362
+ normalize = CellSelection.rowSelection($cell, $cell)
363
+ }
364
+ else if (!allowTableNodeSelection) {
365
+ const map = TableMap.get(sel.node)
366
+ const start = sel.from + 1
367
+ const pos = map.map[map.width * map.height - 1] as number
368
+ const lastCell = start + pos
369
+ normalize = CellSelection.create(doc, start + 1, lastCell)
349
370
  }
350
- if (normalize) (tr || (tr = state.tr)).setSelection(normalize);
351
- return tr;
371
+ }
372
+ else if (sel instanceof TextSelection && isCellBoundarySelection(sel)) {
373
+ normalize = TextSelection.create(doc, sel.from)
374
+ }
375
+ else if (sel instanceof TextSelection && isTextSelectionAcrossCells(sel)) {
376
+ normalize = TextSelection.create(doc, sel.$from.start(), sel.$from.end())
377
+ }
378
+ if (normalize)
379
+ (tr || (tr = state.tr)).setSelection(normalize)
380
+ return tr
352
381
  }