@milkdown/preset-gfm 7.15.0 → 7.15.2
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/index.js +265 -205
- package/lib/index.js.map +1 -1
- package/lib/mark/strike-through.d.ts.map +1 -1
- package/lib/node/table/command.d.ts.map +1 -1
- package/lib/node/table/utils/add-row-with-alignment.d.ts +5 -0
- package/lib/node/table/utils/add-row-with-alignment.d.ts.map +1 -0
- package/lib/node/table/utils/convert-rows-to-table.d.ts +3 -0
- package/lib/node/table/utils/convert-rows-to-table.d.ts.map +1 -0
- package/lib/node/table/utils/convert-table-to-rows.d.ts +3 -0
- package/lib/node/table/utils/convert-table-to-rows.d.ts.map +1 -0
- package/lib/node/table/utils/create-table.d.ts +4 -0
- package/lib/node/table/utils/create-table.d.ts.map +1 -0
- package/lib/node/table/utils/find-table.d.ts +3 -0
- package/lib/node/table/utils/find-table.d.ts.map +1 -0
- package/lib/node/table/utils/get-all-cells-in-table.d.ts +7 -0
- package/lib/node/table/utils/get-all-cells-in-table.d.ts.map +1 -0
- package/lib/node/table/utils/get-cells-in-col.d.ts +4 -0
- package/lib/node/table/utils/get-cells-in-col.d.ts.map +1 -0
- package/lib/node/table/utils/get-cells-in-row.d.ts +4 -0
- package/lib/node/table/utils/get-cells-in-row.d.ts.map +1 -0
- package/lib/node/table/utils/get-selection-range-in-col.d.ts +4 -0
- package/lib/node/table/utils/get-selection-range-in-col.d.ts.map +1 -0
- package/lib/node/table/utils/get-selection-range-in-row.d.ts +4 -0
- package/lib/node/table/utils/get-selection-range-in-row.d.ts.map +1 -0
- package/lib/node/table/utils/index.d.ts +12 -0
- package/lib/node/table/utils/index.d.ts.map +1 -0
- package/lib/node/table/utils/move-col.d.ts +10 -0
- package/lib/node/table/utils/move-col.d.ts.map +1 -0
- package/lib/node/table/utils/move-row-in-array-of-rows.d.ts +3 -0
- package/lib/node/table/utils/move-row-in-array-of-rows.d.ts.map +1 -0
- package/lib/node/table/utils/move-row.d.ts +10 -0
- package/lib/node/table/utils/move-row.d.ts.map +1 -0
- package/lib/node/table/utils/select-line.d.ts +5 -0
- package/lib/node/table/utils/select-line.d.ts.map +1 -0
- package/lib/node/table/utils/select-table.d.ts +3 -0
- package/lib/node/table/utils/select-table.d.ts.map +1 -0
- package/lib/node/table/utils/transpose.d.ts +2 -0
- package/lib/node/table/utils/transpose.d.ts.map +1 -0
- package/lib/node/table/utils/types.d.ts +12 -0
- package/lib/node/table/utils/types.d.ts.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/src/mark/strike-through.ts +4 -1
- package/src/node/table/command.ts +28 -10
- package/src/node/table/utils/add-row-with-alignment.ts +32 -0
- package/src/node/table/utils/convert-rows-to-table.ts +43 -0
- package/src/node/table/utils/convert-table-to-rows.ts +65 -0
- package/src/node/table/utils/create-table.ts +31 -0
- package/src/node/table/utils/find-table.ts +10 -0
- package/src/node/table/utils/get-all-cells-in-table.ts +24 -0
- package/src/node/table/utils/get-cells-in-col.ts +35 -0
- package/src/node/table/utils/get-cells-in-row.ts +37 -0
- package/src/node/table/utils/get-selection-range-in-col.ts +86 -0
- package/src/node/table/utils/get-selection-range-in-row.ts +86 -0
- package/src/node/table/utils/index.ts +11 -0
- package/src/node/table/utils/move-col.ts +73 -0
- package/src/node/table/utils/move-row-in-array-of-rows.ts +29 -0
- package/src/node/table/utils/move-row.ts +71 -0
- package/src/node/table/utils/select-line.ts +61 -0
- package/src/node/table/utils/select-table.ts +20 -0
- package/src/node/table/utils/transpose.ts +26 -0
- package/src/node/table/utils/types.ts +16 -0
- package/lib/node/table/utils.d.ts +0 -41
- package/lib/node/table/utils.d.ts.map +0 -1
- package/src/node/table/utils.ts +0 -564
|
@@ -112,11 +112,20 @@ export const moveRowCommand = $command(
|
|
|
112
112
|
({ from, to, pos }: { from?: number; to?: number; pos?: number } = {}) =>
|
|
113
113
|
(state, dispatch) => {
|
|
114
114
|
const { tr } = state
|
|
115
|
-
|
|
116
|
-
moveRow({
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
115
|
+
if (
|
|
116
|
+
moveRow({
|
|
117
|
+
tr,
|
|
118
|
+
origin: from ?? 0,
|
|
119
|
+
target: to ?? 0,
|
|
120
|
+
pos: pos ?? state.selection.from,
|
|
121
|
+
select: true,
|
|
122
|
+
})
|
|
123
|
+
) {
|
|
124
|
+
dispatch?.(tr)
|
|
125
|
+
return true
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return false
|
|
120
129
|
}
|
|
121
130
|
)
|
|
122
131
|
|
|
@@ -133,11 +142,20 @@ export const moveColCommand = $command(
|
|
|
133
142
|
({ from, to, pos }: { from?: number; to?: number; pos?: number } = {}) =>
|
|
134
143
|
(state, dispatch) => {
|
|
135
144
|
const { tr } = state
|
|
136
|
-
|
|
137
|
-
moveCol({
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
145
|
+
if (
|
|
146
|
+
moveCol({
|
|
147
|
+
tr,
|
|
148
|
+
origin: from ?? 0,
|
|
149
|
+
target: to ?? 0,
|
|
150
|
+
pos: pos ?? state.selection.from,
|
|
151
|
+
select: true,
|
|
152
|
+
})
|
|
153
|
+
) {
|
|
154
|
+
dispatch?.(tr)
|
|
155
|
+
return true
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return false
|
|
141
159
|
}
|
|
142
160
|
)
|
|
143
161
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Ctx } from '@milkdown/ctx'
|
|
2
|
+
import type { Node } from '@milkdown/prose/model'
|
|
3
|
+
import type { Transaction } from '@milkdown/prose/state'
|
|
4
|
+
import type { TableRect } from '@milkdown/prose/tables'
|
|
5
|
+
|
|
6
|
+
import { tableCellSchema, tableRowSchema } from '../schema'
|
|
7
|
+
|
|
8
|
+
/// @internal
|
|
9
|
+
export function addRowWithAlignment(
|
|
10
|
+
ctx: Ctx,
|
|
11
|
+
tr: Transaction,
|
|
12
|
+
{ map, tableStart, table }: TableRect,
|
|
13
|
+
row: number
|
|
14
|
+
) {
|
|
15
|
+
const rowPos = Array(row)
|
|
16
|
+
.fill(0)
|
|
17
|
+
.reduce((acc, _, i) => {
|
|
18
|
+
return acc + table.child(i).nodeSize
|
|
19
|
+
}, tableStart)
|
|
20
|
+
|
|
21
|
+
const cells = Array(map.width)
|
|
22
|
+
.fill(0)
|
|
23
|
+
.map((_, col) => {
|
|
24
|
+
const headerCol = table.nodeAt(map.map[col] as number)
|
|
25
|
+
return tableCellSchema
|
|
26
|
+
.type(ctx)
|
|
27
|
+
.createAndFill({ alignment: headerCol?.attrs.alignment }) as Node
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
tr.insert(rowPos, tableRowSchema.type(ctx).create(null, cells))
|
|
31
|
+
return tr
|
|
32
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Node } from '@milkdown/prose/model'
|
|
2
|
+
|
|
3
|
+
import { TableMap } from '@milkdown/prose/tables'
|
|
4
|
+
|
|
5
|
+
/// @internal
|
|
6
|
+
///
|
|
7
|
+
/// Convert an array of rows to a table node.
|
|
8
|
+
export function convertRowsToTable(
|
|
9
|
+
tableNode: Node,
|
|
10
|
+
arrayOfNodes: (Node | null)[][]
|
|
11
|
+
) {
|
|
12
|
+
const rowsPM = []
|
|
13
|
+
const map = TableMap.get(tableNode)
|
|
14
|
+
for (let rowIndex = 0; rowIndex < map.height; rowIndex++) {
|
|
15
|
+
const row = tableNode.child(rowIndex)
|
|
16
|
+
const rowCells = []
|
|
17
|
+
|
|
18
|
+
for (let colIndex = 0; colIndex < map.width; colIndex++) {
|
|
19
|
+
if (!arrayOfNodes[rowIndex]![colIndex]) continue
|
|
20
|
+
|
|
21
|
+
const cellPos = map.map[rowIndex * map.width + colIndex]!
|
|
22
|
+
|
|
23
|
+
const cell = arrayOfNodes[rowIndex]![colIndex]!
|
|
24
|
+
const oldCell = tableNode.nodeAt(cellPos)!
|
|
25
|
+
const newCell = oldCell.type.createChecked(
|
|
26
|
+
Object.assign({}, cell.attrs),
|
|
27
|
+
cell.content,
|
|
28
|
+
cell.marks
|
|
29
|
+
)
|
|
30
|
+
rowCells.push(newCell)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
rowsPM.push(row.type.createChecked(row.attrs, rowCells, row.marks))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const newTable = tableNode.type.createChecked(
|
|
37
|
+
tableNode.attrs,
|
|
38
|
+
rowsPM,
|
|
39
|
+
tableNode.marks
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
return newTable
|
|
43
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Node } from '@milkdown/prose/model'
|
|
2
|
+
|
|
3
|
+
import { TableMap } from '@milkdown/prose/tables'
|
|
4
|
+
|
|
5
|
+
/// @internal
|
|
6
|
+
///
|
|
7
|
+
/// This function will transform the table node into a matrix of rows and columns
|
|
8
|
+
/// respecting merged cells, for example this table:
|
|
9
|
+
///
|
|
10
|
+
/// ```
|
|
11
|
+
/// ┌──────┬──────┬─────────────┐
|
|
12
|
+
/// │ A1 │ B1 │ C1 │
|
|
13
|
+
/// ├──────┼──────┴──────┬──────┤
|
|
14
|
+
/// │ A2 │ B2 │ │
|
|
15
|
+
/// ├──────┼─────────────┤ D1 │
|
|
16
|
+
/// │ A3 │ B3 │ C3 │ │
|
|
17
|
+
/// └──────┴──────┴──────┴──────┘
|
|
18
|
+
/// ```
|
|
19
|
+
///
|
|
20
|
+
/// will be converted to the below:
|
|
21
|
+
///
|
|
22
|
+
/// ```javascript
|
|
23
|
+
/// [
|
|
24
|
+
/// [A1, B1, C1, null],
|
|
25
|
+
/// [A2, B2, null, D1],
|
|
26
|
+
/// [A3, B3, C3, null],
|
|
27
|
+
/// ]
|
|
28
|
+
/// ```
|
|
29
|
+
export function convertTableToRows(tableNode: Node): (Node | null)[][] {
|
|
30
|
+
const map = TableMap.get(tableNode)
|
|
31
|
+
const rows: (Node | null)[][] = []
|
|
32
|
+
const rowCount = map.height
|
|
33
|
+
const colCount = map.width
|
|
34
|
+
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
|
35
|
+
const row: (Node | null)[] = []
|
|
36
|
+
for (let colIndex = 0; colIndex < colCount; colIndex++) {
|
|
37
|
+
let cellIndex = rowIndex * colCount + colIndex
|
|
38
|
+
let cellPos = map.map[cellIndex]
|
|
39
|
+
if (rowIndex > 0) {
|
|
40
|
+
const topCellIndex = cellIndex - colCount
|
|
41
|
+
const topCellPos = map.map[topCellIndex]
|
|
42
|
+
if (cellPos === topCellPos) {
|
|
43
|
+
row.push(null)
|
|
44
|
+
continue
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (colIndex > 0) {
|
|
48
|
+
const leftCellIndex = cellIndex - 1
|
|
49
|
+
const leftCellPos = map.map[leftCellIndex]
|
|
50
|
+
if (cellPos === leftCellPos) {
|
|
51
|
+
row.push(null)
|
|
52
|
+
continue
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!cellPos) {
|
|
56
|
+
row.push(null)
|
|
57
|
+
} else {
|
|
58
|
+
row.push(tableNode.nodeAt(cellPos))
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
rows.push(row)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return rows
|
|
65
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Ctx } from '@milkdown/ctx'
|
|
2
|
+
import type { Node } from '@milkdown/prose/model'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
tableCellSchema,
|
|
6
|
+
tableHeaderRowSchema,
|
|
7
|
+
tableHeaderSchema,
|
|
8
|
+
tableRowSchema,
|
|
9
|
+
tableSchema,
|
|
10
|
+
} from '../schema'
|
|
11
|
+
|
|
12
|
+
/// @internal
|
|
13
|
+
export function createTable(ctx: Ctx, rowsCount = 3, colsCount = 3): Node {
|
|
14
|
+
const cells = Array(colsCount)
|
|
15
|
+
.fill(0)
|
|
16
|
+
.map(() => tableCellSchema.type(ctx).createAndFill()!)
|
|
17
|
+
|
|
18
|
+
const headerCells = Array(colsCount)
|
|
19
|
+
.fill(0)
|
|
20
|
+
.map(() => tableHeaderSchema.type(ctx).createAndFill()!)
|
|
21
|
+
|
|
22
|
+
const rows = Array(rowsCount)
|
|
23
|
+
.fill(0)
|
|
24
|
+
.map((_, i) =>
|
|
25
|
+
i === 0
|
|
26
|
+
? tableHeaderRowSchema.type(ctx).create(null, headerCells)
|
|
27
|
+
: tableRowSchema.type(ctx).create(null, cells)
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
return tableSchema.type(ctx).create(null, rows)
|
|
31
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ResolvedPos } from '@milkdown/prose/model'
|
|
2
|
+
|
|
3
|
+
import { findParentNodeClosestToPos } from '@milkdown/prose'
|
|
4
|
+
|
|
5
|
+
/// Find the table node with position information for target pos.
|
|
6
|
+
export function findTable($pos: ResolvedPos) {
|
|
7
|
+
return findParentNodeClosestToPos(
|
|
8
|
+
(node) => node.type.spec.tableRole === 'table'
|
|
9
|
+
)($pos)
|
|
10
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Selection } from '@milkdown/prose/state'
|
|
2
|
+
|
|
3
|
+
import { TableMap } from '@milkdown/prose/tables'
|
|
4
|
+
|
|
5
|
+
import { findTable } from './find-table'
|
|
6
|
+
|
|
7
|
+
/// Get all cells in a table.
|
|
8
|
+
export function getAllCellsInTable(selection: Selection) {
|
|
9
|
+
const table = findTable(selection.$from)
|
|
10
|
+
if (!table) return
|
|
11
|
+
|
|
12
|
+
const map = TableMap.get(table.node)
|
|
13
|
+
const cells = map.cellsInRect({
|
|
14
|
+
left: 0,
|
|
15
|
+
right: map.width,
|
|
16
|
+
top: 0,
|
|
17
|
+
bottom: map.height,
|
|
18
|
+
})
|
|
19
|
+
return cells.map((nodePos) => {
|
|
20
|
+
const node = table.node.nodeAt(nodePos)
|
|
21
|
+
const pos = nodePos + table.start
|
|
22
|
+
return { pos, start: pos + 1, node }
|
|
23
|
+
})
|
|
24
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Selection } from '@milkdown/prose/state'
|
|
2
|
+
|
|
3
|
+
import { TableMap } from '@milkdown/prose/tables'
|
|
4
|
+
|
|
5
|
+
import type { CellPos } from './types'
|
|
6
|
+
|
|
7
|
+
import { findTable } from './find-table'
|
|
8
|
+
|
|
9
|
+
/// Get cells in a column of a table.
|
|
10
|
+
export function getCellsInCol(
|
|
11
|
+
columnIndexes: number | number[],
|
|
12
|
+
selection: Selection
|
|
13
|
+
): CellPos[] | undefined {
|
|
14
|
+
const table = findTable(selection.$from)
|
|
15
|
+
if (!table) return undefined
|
|
16
|
+
|
|
17
|
+
const map = TableMap.get(table.node)
|
|
18
|
+
const indexes = Array.isArray(columnIndexes) ? columnIndexes : [columnIndexes]
|
|
19
|
+
|
|
20
|
+
return indexes
|
|
21
|
+
.filter((index) => index >= 0 && index <= map.width - 1)
|
|
22
|
+
.flatMap((index) => {
|
|
23
|
+
const cells = map.cellsInRect({
|
|
24
|
+
left: index,
|
|
25
|
+
right: index + 1,
|
|
26
|
+
top: 0,
|
|
27
|
+
bottom: map.height,
|
|
28
|
+
})
|
|
29
|
+
return cells.map((nodePos) => {
|
|
30
|
+
const node = table.node.nodeAt(nodePos)!
|
|
31
|
+
const pos = nodePos + table.start
|
|
32
|
+
return { pos, start: pos + 1, node, depth: table.depth + 2 }
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Selection } from '@milkdown/prose/state'
|
|
2
|
+
|
|
3
|
+
import { TableMap } from '@milkdown/prose/tables'
|
|
4
|
+
|
|
5
|
+
import type { CellPos } from './types'
|
|
6
|
+
|
|
7
|
+
import { findTable } from './find-table'
|
|
8
|
+
|
|
9
|
+
/// Get cells in a row of a table.
|
|
10
|
+
export function getCellsInRow(
|
|
11
|
+
rowIndex: number | number[],
|
|
12
|
+
selection: Selection
|
|
13
|
+
): CellPos[] | undefined {
|
|
14
|
+
const table = findTable(selection.$from)
|
|
15
|
+
if (!table) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const map = TableMap.get(table.node)
|
|
20
|
+
const indexes = Array.isArray(rowIndex) ? rowIndex : [rowIndex]
|
|
21
|
+
|
|
22
|
+
return indexes
|
|
23
|
+
.filter((index) => index >= 0 && index <= map.height - 1)
|
|
24
|
+
.flatMap((index) => {
|
|
25
|
+
const cells = map.cellsInRect({
|
|
26
|
+
left: 0,
|
|
27
|
+
right: map.width,
|
|
28
|
+
top: index,
|
|
29
|
+
bottom: index + 1,
|
|
30
|
+
})
|
|
31
|
+
return cells.map((nodePos) => {
|
|
32
|
+
const node = table.node.nodeAt(nodePos)!
|
|
33
|
+
const pos = nodePos + table.start
|
|
34
|
+
return { pos, start: pos + 1, node, depth: table.depth + 2 }
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { Transaction } from '@milkdown/prose/state'
|
|
2
|
+
|
|
3
|
+
import type { CellSelectionRange } from './types'
|
|
4
|
+
|
|
5
|
+
import { getCellsInCol } from './get-cells-in-col'
|
|
6
|
+
import { getCellsInRow } from './get-cells-in-row'
|
|
7
|
+
|
|
8
|
+
export function getSelectionRangeInCol(
|
|
9
|
+
tr: Transaction,
|
|
10
|
+
startColIndex: number,
|
|
11
|
+
endColIndex: number = startColIndex
|
|
12
|
+
): CellSelectionRange | undefined {
|
|
13
|
+
let startIndex = startColIndex
|
|
14
|
+
let endIndex = endColIndex
|
|
15
|
+
|
|
16
|
+
// looking for selection start column (startIndex)
|
|
17
|
+
for (let i = startColIndex; i >= 0; i--) {
|
|
18
|
+
const cells = getCellsInCol(i, tr.selection)
|
|
19
|
+
if (cells) {
|
|
20
|
+
cells.forEach((cell) => {
|
|
21
|
+
const maybeEndIndex = cell.node.attrs.colspan + i - 1
|
|
22
|
+
if (maybeEndIndex >= startIndex) {
|
|
23
|
+
startIndex = i
|
|
24
|
+
}
|
|
25
|
+
if (maybeEndIndex > endIndex) {
|
|
26
|
+
endIndex = maybeEndIndex
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// looking for selection end column (endIndex)
|
|
32
|
+
for (let i = startColIndex; i <= endIndex; i++) {
|
|
33
|
+
const cells = getCellsInCol(i, tr.selection)
|
|
34
|
+
if (cells) {
|
|
35
|
+
cells.forEach((cell) => {
|
|
36
|
+
const maybeEndIndex = cell.node.attrs.colspan + i - 1
|
|
37
|
+
if (cell.node.attrs.colspan > 1 && maybeEndIndex > endIndex) {
|
|
38
|
+
endIndex = maybeEndIndex
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// filter out columns without cells (where all rows have colspan > 1 in the same column)
|
|
45
|
+
const indexes = []
|
|
46
|
+
for (let i = startIndex; i <= endIndex; i++) {
|
|
47
|
+
const maybeCells = getCellsInCol(i, tr.selection)
|
|
48
|
+
if (maybeCells && maybeCells.length > 0) {
|
|
49
|
+
indexes.push(i)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
startIndex = indexes[0]!
|
|
53
|
+
endIndex = indexes[indexes.length - 1]!
|
|
54
|
+
|
|
55
|
+
const firstSelectedColumnCells = getCellsInCol(startIndex, tr.selection)
|
|
56
|
+
const firstRowCells = getCellsInRow(0, tr.selection)
|
|
57
|
+
if (!firstSelectedColumnCells || !firstRowCells) {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const $anchor = tr.doc.resolve(
|
|
62
|
+
firstSelectedColumnCells[firstSelectedColumnCells.length - 1]!.pos
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
let headCell
|
|
66
|
+
for (let i = endIndex; i >= startIndex; i--) {
|
|
67
|
+
const columnCells = getCellsInCol(i, tr.selection)
|
|
68
|
+
if (columnCells && columnCells.length > 0) {
|
|
69
|
+
for (let j = firstRowCells.length - 1; j >= 0; j--) {
|
|
70
|
+
if (firstRowCells[j]!.pos === columnCells[0]!.pos) {
|
|
71
|
+
headCell = columnCells[0]
|
|
72
|
+
break
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (headCell) {
|
|
76
|
+
break
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!headCell) {
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const $head = tr.doc.resolve(headCell.pos)
|
|
85
|
+
return { $anchor, $head, indexes }
|
|
86
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { Transaction } from '@milkdown/prose/state'
|
|
2
|
+
|
|
3
|
+
import type { CellSelectionRange } from './types'
|
|
4
|
+
|
|
5
|
+
import { getCellsInCol } from './get-cells-in-col'
|
|
6
|
+
import { getCellsInRow } from './get-cells-in-row'
|
|
7
|
+
|
|
8
|
+
export function getSelectionRangeInRow(
|
|
9
|
+
tr: Transaction,
|
|
10
|
+
startRowIndex: number,
|
|
11
|
+
endRowIndex: number = startRowIndex
|
|
12
|
+
): CellSelectionRange | undefined {
|
|
13
|
+
let startIndex = startRowIndex
|
|
14
|
+
let endIndex = endRowIndex
|
|
15
|
+
|
|
16
|
+
// looking for selection start row (startIndex)
|
|
17
|
+
for (let i = startRowIndex; i >= 0; i--) {
|
|
18
|
+
const cells = getCellsInRow(i, tr.selection)
|
|
19
|
+
if (cells) {
|
|
20
|
+
cells.forEach((cell) => {
|
|
21
|
+
const maybeEndIndex = cell.node.attrs.rowspan + i - 1
|
|
22
|
+
if (maybeEndIndex >= startIndex) {
|
|
23
|
+
startIndex = i
|
|
24
|
+
}
|
|
25
|
+
if (maybeEndIndex > endIndex) {
|
|
26
|
+
endIndex = maybeEndIndex
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// looking for selection end row (endIndex)
|
|
32
|
+
for (let i = startRowIndex; i <= endIndex; i++) {
|
|
33
|
+
const cells = getCellsInRow(i, tr.selection)
|
|
34
|
+
if (cells) {
|
|
35
|
+
cells.forEach((cell) => {
|
|
36
|
+
const maybeEndIndex = cell.node.attrs.rowspan + i - 1
|
|
37
|
+
if (cell.node.attrs.rowspan > 1 && maybeEndIndex > endIndex) {
|
|
38
|
+
endIndex = maybeEndIndex
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// filter out rows without cells (where all columns have rowspan > 1 in the same row)
|
|
45
|
+
const indexes = []
|
|
46
|
+
for (let i = startIndex; i <= endIndex; i++) {
|
|
47
|
+
const maybeCells = getCellsInRow(i, tr.selection)
|
|
48
|
+
if (maybeCells && maybeCells.length > 0) {
|
|
49
|
+
indexes.push(i)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
startIndex = indexes[0]!
|
|
53
|
+
endIndex = indexes[indexes.length - 1]!
|
|
54
|
+
|
|
55
|
+
const firstSelectedRowCells = getCellsInRow(startIndex, tr.selection)
|
|
56
|
+
const firstColumnCells = getCellsInCol(0, tr.selection)
|
|
57
|
+
if (!firstSelectedRowCells || !firstColumnCells) {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const $anchor = tr.doc.resolve(
|
|
62
|
+
firstSelectedRowCells[firstSelectedRowCells.length - 1]!.pos
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
let headCell
|
|
66
|
+
for (let i = endIndex; i >= startIndex; i--) {
|
|
67
|
+
const rowCells = getCellsInRow(i, tr.selection)
|
|
68
|
+
if (rowCells && rowCells.length > 0) {
|
|
69
|
+
for (let j = firstColumnCells.length - 1; j >= 0; j--) {
|
|
70
|
+
if (firstColumnCells[j]!.pos === rowCells[0]!.pos) {
|
|
71
|
+
headCell = rowCells[0]
|
|
72
|
+
break
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (headCell) {
|
|
76
|
+
break
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!headCell) {
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const $head = tr.doc.resolve(headCell.pos)
|
|
85
|
+
return { $anchor, $head, indexes }
|
|
86
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './create-table'
|
|
2
|
+
export * from './find-table'
|
|
3
|
+
export * from './get-cells-in-col'
|
|
4
|
+
export * from './get-cells-in-row'
|
|
5
|
+
export * from './select-line'
|
|
6
|
+
export * from './types'
|
|
7
|
+
export * from './add-row-with-alignment'
|
|
8
|
+
export * from './move-row'
|
|
9
|
+
export * from './move-col'
|
|
10
|
+
export * from './select-table'
|
|
11
|
+
export * from './get-all-cells-in-table'
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Node } from '@milkdown/prose/model'
|
|
2
|
+
import type { Transaction } from '@milkdown/prose/state'
|
|
3
|
+
|
|
4
|
+
import { CellSelection, TableMap } from '@milkdown/prose/tables'
|
|
5
|
+
|
|
6
|
+
import { convertRowsToTable } from './convert-rows-to-table'
|
|
7
|
+
import { convertTableToRows } from './convert-table-to-rows'
|
|
8
|
+
import { findTable } from './find-table'
|
|
9
|
+
import { getSelectionRangeInCol } from './get-selection-range-in-col'
|
|
10
|
+
import { moveRowInArrayOfRows } from './move-row-in-array-of-rows'
|
|
11
|
+
import { transpose } from './transpose'
|
|
12
|
+
|
|
13
|
+
export interface MoveColParams {
|
|
14
|
+
tr: Transaction
|
|
15
|
+
origin: number
|
|
16
|
+
target: number
|
|
17
|
+
pos: number
|
|
18
|
+
select?: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// If the selection is in a table,
|
|
22
|
+
/// Move the columns at `origin` to `target` in current table.
|
|
23
|
+
/// The `select` is true by default, which means the selection will be set to the moved column.
|
|
24
|
+
export function moveCol(moveColParams: MoveColParams) {
|
|
25
|
+
const { tr, origin, target, select, pos } = moveColParams
|
|
26
|
+
const $pos = tr.doc.resolve(pos)
|
|
27
|
+
const table = findTable($pos)
|
|
28
|
+
if (!table) return false
|
|
29
|
+
|
|
30
|
+
const indexesOriginColumn = getSelectionRangeInCol(tr, origin)?.indexes
|
|
31
|
+
const indexesTargetColumn = getSelectionRangeInCol(tr, target)?.indexes
|
|
32
|
+
|
|
33
|
+
if (!indexesOriginColumn || !indexesTargetColumn) return false
|
|
34
|
+
|
|
35
|
+
if (indexesOriginColumn.includes(target)) return false
|
|
36
|
+
|
|
37
|
+
const newTable = moveTableCol(
|
|
38
|
+
table.node,
|
|
39
|
+
indexesOriginColumn,
|
|
40
|
+
indexesTargetColumn,
|
|
41
|
+
0
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
tr.replaceWith(table.pos, table.pos + table.node.nodeSize, newTable)
|
|
45
|
+
|
|
46
|
+
if (!select) return true
|
|
47
|
+
|
|
48
|
+
const map = TableMap.get(newTable)
|
|
49
|
+
const start = table.start
|
|
50
|
+
const index = target
|
|
51
|
+
const lastCell = map.positionAt(map.height - 1, index, newTable)
|
|
52
|
+
const $lastCell = tr.doc.resolve(start + lastCell)
|
|
53
|
+
|
|
54
|
+
const firstCell = map.positionAt(0, index, newTable)
|
|
55
|
+
const $firstCell = tr.doc.resolve(start + firstCell)
|
|
56
|
+
|
|
57
|
+
tr.setSelection(CellSelection.colSelection($lastCell, $firstCell))
|
|
58
|
+
return true
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function moveTableCol(
|
|
62
|
+
table: Node,
|
|
63
|
+
indexesOrigin: number[],
|
|
64
|
+
indexesTarget: number[],
|
|
65
|
+
direction: -1 | 1 | 0
|
|
66
|
+
) {
|
|
67
|
+
let rows = transpose(convertTableToRows(table))
|
|
68
|
+
|
|
69
|
+
rows = moveRowInArrayOfRows(rows, indexesOrigin, indexesTarget, direction)
|
|
70
|
+
rows = transpose(rows)
|
|
71
|
+
|
|
72
|
+
return convertRowsToTable(table, rows)
|
|
73
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Node } from '@milkdown/prose/model'
|
|
2
|
+
|
|
3
|
+
/// @internal
|
|
4
|
+
export function moveRowInArrayOfRows(
|
|
5
|
+
rows: (Node | null)[][],
|
|
6
|
+
indexesOrigin: number[],
|
|
7
|
+
indexesTarget: number[],
|
|
8
|
+
directionOverride: -1 | 1 | 0
|
|
9
|
+
) {
|
|
10
|
+
const direction = indexesOrigin[0]! > indexesTarget[0]! ? -1 : 1
|
|
11
|
+
|
|
12
|
+
const rowsExtracted = rows.splice(indexesOrigin[0]!, indexesOrigin.length)
|
|
13
|
+
const positionOffset = rowsExtracted.length % 2 === 0 ? 1 : 0
|
|
14
|
+
let target: number
|
|
15
|
+
|
|
16
|
+
if (directionOverride === -1 && direction === 1) {
|
|
17
|
+
target = indexesTarget[0]! - 1
|
|
18
|
+
} else if (directionOverride === 1 && direction === -1) {
|
|
19
|
+
target = indexesTarget[indexesTarget.length - 1]! - positionOffset + 1
|
|
20
|
+
} else {
|
|
21
|
+
target =
|
|
22
|
+
direction === -1
|
|
23
|
+
? indexesTarget[0]!
|
|
24
|
+
: indexesTarget[indexesTarget.length - 1]! - positionOffset
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
rows.splice(target, 0, ...rowsExtracted)
|
|
28
|
+
return rows
|
|
29
|
+
}
|