@milkdown/preset-commonmark 7.12.1 → 7.13.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.
@@ -0,0 +1,140 @@
1
+ import { findNodeInSelection } from '@milkdown/prose'
2
+ import {
3
+ Node,
4
+ type Attrs,
5
+ type MarkType,
6
+ type NodeType,
7
+ } from '@milkdown/prose/model'
8
+ import { TextSelection } from '@milkdown/prose/state'
9
+ import { findWrapping } from '@milkdown/prose/transform'
10
+ import { $command } from '@milkdown/utils'
11
+
12
+ /// A command to check if a mark is selected.
13
+ export const isMarkSelectedCommand = $command(
14
+ 'IsMarkSelected',
15
+ () => (markType?: MarkType) => (state) => {
16
+ if (!markType) return false
17
+ const { doc, selection } = state
18
+ const hasLink = doc.rangeHasMark(selection.from, selection.to, markType)
19
+ return hasLink
20
+ }
21
+ )
22
+
23
+ /// A command to check if a node is selected.
24
+ export const isNodeSelectedCommand = $command(
25
+ 'IsNoteSelected',
26
+ () => (nodeType?: NodeType) => (state) => {
27
+ if (!nodeType) return false
28
+ const result = findNodeInSelection(state, nodeType)
29
+ return result.hasNode
30
+ }
31
+ )
32
+
33
+ /// A command to clear text in the current block.
34
+ export const clearTextInCurrentBlockCommand = $command(
35
+ 'ClearTextInCurrentBlock',
36
+ () => () => (state, dispatch) => {
37
+ let tr = state.tr
38
+ const { $from, $to } = tr.selection
39
+ const { pos: from } = $from
40
+ const { pos: right } = $to
41
+ const left = from - $from.node().content.size
42
+ if (left < 0) return false
43
+
44
+ tr = tr.deleteRange(left, right)
45
+ dispatch?.(tr)
46
+ return true
47
+ }
48
+ )
49
+
50
+ /// Set block type to target block and attribute.
51
+ export const setBlockTypeCommand = $command(
52
+ 'SetBlockType',
53
+ () =>
54
+ (payload?: { nodeType: NodeType; attrs?: Attrs | null }) =>
55
+ (state, dispatch) => {
56
+ const { nodeType, attrs = null } = payload ?? {}
57
+ if (!nodeType) return false
58
+ const tr = state.tr
59
+ const { from, to } = tr.selection
60
+ try {
61
+ tr.setBlockType(from, to, nodeType, attrs)
62
+ } catch {
63
+ return false
64
+ }
65
+ dispatch?.(tr)
66
+ return true
67
+ }
68
+ )
69
+
70
+ /// A command to wrap the current block with a block type.
71
+ export const wrapInBlockTypeCommand = $command(
72
+ 'WrapInBlockType',
73
+ () =>
74
+ (payload?: { nodeType: NodeType; attrs?: Attrs | null }) =>
75
+ (state, dispatch) => {
76
+ const { nodeType, attrs = null } = payload ?? {}
77
+ if (!nodeType) return false
78
+
79
+ let tr = state.tr
80
+
81
+ try {
82
+ const { $from, $to } = tr.selection
83
+ const blockRange = $from.blockRange($to)
84
+ const wrapping = blockRange && findWrapping(blockRange, nodeType, attrs)
85
+ if (!wrapping) return false
86
+ tr = tr.wrap(blockRange, wrapping)
87
+ } catch {
88
+ return false
89
+ }
90
+
91
+ dispatch?.(tr)
92
+ return true
93
+ }
94
+ )
95
+
96
+ /// A command to add a block type to the current selection.
97
+ export const addBlockTypeCommand = $command(
98
+ 'AddBlockType',
99
+ () =>
100
+ (payload?: { nodeType: NodeType | Node; attrs?: Attrs | null }) =>
101
+ (state, dispatch) => {
102
+ const { nodeType, attrs = null } = payload ?? {}
103
+ if (!nodeType) return false
104
+ const tr = state.tr
105
+
106
+ try {
107
+ const node =
108
+ nodeType instanceof Node ? nodeType : nodeType.createAndFill(attrs)
109
+ if (!node) return false
110
+
111
+ tr.replaceSelectionWith(node)
112
+ } catch {
113
+ return false
114
+ }
115
+ dispatch?.(tr)
116
+ return true
117
+ }
118
+ )
119
+
120
+ /// A command to select text near a position.
121
+ export const selectTextNearPosCommand = $command(
122
+ 'SelectTextNearPos',
123
+ () => (payload?: { pos?: number }) => (state, dispatch) => {
124
+ const { pos } = payload ?? {}
125
+ if (pos == null) return false
126
+
127
+ const clamp = (value: number, min: number, max: number) =>
128
+ Math.min(Math.max(value, min), max)
129
+
130
+ const tr = state.tr
131
+ try {
132
+ const $pos = state.doc.resolve(clamp(pos, 0, state.doc.content.size))
133
+ tr.setSelection(TextSelection.near($pos))
134
+ } catch {
135
+ return false
136
+ }
137
+ dispatch?.(tr.scrollIntoView())
138
+ return true
139
+ }
140
+ )
@@ -1,5 +1,14 @@
1
1
  import type { MilkdownPlugin } from '@milkdown/ctx'
2
2
 
3
+ import {
4
+ addBlockTypeCommand,
5
+ clearTextInCurrentBlockCommand,
6
+ isMarkSelectedCommand,
7
+ isNodeSelectedCommand,
8
+ selectTextNearPosCommand,
9
+ setBlockTypeCommand,
10
+ wrapInBlockTypeCommand,
11
+ } from '../commands'
3
12
  import {
4
13
  toggleEmphasisCommand,
5
14
  toggleInlineCodeCommand,
@@ -51,4 +60,13 @@ export const commands: MilkdownPlugin[] = [
51
60
 
52
61
  toggleLinkCommand,
53
62
  updateLinkCommand,
63
+
64
+ isMarkSelectedCommand,
65
+ isNodeSelectedCommand,
66
+
67
+ clearTextInCurrentBlockCommand,
68
+ setBlockTypeCommand,
69
+ wrapInBlockTypeCommand,
70
+ addBlockTypeCommand,
71
+ selectTextNearPosCommand,
54
72
  ]
package/src/index.ts CHANGED
@@ -13,6 +13,7 @@ export * from './node'
13
13
  export * from './mark'
14
14
  export * from './plugin'
15
15
  export * from './composed'
16
+ export * from './commands'
16
17
 
17
18
  /// The commonmark preset, includes all the plugins.
18
19
  export const commonmark: MilkdownPlugin[] = [