@milkdown/preset-gfm 6.5.4 → 7.0.0-next.1
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/lib/composed/commands.d.ts +8 -0
- package/lib/composed/commands.d.ts.map +1 -0
- package/lib/composed/index.d.ts +6 -0
- package/lib/composed/index.d.ts.map +1 -0
- package/lib/composed/inputrules.d.ts +3 -0
- package/lib/composed/inputrules.d.ts.map +1 -0
- package/lib/composed/keymap.d.ts +3 -0
- package/lib/composed/keymap.d.ts.map +1 -0
- package/lib/composed/plugins.d.ts +3 -0
- package/lib/composed/plugins.d.ts.map +1 -0
- package/lib/composed/schema.d.ts +3 -0
- package/lib/composed/schema.d.ts.map +1 -0
- package/lib/index.d.ts +4 -34
- package/lib/index.d.ts.map +1 -1
- package/lib/index.es.js +634 -2328
- package/lib/index.es.js.map +1 -1
- package/lib/mark/index.d.ts +2 -0
- package/lib/mark/index.d.ts.map +1 -0
- package/lib/mark/strike-through.d.ts +5 -0
- package/lib/mark/strike-through.d.ts.map +1 -0
- package/lib/node/footnote/definition.d.ts +2 -0
- package/lib/node/footnote/definition.d.ts.map +1 -0
- package/lib/{footnote → node/footnote}/index.d.ts +0 -0
- package/lib/node/footnote/index.d.ts.map +1 -0
- package/lib/node/footnote/reference.d.ts +2 -0
- package/lib/node/footnote/reference.d.ts.map +1 -0
- package/lib/node/index.d.ts +4 -0
- package/lib/node/index.d.ts.map +1 -0
- package/lib/node/table/index.d.ts +32 -0
- package/lib/node/table/index.d.ts.map +1 -0
- package/lib/node/table/utils.d.ts +26 -0
- package/lib/node/table/utils.d.ts.map +1 -0
- package/lib/node/task-list-item.d.ts +2 -0
- package/lib/node/task-list-item.d.ts.map +1 -0
- package/lib/plugin/auto-insert-zero-space-plugin.d.ts +2 -0
- package/lib/plugin/auto-insert-zero-space-plugin.d.ts.map +1 -0
- package/lib/plugin/column-resizing-plugin.d.ts +2 -0
- package/lib/plugin/column-resizing-plugin.d.ts.map +1 -0
- package/lib/plugin/index.d.ts +5 -0
- package/lib/plugin/index.d.ts.map +1 -0
- package/lib/plugin/remark-gfm-plugin.d.ts +2 -0
- package/lib/plugin/remark-gfm-plugin.d.ts.map +1 -0
- package/lib/plugin/table-editing-plugin.d.ts +2 -0
- package/lib/plugin/table-editing-plugin.d.ts.map +1 -0
- package/package.json +13 -10
- package/src/composed/commands.ts +24 -0
- package/src/composed/index.ts +6 -0
- package/src/composed/inputrules.ts +8 -0
- package/src/composed/keymap.ts +10 -0
- package/src/composed/plugins.ts +11 -0
- package/src/composed/schema.ts +20 -0
- package/src/index.ts +6 -89
- package/src/mark/index.ts +2 -0
- package/src/mark/strike-through.ts +46 -0
- package/src/node/footnote/definition.ts +70 -0
- package/src/{footnote → node/footnote}/index.ts +0 -0
- package/src/node/footnote/reference.ts +60 -0
- package/src/node/index.ts +4 -0
- package/src/node/table/index.ts +318 -0
- package/src/node/table/utils.ts +509 -0
- package/src/node/task-list-item.ts +88 -0
- package/src/{table/plugin/auto-insert-zero-space.ts → plugin/auto-insert-zero-space-plugin.ts} +14 -15
- package/src/plugin/column-resizing-plugin.ts +6 -0
- package/src/plugin/index.ts +5 -0
- package/src/plugin/remark-gfm-plugin.ts +6 -0
- package/src/plugin/table-editing-plugin.ts +6 -0
- package/lib/footnote/definition.d.ts +0 -3
- package/lib/footnote/definition.d.ts.map +0 -1
- package/lib/footnote/index.d.ts.map +0 -1
- package/lib/footnote/reference.d.ts +0 -3
- package/lib/footnote/reference.d.ts.map +0 -1
- package/lib/footnote/utils.d.ts +0 -3
- package/lib/footnote/utils.d.ts.map +0 -1
- package/lib/strike-through.d.ts +0 -3
- package/lib/strike-through.d.ts.map +0 -1
- package/lib/supported-keys.d.ts +0 -28
- package/lib/supported-keys.d.ts.map +0 -1
- package/lib/table/command.d.ts +0 -4
- package/lib/table/command.d.ts.map +0 -1
- package/lib/table/index.d.ts +0 -10
- package/lib/table/index.d.ts.map +0 -1
- package/lib/table/nodes/index.d.ts +0 -12
- package/lib/table/nodes/index.d.ts.map +0 -1
- package/lib/table/operator-plugin/actions.d.ts +0 -20
- package/lib/table/operator-plugin/actions.d.ts.map +0 -1
- package/lib/table/operator-plugin/calc-pos.d.ts +0 -3
- package/lib/table/operator-plugin/calc-pos.d.ts.map +0 -1
- package/lib/table/operator-plugin/constant.d.ts +0 -6
- package/lib/table/operator-plugin/constant.d.ts.map +0 -1
- package/lib/table/operator-plugin/helper.d.ts +0 -7
- package/lib/table/operator-plugin/helper.d.ts.map +0 -1
- package/lib/table/operator-plugin/index.d.ts +0 -6
- package/lib/table/operator-plugin/index.d.ts.map +0 -1
- package/lib/table/operator-plugin/style.d.ts +0 -3
- package/lib/table/operator-plugin/style.d.ts.map +0 -1
- package/lib/table/operator-plugin/widget.d.ts +0 -8
- package/lib/table/operator-plugin/widget.d.ts.map +0 -1
- package/lib/table/plugin/auto-insert-zero-space.d.ts +0 -3
- package/lib/table/plugin/auto-insert-zero-space.d.ts.map +0 -1
- package/lib/table/plugin/cell-selection.d.ts +0 -40
- package/lib/table/plugin/cell-selection.d.ts.map +0 -1
- package/lib/table/plugin/column-resizing.d.ts +0 -18
- package/lib/table/plugin/column-resizing.d.ts.map +0 -1
- package/lib/table/plugin/commands.d.ts +0 -30
- package/lib/table/plugin/commands.d.ts.map +0 -1
- package/lib/table/plugin/copy-paste.d.ts +0 -14
- package/lib/table/plugin/copy-paste.d.ts.map +0 -1
- package/lib/table/plugin/fix-tables.d.ts +0 -7
- package/lib/table/plugin/fix-tables.d.ts.map +0 -1
- package/lib/table/plugin/index.d.ts +0 -4
- package/lib/table/plugin/index.d.ts.map +0 -1
- package/lib/table/plugin/schema.d.ts +0 -4
- package/lib/table/plugin/schema.d.ts.map +0 -1
- package/lib/table/plugin/table-editing.d.ts +0 -9
- package/lib/table/plugin/table-editing.d.ts.map +0 -1
- package/lib/table/plugin/table-map.d.ts +0 -44
- package/lib/table/plugin/table-map.d.ts.map +0 -1
- package/lib/table/plugin/table-view.d.ts +0 -15
- package/lib/table/plugin/table-view.d.ts.map +0 -1
- package/lib/table/plugin/types.d.ts +0 -15
- package/lib/table/plugin/types.d.ts.map +0 -1
- package/lib/table/plugin/util.d.ts +0 -16
- package/lib/table/plugin/util.d.ts.map +0 -1
- package/lib/table/utils.d.ts +0 -21
- package/lib/table/utils.d.ts.map +0 -1
- package/lib/task-list-item.d.ts +0 -9
- package/lib/task-list-item.d.ts.map +0 -1
- package/src/footnote/definition.ts +0 -187
- package/src/footnote/reference.ts +0 -178
- package/src/footnote/utils.ts +0 -4
- package/src/strike-through.ts +0 -43
- package/src/supported-keys.ts +0 -13
- package/src/table/command.ts +0 -20
- package/src/table/index.ts +0 -13
- package/src/table/nodes/index.ts +0 -189
- package/src/table/operator-plugin/actions.ts +0 -116
- package/src/table/operator-plugin/calc-pos.ts +0 -36
- package/src/table/operator-plugin/constant.ts +0 -7
- package/src/table/operator-plugin/helper.ts +0 -39
- package/src/table/operator-plugin/index.ts +0 -110
- package/src/table/operator-plugin/style.ts +0 -123
- package/src/table/operator-plugin/widget.ts +0 -57
- package/src/table/plugin/cell-selection.ts +0 -381
- package/src/table/plugin/column-resizing.ts +0 -288
- package/src/table/plugin/commands.ts +0 -594
- package/src/table/plugin/copy-paste.ts +0 -322
- package/src/table/plugin/fix-tables.ts +0 -132
- package/src/table/plugin/index.ts +0 -4
- package/src/table/plugin/schema.ts +0 -120
- package/src/table/plugin/table-editing.ts +0 -369
- package/src/table/plugin/table-map.ts +0 -345
- package/src/table/plugin/table-view.ts +0 -80
- package/src/table/plugin/types.ts +0 -16
- package/src/table/plugin/util.ts +0 -119
- package/src/table/utils.ts +0 -165
- package/src/task-list-item.ts +0 -159
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
|
|
3
|
+
import type { ContentNodeWithPos } from '@milkdown/prose'
|
|
4
|
+
import { cloneTr, findParentNode } from '@milkdown/prose'
|
|
5
|
+
import type { Node } from '@milkdown/prose/model'
|
|
6
|
+
import type { Selection, Transaction } from '@milkdown/prose/state'
|
|
7
|
+
import type { TableRect } from '@milkdown/prose/tables'
|
|
8
|
+
import { CellSelection, TableMap } from '@milkdown/prose/tables'
|
|
9
|
+
|
|
10
|
+
import { tableCellSchema, tableHeaderSchema, tableRowSchema, tableSchema } from '.'
|
|
11
|
+
|
|
12
|
+
/// @internal
|
|
13
|
+
export interface CellPos {
|
|
14
|
+
pos: number
|
|
15
|
+
start: number
|
|
16
|
+
node: Node
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/// @internal
|
|
20
|
+
export const createTable = (rowsCount = 3, colsCount = 3): Node => {
|
|
21
|
+
const cells = Array(colsCount)
|
|
22
|
+
.fill(0)
|
|
23
|
+
.map(() => tableCellSchema.type().createAndFill()!)
|
|
24
|
+
|
|
25
|
+
const headerCells = Array(colsCount)
|
|
26
|
+
.fill(0)
|
|
27
|
+
.map(() => tableHeaderSchema.type().createAndFill()!)
|
|
28
|
+
|
|
29
|
+
const rows = Array(rowsCount)
|
|
30
|
+
.fill(0)
|
|
31
|
+
.map((_, i) => tableRowSchema.type().create(null, i === 0 ? headerCells : cells))
|
|
32
|
+
|
|
33
|
+
return tableSchema.type().create(null, rows)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// Find the table node with position information for current selection.
|
|
37
|
+
export const findTable = (selection: Selection) =>
|
|
38
|
+
findParentNode(node => node.type.spec.tableRole === 'table')(selection)
|
|
39
|
+
|
|
40
|
+
/// Get cells in a column of a table.
|
|
41
|
+
export const getCellsInCol = (columnIndex: number, selection: Selection): CellPos[] | undefined => {
|
|
42
|
+
const table = findTable(selection)
|
|
43
|
+
if (!table)
|
|
44
|
+
return undefined
|
|
45
|
+
const map = TableMap.get(table.node)
|
|
46
|
+
if (columnIndex < 0 || columnIndex >= map.width)
|
|
47
|
+
return undefined
|
|
48
|
+
|
|
49
|
+
return map
|
|
50
|
+
.cellsInRect({ left: columnIndex, right: columnIndex + 1, top: 0, bottom: map.height })
|
|
51
|
+
.map((pos) => {
|
|
52
|
+
const node = table.node.nodeAt(pos)
|
|
53
|
+
if (!node)
|
|
54
|
+
return undefined
|
|
55
|
+
const start = pos + table.start
|
|
56
|
+
return {
|
|
57
|
+
pos: start,
|
|
58
|
+
start: start + 1,
|
|
59
|
+
node,
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
.filter((x): x is CellPos => x != null)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// Get cells in a row of a table.
|
|
66
|
+
export const getCellsInRow = (rowIndex: number, selection: Selection): CellPos[] | undefined => {
|
|
67
|
+
const table = findTable(selection)
|
|
68
|
+
if (!table)
|
|
69
|
+
return undefined
|
|
70
|
+
const map = TableMap.get(table.node)
|
|
71
|
+
if (rowIndex < 0 || rowIndex >= map.height)
|
|
72
|
+
return undefined
|
|
73
|
+
|
|
74
|
+
return map
|
|
75
|
+
.cellsInRect({ left: 0, right: map.width, top: rowIndex, bottom: rowIndex + 1 })
|
|
76
|
+
.map((pos) => {
|
|
77
|
+
const node = table.node.nodeAt(pos)
|
|
78
|
+
if (!node)
|
|
79
|
+
return undefined
|
|
80
|
+
const start = pos + table.start
|
|
81
|
+
return {
|
|
82
|
+
pos: start,
|
|
83
|
+
start: start + 1,
|
|
84
|
+
node,
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
.filter((x): x is CellPos => x != null)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// Get all cells in a table.
|
|
91
|
+
export const getAllCellsInTable = (selection: Selection) => {
|
|
92
|
+
const table = findTable(selection)
|
|
93
|
+
if (!table)
|
|
94
|
+
return
|
|
95
|
+
|
|
96
|
+
const map = TableMap.get(table.node)
|
|
97
|
+
const cells = map.cellsInRect({
|
|
98
|
+
left: 0,
|
|
99
|
+
right: map.width,
|
|
100
|
+
top: 0,
|
|
101
|
+
bottom: map.height,
|
|
102
|
+
})
|
|
103
|
+
return cells.map((nodePos) => {
|
|
104
|
+
const node = table.node.nodeAt(nodePos)
|
|
105
|
+
const pos = nodePos + table.start
|
|
106
|
+
return { pos, start: pos + 1, node }
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/// Select a possible table in current selection.
|
|
111
|
+
export const selectTable = (tr: Transaction) => {
|
|
112
|
+
const cells = getAllCellsInTable(tr.selection)
|
|
113
|
+
if (cells && cells[0]) {
|
|
114
|
+
const $firstCell = tr.doc.resolve(cells[0].pos)
|
|
115
|
+
const last = cells[cells.length - 1]
|
|
116
|
+
if (last) {
|
|
117
|
+
const $lastCell = tr.doc.resolve(last.pos)
|
|
118
|
+
return cloneTr(tr.setSelection(new CellSelection($lastCell, $firstCell)))
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return tr
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/// @internal
|
|
125
|
+
export function addRowWithAlignment(tr: Transaction, { map, tableStart, table }: TableRect, row: number) {
|
|
126
|
+
const rowPos = Array(row)
|
|
127
|
+
.fill(0)
|
|
128
|
+
.reduce((acc, _, i) => {
|
|
129
|
+
return acc + table.child(i).nodeSize
|
|
130
|
+
}, tableStart)
|
|
131
|
+
|
|
132
|
+
const cells = Array(map.width)
|
|
133
|
+
.fill(0)
|
|
134
|
+
.map((_, col) => {
|
|
135
|
+
const headerCol = table.nodeAt(map.map[col] as number)
|
|
136
|
+
return tableCellSchema.type().createAndFill({ alignment: headerCol?.attrs.alignment }) as Node
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
tr.insert(rowPos, tableRowSchema.type().create(null, cells))
|
|
140
|
+
return tr
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/// @internal
|
|
144
|
+
export const selectLine = (type: 'row' | 'col') => (index: number) => (tr: Transaction) => {
|
|
145
|
+
const table = findTable(tr.selection)
|
|
146
|
+
const isRowSelection = type === 'row'
|
|
147
|
+
if (table) {
|
|
148
|
+
const map = TableMap.get(table.node)
|
|
149
|
+
|
|
150
|
+
// Check if the index is valid
|
|
151
|
+
if (index >= 0 && index < (isRowSelection ? map.height : map.width)) {
|
|
152
|
+
const lastCell = map.positionAt(
|
|
153
|
+
isRowSelection ? index : map.height - 1,
|
|
154
|
+
isRowSelection ? map.width - 1 : index,
|
|
155
|
+
table.node,
|
|
156
|
+
)
|
|
157
|
+
const $lastCell = tr.doc.resolve(table.start + lastCell)
|
|
158
|
+
|
|
159
|
+
const createCellSelection = isRowSelection ? CellSelection.rowSelection : CellSelection.colSelection
|
|
160
|
+
|
|
161
|
+
const firstCell = map.positionAt(isRowSelection ? index : 0, isRowSelection ? 0 : index, table.node)
|
|
162
|
+
const $firstCell = tr.doc.resolve(table.start + firstCell)
|
|
163
|
+
return cloneTr(tr.setSelection(createCellSelection($lastCell, $firstCell) as unknown as Selection))
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return tr
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/// If the selection is in a table,
|
|
170
|
+
/// select the {index} row.
|
|
171
|
+
export const selectRow = selectLine('row')
|
|
172
|
+
|
|
173
|
+
/// If the selection is in a table,
|
|
174
|
+
/// select the {index} column.
|
|
175
|
+
export const selectCol = selectLine('col')
|
|
176
|
+
|
|
177
|
+
const transpose = <T>(array: T[][]) => {
|
|
178
|
+
return array[0]!.map((_, i) => {
|
|
179
|
+
return array.map(column => column[i])
|
|
180
|
+
}) as T[][]
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const convertArrayOfRowsToTableNode = (tableNode: Node, arrayOfNodes: (Node | null)[][]) => {
|
|
184
|
+
const rowsPM = []
|
|
185
|
+
const map = TableMap.get(tableNode)
|
|
186
|
+
for (let rowIndex = 0; rowIndex < map.height; rowIndex++) {
|
|
187
|
+
const row = tableNode.child(rowIndex)
|
|
188
|
+
const rowCells = []
|
|
189
|
+
|
|
190
|
+
for (let colIndex = 0; colIndex < map.width; colIndex++) {
|
|
191
|
+
if (!arrayOfNodes[rowIndex]![colIndex])
|
|
192
|
+
continue
|
|
193
|
+
|
|
194
|
+
const cellPos = map.map[rowIndex * map.width + colIndex]!
|
|
195
|
+
|
|
196
|
+
const cell = arrayOfNodes[rowIndex]![colIndex]!
|
|
197
|
+
const oldCell = tableNode.nodeAt(cellPos)!
|
|
198
|
+
const newCell = oldCell.type.createChecked(
|
|
199
|
+
Object.assign({}, cell.attrs),
|
|
200
|
+
cell.content,
|
|
201
|
+
cell.marks,
|
|
202
|
+
)
|
|
203
|
+
rowCells.push(newCell)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
rowsPM.push(row.type.createChecked(row.attrs, rowCells, row.marks))
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const newTable = tableNode.type.createChecked(
|
|
210
|
+
tableNode.attrs,
|
|
211
|
+
rowsPM,
|
|
212
|
+
tableNode.marks,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
return newTable
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const convertTableNodeToArrayOfRows = (tableNode: Node) => {
|
|
219
|
+
const map = TableMap.get(tableNode)
|
|
220
|
+
const rows: (Node | null)[][] = []
|
|
221
|
+
for (let rowIndex = 0; rowIndex < map.height; rowIndex++) {
|
|
222
|
+
const rowCells: (Node | null)[] = []
|
|
223
|
+
const seen: Record<number, boolean> = {}
|
|
224
|
+
|
|
225
|
+
for (let colIndex = 0; colIndex < map.width; colIndex++) {
|
|
226
|
+
const cellPos = map.map[rowIndex * map.width + colIndex]!
|
|
227
|
+
const cell = tableNode.nodeAt(cellPos)
|
|
228
|
+
const rect = map.findCell(cellPos)
|
|
229
|
+
if (seen[cellPos] || rect.top !== rowIndex) {
|
|
230
|
+
rowCells.push(null)
|
|
231
|
+
continue
|
|
232
|
+
}
|
|
233
|
+
seen[cellPos] = true
|
|
234
|
+
|
|
235
|
+
rowCells.push(cell)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
rows.push(rowCells)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return rows
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const moveRowInArrayOfRows = (
|
|
245
|
+
rows: (Node | null)[][],
|
|
246
|
+
indexesOrigin: number[],
|
|
247
|
+
indexesTarget: number[],
|
|
248
|
+
directionOverride: -1 | 1 | 0,
|
|
249
|
+
) => {
|
|
250
|
+
const direction = indexesOrigin[0]! > indexesTarget[0]! ? -1 : 1
|
|
251
|
+
|
|
252
|
+
const rowsExtracted = rows.splice(indexesOrigin[0]!, indexesOrigin.length)
|
|
253
|
+
const positionOffset = rowsExtracted.length % 2 === 0 ? 1 : 0
|
|
254
|
+
let target: number
|
|
255
|
+
|
|
256
|
+
if (directionOverride === -1 && direction === 1) {
|
|
257
|
+
target = indexesTarget[0]! - 1
|
|
258
|
+
}
|
|
259
|
+
else if (directionOverride === 1 && direction === -1) {
|
|
260
|
+
target = indexesTarget[indexesTarget.length - 1]! - positionOffset + 1
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
target
|
|
264
|
+
= direction === -1
|
|
265
|
+
? indexesTarget[0]!
|
|
266
|
+
: indexesTarget[indexesTarget.length - 1]! - positionOffset
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
rows.splice(target, 0, ...rowsExtracted)
|
|
270
|
+
return rows
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const moveTableColumn = (
|
|
274
|
+
table: ContentNodeWithPos,
|
|
275
|
+
indexesOrigin: number[],
|
|
276
|
+
indexesTarget: number[],
|
|
277
|
+
direction: -1 | 1 | 0,
|
|
278
|
+
) => {
|
|
279
|
+
let rows = transpose(convertTableNodeToArrayOfRows(table.node))
|
|
280
|
+
|
|
281
|
+
rows = moveRowInArrayOfRows(rows, indexesOrigin, indexesTarget, direction)
|
|
282
|
+
rows = transpose(rows)
|
|
283
|
+
|
|
284
|
+
return convertArrayOfRowsToTableNode(table.node, rows)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const moveTableRow = (
|
|
288
|
+
table: ContentNodeWithPos,
|
|
289
|
+
indexesOrigin: number[],
|
|
290
|
+
indexesTarget: number[],
|
|
291
|
+
direction: -1 | 1 | 0,
|
|
292
|
+
) => {
|
|
293
|
+
let rows = convertTableNodeToArrayOfRows(table.node)
|
|
294
|
+
|
|
295
|
+
rows = moveRowInArrayOfRows(rows, indexesOrigin, indexesTarget, direction)
|
|
296
|
+
|
|
297
|
+
return convertArrayOfRowsToTableNode(table.node, rows)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const getSelectionRangeInColumn = (columnIndex: number, tr: Transaction) => {
|
|
301
|
+
let startIndex = columnIndex
|
|
302
|
+
let endIndex = columnIndex
|
|
303
|
+
|
|
304
|
+
// looking for selection start column (startIndex)
|
|
305
|
+
for (let i = columnIndex; i >= 0; i--) {
|
|
306
|
+
const cells = getCellsInCol(i, tr.selection)
|
|
307
|
+
if (cells) {
|
|
308
|
+
cells.forEach((cell) => {
|
|
309
|
+
const maybeEndIndex = cell.node.attrs.colspan + i - 1
|
|
310
|
+
if (maybeEndIndex >= startIndex)
|
|
311
|
+
startIndex = i
|
|
312
|
+
|
|
313
|
+
if (maybeEndIndex > endIndex)
|
|
314
|
+
endIndex = maybeEndIndex
|
|
315
|
+
})
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// looking for selection end column (endIndex)
|
|
319
|
+
for (let i = columnIndex; i <= endIndex; i++) {
|
|
320
|
+
const cells = getCellsInCol(i, tr.selection)
|
|
321
|
+
if (cells) {
|
|
322
|
+
cells.forEach((cell) => {
|
|
323
|
+
const maybeEndIndex = cell.node.attrs.colspan + i - 1
|
|
324
|
+
if (cell.node.attrs.colspan > 1 && maybeEndIndex > endIndex)
|
|
325
|
+
endIndex = maybeEndIndex
|
|
326
|
+
})
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// filter out columns without cells (where all rows have colspan > 1 in the same column)
|
|
331
|
+
const indexes = []
|
|
332
|
+
for (let i = startIndex; i <= endIndex; i++) {
|
|
333
|
+
const maybeCells = getCellsInCol(i, tr.selection)
|
|
334
|
+
if (maybeCells && maybeCells.length)
|
|
335
|
+
indexes.push(i)
|
|
336
|
+
}
|
|
337
|
+
startIndex = indexes[0]!
|
|
338
|
+
endIndex = indexes[indexes.length - 1]!
|
|
339
|
+
|
|
340
|
+
const firstSelectedColumnCells = getCellsInCol(startIndex, tr.selection)!
|
|
341
|
+
const firstRowCells = getCellsInRow(0, tr.selection)!
|
|
342
|
+
const $anchor = tr.doc.resolve(
|
|
343
|
+
firstSelectedColumnCells[firstSelectedColumnCells.length - 1]!.pos,
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
let headCell: CellPos | undefined
|
|
347
|
+
for (let i = endIndex; i >= startIndex; i--) {
|
|
348
|
+
const columnCells = getCellsInCol(i, tr.selection)
|
|
349
|
+
if (columnCells && columnCells.length) {
|
|
350
|
+
for (let j = firstRowCells.length - 1; j >= 0; j--) {
|
|
351
|
+
if (firstRowCells[j]!.pos === columnCells[0]!.pos) {
|
|
352
|
+
headCell = columnCells[0]
|
|
353
|
+
break
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (headCell)
|
|
357
|
+
break
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const $head = tr.doc.resolve(headCell!.pos)
|
|
362
|
+
return { $anchor, $head, indexes }
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const getSelectionRangeInRow = (rowIndex: number, tr: Transaction) => {
|
|
366
|
+
let startIndex = rowIndex
|
|
367
|
+
let endIndex = rowIndex
|
|
368
|
+
// looking for selection start row (startIndex)
|
|
369
|
+
for (let i = rowIndex; i >= 0; i--) {
|
|
370
|
+
const cells = getCellsInRow(i, tr.selection)
|
|
371
|
+
cells!.forEach((cell) => {
|
|
372
|
+
const maybeEndIndex = cell.node.attrs.rowspan + i - 1
|
|
373
|
+
if (maybeEndIndex >= startIndex)
|
|
374
|
+
startIndex = i
|
|
375
|
+
|
|
376
|
+
if (maybeEndIndex > endIndex)
|
|
377
|
+
endIndex = maybeEndIndex
|
|
378
|
+
})
|
|
379
|
+
}
|
|
380
|
+
// looking for selection end row (endIndex)
|
|
381
|
+
for (let i = rowIndex; i <= endIndex; i++) {
|
|
382
|
+
const cells = getCellsInRow(i, tr.selection)
|
|
383
|
+
cells!.forEach((cell) => {
|
|
384
|
+
const maybeEndIndex = cell.node.attrs.rowspan + i - 1
|
|
385
|
+
if (cell.node.attrs.rowspan > 1 && maybeEndIndex > endIndex)
|
|
386
|
+
endIndex = maybeEndIndex
|
|
387
|
+
})
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// filter out rows without cells (where all columns have rowspan > 1 in the same row)
|
|
391
|
+
const indexes = []
|
|
392
|
+
for (let i = startIndex; i <= endIndex; i++) {
|
|
393
|
+
const maybeCells = getCellsInRow(i, tr.selection)
|
|
394
|
+
if (maybeCells && maybeCells.length)
|
|
395
|
+
indexes.push(i)
|
|
396
|
+
}
|
|
397
|
+
startIndex = indexes[0]!
|
|
398
|
+
endIndex = indexes[indexes.length - 1]!
|
|
399
|
+
|
|
400
|
+
const firstSelectedRowCells = getCellsInRow(startIndex, tr.selection)!
|
|
401
|
+
const firstColumnCells = getCellsInCol(0, tr.selection)!
|
|
402
|
+
const $anchor = tr.doc.resolve(firstSelectedRowCells[firstSelectedRowCells.length - 1]!.pos)
|
|
403
|
+
|
|
404
|
+
let headCell: CellPos | undefined
|
|
405
|
+
for (let i = endIndex; i >= startIndex; i--) {
|
|
406
|
+
const rowCells = getCellsInRow(i, tr.selection)
|
|
407
|
+
if (rowCells && rowCells.length) {
|
|
408
|
+
for (let j = firstColumnCells.length - 1; j >= 0; j--) {
|
|
409
|
+
if (firstColumnCells[j]!.pos === rowCells[0]!.pos) {
|
|
410
|
+
headCell = rowCells[0]!
|
|
411
|
+
break
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if (headCell)
|
|
415
|
+
break
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const $head = tr.doc.resolve(headCell!.pos)
|
|
420
|
+
return { $anchor, $head, indexes }
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/// If the selection is in a table,
|
|
424
|
+
/// Move the columns at `origin` to `target` in current table.
|
|
425
|
+
/// The `select` is true by default, which means the selection will be set to the moved column.
|
|
426
|
+
export function moveCol(tr: Transaction, origin: number, target: number, select = true) {
|
|
427
|
+
const table = findTable(tr.selection)
|
|
428
|
+
if (!table)
|
|
429
|
+
return tr
|
|
430
|
+
|
|
431
|
+
const { indexes: indexesOriginColumn } = getSelectionRangeInColumn(origin, tr)
|
|
432
|
+
const { indexes: indexesTargetColumn } = getSelectionRangeInColumn(target, tr)
|
|
433
|
+
|
|
434
|
+
if (indexesOriginColumn.includes(target))
|
|
435
|
+
return tr
|
|
436
|
+
|
|
437
|
+
const newTable = moveTableColumn(
|
|
438
|
+
table,
|
|
439
|
+
indexesOriginColumn,
|
|
440
|
+
indexesTargetColumn,
|
|
441
|
+
0,
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
const _tr = cloneTr(tr).replaceWith(
|
|
445
|
+
table.pos,
|
|
446
|
+
table.pos + table.node.nodeSize,
|
|
447
|
+
newTable,
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
if (!select)
|
|
451
|
+
return _tr
|
|
452
|
+
|
|
453
|
+
const map = TableMap.get(newTable)
|
|
454
|
+
const start = table.start
|
|
455
|
+
const index = target
|
|
456
|
+
const lastCell = map.positionAt(map.height - 1, index, newTable)
|
|
457
|
+
const $lastCell = _tr.doc.resolve(start + lastCell)
|
|
458
|
+
|
|
459
|
+
const createCellSelection = CellSelection.colSelection
|
|
460
|
+
|
|
461
|
+
const firstCell = map.positionAt(0, index, newTable)
|
|
462
|
+
const $firstCell = _tr.doc.resolve(start + firstCell)
|
|
463
|
+
|
|
464
|
+
return _tr.setSelection(createCellSelection($lastCell, $firstCell))
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/// If the selection is in a table,
|
|
468
|
+
/// Move the rows at `origin` and `target` in current table.
|
|
469
|
+
/// The `select` is true by default, which means the selection will be set to the moved row.
|
|
470
|
+
export function moveRow(tr: Transaction, origin: number, target: number, select = true) {
|
|
471
|
+
const table = findTable(tr.selection)
|
|
472
|
+
if (!table)
|
|
473
|
+
return tr
|
|
474
|
+
|
|
475
|
+
const { indexes: indexesOriginRow } = getSelectionRangeInRow(origin, tr)
|
|
476
|
+
const { indexes: indexesTargetRow } = getSelectionRangeInRow(target, tr)
|
|
477
|
+
|
|
478
|
+
if (indexesOriginRow.includes(target))
|
|
479
|
+
return tr
|
|
480
|
+
|
|
481
|
+
const newTable = moveTableRow(
|
|
482
|
+
table,
|
|
483
|
+
indexesOriginRow,
|
|
484
|
+
indexesTargetRow,
|
|
485
|
+
0,
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
const _tr = cloneTr(tr).replaceWith(
|
|
489
|
+
table.pos,
|
|
490
|
+
table.pos + table.node.nodeSize,
|
|
491
|
+
newTable,
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
if (!select)
|
|
495
|
+
return _tr
|
|
496
|
+
|
|
497
|
+
const map = TableMap.get(newTable)
|
|
498
|
+
const start = table.start
|
|
499
|
+
const index = target
|
|
500
|
+
const lastCell = map.positionAt(index, map.width - 1, newTable)
|
|
501
|
+
const $lastCell = _tr.doc.resolve(start + lastCell)
|
|
502
|
+
|
|
503
|
+
const createCellSelection = CellSelection.rowSelection
|
|
504
|
+
|
|
505
|
+
const firstCell = map.positionAt(index, 0, newTable)
|
|
506
|
+
const $firstCell = _tr.doc.resolve(start + firstCell)
|
|
507
|
+
|
|
508
|
+
return _tr.setSelection(createCellSelection($lastCell, $firstCell))
|
|
509
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import { expectDomTypeError } from '@milkdown/exception'
|
|
3
|
+
import { listItemSchema } from '@milkdown/preset-commonmark'
|
|
4
|
+
|
|
5
|
+
/// This schema extends the [list item](/preset-commonmark#list-item) schema and add task list support for it.
|
|
6
|
+
export const extendListItemSchemaForTask = listItemSchema.extendSchema((prev) => {
|
|
7
|
+
return (ctx) => {
|
|
8
|
+
const baseSchema = prev(ctx)
|
|
9
|
+
return {
|
|
10
|
+
...baseSchema,
|
|
11
|
+
attrs: {
|
|
12
|
+
...baseSchema.attrs,
|
|
13
|
+
checked: {
|
|
14
|
+
default: null,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
parseDOM: [
|
|
18
|
+
{
|
|
19
|
+
tag: 'li[data-item-type="task"]',
|
|
20
|
+
getAttrs: (dom) => {
|
|
21
|
+
if (!(dom instanceof HTMLElement))
|
|
22
|
+
throw expectDomTypeError(dom)
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
label: dom.dataset.label,
|
|
26
|
+
listType: dom.dataset['list-type'],
|
|
27
|
+
spread: dom.dataset.spread,
|
|
28
|
+
checked: dom.dataset.checked ? dom.dataset.checked === 'true' : null,
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
...baseSchema?.parseDOM || [],
|
|
33
|
+
],
|
|
34
|
+
toDOM: (node) => {
|
|
35
|
+
if (baseSchema.toDOM && node.attrs.checked == null)
|
|
36
|
+
return baseSchema.toDOM(node)
|
|
37
|
+
|
|
38
|
+
return [
|
|
39
|
+
'li',
|
|
40
|
+
{
|
|
41
|
+
'data-item-type': 'task',
|
|
42
|
+
'data-label': node.attrs.label,
|
|
43
|
+
'data-list-type': node.attrs.listType,
|
|
44
|
+
'data-spread': node.attrs.spread,
|
|
45
|
+
'data-checked': node.attrs.checked,
|
|
46
|
+
},
|
|
47
|
+
0,
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
parseMarkdown: {
|
|
51
|
+
match: ({ type }) => type === 'listItem',
|
|
52
|
+
runner: (state, node, type) => {
|
|
53
|
+
if (node.checked == null) {
|
|
54
|
+
baseSchema.parseMarkdown.runner(state, node, type)
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const label = node.label != null ? `${node.label}.` : '•'
|
|
59
|
+
const checked = node.checked != null ? Boolean(node.checked) : null
|
|
60
|
+
const listType = node.label != null ? 'ordered' : 'bullet'
|
|
61
|
+
const spread = node.spread != null ? `${node.spread}` : 'true'
|
|
62
|
+
|
|
63
|
+
state.openNode(type, { label, listType, spread, checked })
|
|
64
|
+
state.next(node.children)
|
|
65
|
+
state.closeNode()
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
toMarkdown: {
|
|
69
|
+
match: node => node.type.name === 'list_item',
|
|
70
|
+
runner: (state, node) => {
|
|
71
|
+
if (node.attrs.checked == null) {
|
|
72
|
+
baseSchema.toMarkdown.runner(state, node)
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const label = node.attrs.label
|
|
77
|
+
const listType = node.attrs.listType
|
|
78
|
+
const spread = node.attrs.spread === 'true'
|
|
79
|
+
const checked = node.attrs.checked
|
|
80
|
+
|
|
81
|
+
state.openNode('listItem', undefined, { label, listType, spread, checked })
|
|
82
|
+
state.next(node.content)
|
|
83
|
+
state.closeNode()
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
})
|
package/src/{table/plugin/auto-insert-zero-space.ts → plugin/auto-insert-zero-space-plugin.ts}
RENAMED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
2
|
import { browser } from '@milkdown/prose'
|
|
3
3
|
import type { Node } from '@milkdown/prose/model'
|
|
4
|
+
import { isInTable } from '@milkdown/prose/tables'
|
|
4
5
|
import { Plugin, PluginKey } from '@milkdown/prose/state'
|
|
6
|
+
import { paragraphSchema } from '@milkdown/preset-commonmark'
|
|
7
|
+
import { $prose } from '@milkdown/utils'
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
/// This plugin is used to fix the bug of IME composing in table in Safari browser.
|
|
10
|
+
/// original discussion in https://discuss.prosemirror.net/t/ime-composing-problems-on-td-or-th-element-in-safari-browser/4501
|
|
11
|
+
export const autoInsertZeroSpaceInTablePlugin = $prose(() => {
|
|
12
|
+
const pluginKey = new PluginKey('MILKDOWN_AUTO_INSERT_ZERO_SPACE')
|
|
7
13
|
|
|
8
|
-
const
|
|
9
|
-
return node.type.name === 'paragraph' && node.nodeSize === 2
|
|
10
|
-
}
|
|
14
|
+
const isParagraph = (node: Node) => node.type === paragraphSchema.type()
|
|
11
15
|
|
|
12
|
-
const
|
|
13
|
-
return node.type.name === 'paragraph'
|
|
14
|
-
}
|
|
16
|
+
const isEmptyParagraph = (node: Node) => isParagraph(node) && node.nodeSize === 2
|
|
15
17
|
|
|
16
|
-
const pluginKey = new PluginKey('plugin_autoInsertZeroSpace')
|
|
17
|
-
|
|
18
|
-
export const autoInsertZeroSpace = () => {
|
|
19
18
|
return new Plugin({
|
|
20
19
|
key: pluginKey,
|
|
21
20
|
props: {
|
|
@@ -36,10 +35,10 @@ export const autoInsertZeroSpace = () => {
|
|
|
36
35
|
|
|
37
36
|
if (
|
|
38
37
|
browser.safari
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
&& isInTable(state)
|
|
39
|
+
&& selection.empty
|
|
40
|
+
&& isParagraph($from.parent)
|
|
41
|
+
&& $from.parent.textContent.startsWith('\u2060')
|
|
43
42
|
)
|
|
44
43
|
dispatch(tr.delete($from.start(), $from.start() + 1))
|
|
45
44
|
|
|
@@ -48,4 +47,4 @@ export const autoInsertZeroSpace = () => {
|
|
|
48
47
|
},
|
|
49
48
|
},
|
|
50
49
|
})
|
|
51
|
-
}
|
|
50
|
+
})
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import { columnResizing } from '@milkdown/prose/tables'
|
|
3
|
+
import { $prose } from '@milkdown/utils'
|
|
4
|
+
|
|
5
|
+
/// This plugin is wrapping the `columnResizing` plugin from [prosemirror-tables](https://github.com/ProseMirror/prosemirror-tables).
|
|
6
|
+
export const columnResizingPlugin = $prose(() => columnResizing({}))
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import { $remark } from '@milkdown/utils'
|
|
3
|
+
import remarkGFM from 'remark-gfm'
|
|
4
|
+
|
|
5
|
+
/// This plugin is wrapping the [remark-gfm](https://github.com/remarkjs/remark-gfm).
|
|
6
|
+
export const remarkGFMPlugin = $remark(() => remarkGFM)
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import { tableEditing } from '@milkdown/prose/tables'
|
|
3
|
+
import { $prose } from '@milkdown/utils'
|
|
4
|
+
|
|
5
|
+
/// This plugin is wrapping the `tableEditing` plugin from [prosemirror-tables](https://github.com/ProseMirror/prosemirror-tables).
|
|
6
|
+
export const tableEditingPlugin = $prose(() => tableEditing())
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/footnote/definition.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,iBAAiB,yCAA4C,CAAA;AAE1E,eAAO,MAAM,kBAAkB,mDA0K7B,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/footnote/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../src/footnote/reference.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,iBAAiB,yCAA4C,CAAA;AAG1E,eAAO,MAAM,iBAAiB,mDAiK5B,CAAA"}
|