@jvs-milkdown/preset-commonmark 1.0.0

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 (141) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -0
  3. package/lib/__internal__/index.d.ts +3 -0
  4. package/lib/__internal__/index.d.ts.map +1 -0
  5. package/lib/__internal__/serialize-text.d.ts +4 -0
  6. package/lib/__internal__/serialize-text.d.ts.map +1 -0
  7. package/lib/__internal__/with-meta.d.ts +3 -0
  8. package/lib/__internal__/with-meta.d.ts.map +1 -0
  9. package/lib/__test__/html.spec.d.ts +2 -0
  10. package/lib/__test__/html.spec.d.ts.map +1 -0
  11. package/lib/__test__/trailing-space.spec.d.ts +2 -0
  12. package/lib/__test__/trailing-space.spec.d.ts.map +1 -0
  13. package/lib/__test__/vitest.setup.d.ts +1 -0
  14. package/lib/__test__/vitest.setup.d.ts.map +1 -0
  15. package/lib/commands/index.d.ts +20 -0
  16. package/lib/commands/index.d.ts.map +1 -0
  17. package/lib/composed/commands.d.ts +3 -0
  18. package/lib/composed/commands.d.ts.map +1 -0
  19. package/lib/composed/index.d.ts +6 -0
  20. package/lib/composed/index.d.ts.map +1 -0
  21. package/lib/composed/inputrules.d.ts +4 -0
  22. package/lib/composed/inputrules.d.ts.map +1 -0
  23. package/lib/composed/keymap.d.ts +3 -0
  24. package/lib/composed/keymap.d.ts.map +1 -0
  25. package/lib/composed/plugins.d.ts +3 -0
  26. package/lib/composed/plugins.d.ts.map +1 -0
  27. package/lib/composed/schema.d.ts +3 -0
  28. package/lib/composed/schema.d.ts.map +1 -0
  29. package/lib/index.d.ts +8 -0
  30. package/lib/index.d.ts.map +1 -0
  31. package/lib/index.js +2153 -0
  32. package/lib/index.js.map +1 -0
  33. package/lib/mark/emphasis.d.ts +7 -0
  34. package/lib/mark/emphasis.d.ts.map +1 -0
  35. package/lib/mark/index.d.ts +5 -0
  36. package/lib/mark/index.d.ts.map +1 -0
  37. package/lib/mark/inline-code.d.ts +6 -0
  38. package/lib/mark/inline-code.d.ts.map +1 -0
  39. package/lib/mark/link.d.ts +9 -0
  40. package/lib/mark/link.d.ts.map +1 -0
  41. package/lib/mark/strong.d.ts +6 -0
  42. package/lib/mark/strong.d.ts.map +1 -0
  43. package/lib/node/blockquote.d.ts +7 -0
  44. package/lib/node/blockquote.d.ts.map +1 -0
  45. package/lib/node/bullet-list.d.ts +6 -0
  46. package/lib/node/bullet-list.d.ts.map +1 -0
  47. package/lib/node/code-block.d.ts +10 -0
  48. package/lib/node/code-block.d.ts.map +1 -0
  49. package/lib/node/doc.d.ts +2 -0
  50. package/lib/node/doc.d.ts.map +1 -0
  51. package/lib/node/hardbreak.d.ts +5 -0
  52. package/lib/node/hardbreak.d.ts.map +1 -0
  53. package/lib/node/heading.d.ts +11 -0
  54. package/lib/node/heading.d.ts.map +1 -0
  55. package/lib/node/hr.d.ts +5 -0
  56. package/lib/node/hr.d.ts.map +1 -0
  57. package/lib/node/html.d.ts +3 -0
  58. package/lib/node/html.d.ts.map +1 -0
  59. package/lib/node/image.d.ts +11 -0
  60. package/lib/node/image.d.ts.map +1 -0
  61. package/lib/node/index.d.ts +14 -0
  62. package/lib/node/index.d.ts.map +1 -0
  63. package/lib/node/list-item.d.ts +8 -0
  64. package/lib/node/list-item.d.ts.map +1 -0
  65. package/lib/node/ordered-list.d.ts +6 -0
  66. package/lib/node/ordered-list.d.ts.map +1 -0
  67. package/lib/node/paragraph.d.ts +5 -0
  68. package/lib/node/paragraph.d.ts.map +1 -0
  69. package/lib/node/text.d.ts +2 -0
  70. package/lib/node/text.d.ts.map +1 -0
  71. package/lib/plugin/hardbreak-clear-mark-plugin.d.ts +2 -0
  72. package/lib/plugin/hardbreak-clear-mark-plugin.d.ts.map +1 -0
  73. package/lib/plugin/hardbreak-filter-plugin.d.ts +3 -0
  74. package/lib/plugin/hardbreak-filter-plugin.d.ts.map +1 -0
  75. package/lib/plugin/index.d.ts +12 -0
  76. package/lib/plugin/index.d.ts.map +1 -0
  77. package/lib/plugin/inline-nodes-cursor-plugin.d.ts +2 -0
  78. package/lib/plugin/inline-nodes-cursor-plugin.d.ts.map +1 -0
  79. package/lib/plugin/remark-add-order-in-list-plugin.d.ts +2 -0
  80. package/lib/plugin/remark-add-order-in-list-plugin.d.ts.map +1 -0
  81. package/lib/plugin/remark-html-transformer.d.ts +2 -0
  82. package/lib/plugin/remark-html-transformer.d.ts.map +1 -0
  83. package/lib/plugin/remark-inline-link-plugin.d.ts +2 -0
  84. package/lib/plugin/remark-inline-link-plugin.d.ts.map +1 -0
  85. package/lib/plugin/remark-line-break.d.ts +2 -0
  86. package/lib/plugin/remark-line-break.d.ts.map +1 -0
  87. package/lib/plugin/remark-marker-plugin.d.ts +2 -0
  88. package/lib/plugin/remark-marker-plugin.d.ts.map +1 -0
  89. package/lib/plugin/remark-preserve-empty-line.d.ts +2 -0
  90. package/lib/plugin/remark-preserve-empty-line.d.ts.map +1 -0
  91. package/lib/plugin/sync-heading-id-plugin.d.ts +2 -0
  92. package/lib/plugin/sync-heading-id-plugin.d.ts.map +1 -0
  93. package/lib/plugin/sync-list-order-plugin.d.ts +2 -0
  94. package/lib/plugin/sync-list-order-plugin.d.ts.map +1 -0
  95. package/lib/tsconfig.tsbuildinfo +1 -0
  96. package/package.json +44 -0
  97. package/src/__internal__/index.ts +2 -0
  98. package/src/__internal__/serialize-text.ts +21 -0
  99. package/src/__internal__/with-meta.ts +15 -0
  100. package/src/__test__/html.spec.ts +46 -0
  101. package/src/__test__/trailing-space.spec.ts +27 -0
  102. package/src/__test__/vitest.setup.ts +65 -0
  103. package/src/commands/index.ts +140 -0
  104. package/src/composed/commands.ts +72 -0
  105. package/src/composed/index.ts +5 -0
  106. package/src/composed/inputrules.ts +34 -0
  107. package/src/composed/keymap.ts +29 -0
  108. package/src/composed/plugins.ts +35 -0
  109. package/src/composed/schema.ts +92 -0
  110. package/src/index.ts +26 -0
  111. package/src/mark/emphasis.ts +130 -0
  112. package/src/mark/index.ts +4 -0
  113. package/src/mark/inline-code.ts +123 -0
  114. package/src/mark/link.ts +134 -0
  115. package/src/mark/strong.ts +130 -0
  116. package/src/node/blockquote.ts +100 -0
  117. package/src/node/bullet-list.ts +129 -0
  118. package/src/node/code-block.ts +176 -0
  119. package/src/node/doc.ts +26 -0
  120. package/src/node/hardbreak.ts +134 -0
  121. package/src/node/heading.ts +271 -0
  122. package/src/node/hr.ts +87 -0
  123. package/src/node/html.ts +66 -0
  124. package/src/node/image.ts +173 -0
  125. package/src/node/index.ts +14 -0
  126. package/src/node/list-item.ts +244 -0
  127. package/src/node/ordered-list.ts +141 -0
  128. package/src/node/paragraph.ts +136 -0
  129. package/src/node/text.ts +25 -0
  130. package/src/plugin/hardbreak-clear-mark-plugin.ts +58 -0
  131. package/src/plugin/hardbreak-filter-plugin.ts +46 -0
  132. package/src/plugin/index.ts +14 -0
  133. package/src/plugin/inline-nodes-cursor-plugin.ts +103 -0
  134. package/src/plugin/remark-add-order-in-list-plugin.ts +29 -0
  135. package/src/plugin/remark-html-transformer.ts +74 -0
  136. package/src/plugin/remark-inline-link-plugin.ts +20 -0
  137. package/src/plugin/remark-line-break.ts +69 -0
  138. package/src/plugin/remark-marker-plugin.ts +33 -0
  139. package/src/plugin/remark-preserve-empty-line.ts +49 -0
  140. package/src/plugin/sync-heading-id-plugin.ts +67 -0
  141. package/src/plugin/sync-list-order-plugin.ts +112 -0
@@ -0,0 +1,140 @@
1
+ import { findNodeInSelection } from '@jvs-milkdown/prose'
2
+ import {
3
+ Node,
4
+ type Attrs,
5
+ type MarkType,
6
+ type NodeType,
7
+ } from '@jvs-milkdown/prose/model'
8
+ import { TextSelection } from '@jvs-milkdown/prose/state'
9
+ import { findWrapping } from '@jvs-milkdown/prose/transform'
10
+ import { $command } from '@jvs-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
+ )
@@ -0,0 +1,72 @@
1
+ import type { MilkdownPlugin } from '@jvs-milkdown/ctx'
2
+
3
+ import {
4
+ addBlockTypeCommand,
5
+ clearTextInCurrentBlockCommand,
6
+ isMarkSelectedCommand,
7
+ isNodeSelectedCommand,
8
+ selectTextNearPosCommand,
9
+ setBlockTypeCommand,
10
+ wrapInBlockTypeCommand,
11
+ } from '../commands'
12
+ import {
13
+ toggleEmphasisCommand,
14
+ toggleInlineCodeCommand,
15
+ toggleLinkCommand,
16
+ toggleStrongCommand,
17
+ updateLinkCommand,
18
+ } from '../mark'
19
+ import {
20
+ createCodeBlockCommand,
21
+ downgradeHeadingCommand,
22
+ insertHardbreakCommand,
23
+ insertHrCommand,
24
+ insertImageCommand,
25
+ liftFirstListItemCommand,
26
+ liftListItemCommand,
27
+ sinkListItemCommand,
28
+ splitListItemCommand,
29
+ turnIntoTextCommand,
30
+ updateImageCommand,
31
+ wrapInBlockquoteCommand,
32
+ wrapInBulletListCommand,
33
+ wrapInHeadingCommand,
34
+ wrapInOrderedListCommand,
35
+ } from '../node'
36
+
37
+ /// @internal
38
+ export const commands: MilkdownPlugin[] = [
39
+ turnIntoTextCommand,
40
+ wrapInBlockquoteCommand,
41
+ wrapInHeadingCommand,
42
+ downgradeHeadingCommand,
43
+ createCodeBlockCommand,
44
+ insertHardbreakCommand,
45
+ insertHrCommand,
46
+
47
+ insertImageCommand,
48
+ updateImageCommand,
49
+
50
+ wrapInOrderedListCommand,
51
+ wrapInBulletListCommand,
52
+ sinkListItemCommand,
53
+ splitListItemCommand,
54
+ liftListItemCommand,
55
+ liftFirstListItemCommand,
56
+
57
+ toggleEmphasisCommand,
58
+ toggleInlineCodeCommand,
59
+ toggleStrongCommand,
60
+
61
+ toggleLinkCommand,
62
+ updateLinkCommand,
63
+
64
+ isMarkSelectedCommand,
65
+ isNodeSelectedCommand,
66
+
67
+ clearTextInCurrentBlockCommand,
68
+ setBlockTypeCommand,
69
+ wrapInBlockTypeCommand,
70
+ addBlockTypeCommand,
71
+ selectTextNearPosCommand,
72
+ ]
@@ -0,0 +1,5 @@
1
+ export * from './schema'
2
+ export * from './inputrules'
3
+ export * from './commands'
4
+ export * from './keymap'
5
+ export * from './plugins'
@@ -0,0 +1,34 @@
1
+ import type { MilkdownPlugin } from '@jvs-milkdown/ctx'
2
+
3
+ import {
4
+ emphasisStarInputRule,
5
+ emphasisUnderscoreInputRule,
6
+ inlineCodeInputRule,
7
+ strongInputRule,
8
+ } from '../mark'
9
+ import {
10
+ createCodeBlockInputRule,
11
+ insertHrInputRule,
12
+ wrapInBlockquoteInputRule,
13
+ wrapInBulletListInputRule,
14
+ wrapInHeadingInputRule,
15
+ wrapInOrderedListInputRule,
16
+ } from '../node'
17
+
18
+ /// @internal
19
+ export const inputRules: MilkdownPlugin[] = [
20
+ wrapInBlockquoteInputRule,
21
+ wrapInBulletListInputRule,
22
+ wrapInOrderedListInputRule,
23
+ createCodeBlockInputRule,
24
+ insertHrInputRule,
25
+ wrapInHeadingInputRule,
26
+ ].flat()
27
+
28
+ /// @internal
29
+ export const markInputRules: MilkdownPlugin[] = [
30
+ emphasisStarInputRule,
31
+ emphasisUnderscoreInputRule,
32
+ inlineCodeInputRule,
33
+ strongInputRule,
34
+ ]
@@ -0,0 +1,29 @@
1
+ import type { MilkdownPlugin } from '@jvs-milkdown/ctx'
2
+
3
+ import { emphasisKeymap, inlineCodeKeymap, strongKeymap } from '../mark'
4
+ import {
5
+ blockquoteKeymap,
6
+ bulletListKeymap,
7
+ codeBlockKeymap,
8
+ hardbreakKeymap,
9
+ headingKeymap,
10
+ listItemKeymap,
11
+ orderedListKeymap,
12
+ paragraphKeymap,
13
+ } from '../node'
14
+
15
+ /// @internal
16
+ export const keymap: MilkdownPlugin[] = [
17
+ blockquoteKeymap,
18
+ codeBlockKeymap,
19
+ hardbreakKeymap,
20
+ headingKeymap,
21
+ listItemKeymap,
22
+ orderedListKeymap,
23
+ bulletListKeymap,
24
+ paragraphKeymap,
25
+
26
+ emphasisKeymap,
27
+ inlineCodeKeymap,
28
+ strongKeymap,
29
+ ].flat()
@@ -0,0 +1,35 @@
1
+ import type { MilkdownPlugin } from '@jvs-milkdown/ctx'
2
+
3
+ import {
4
+ hardbreakClearMarkPlugin,
5
+ hardbreakFilterNodes,
6
+ hardbreakFilterPlugin,
7
+ inlineNodesCursorPlugin,
8
+ remarkAddOrderInListPlugin,
9
+ remarkHtmlTransformer,
10
+ remarkInlineLinkPlugin,
11
+ remarkLineBreak,
12
+ remarkMarker,
13
+ remarkPreserveEmptyLinePlugin,
14
+ syncHeadingIdPlugin,
15
+ syncListOrderPlugin,
16
+ } from '../plugin'
17
+
18
+ /// @internal
19
+ export const plugins: MilkdownPlugin[] = [
20
+ hardbreakClearMarkPlugin,
21
+ hardbreakFilterNodes,
22
+ hardbreakFilterPlugin,
23
+
24
+ inlineNodesCursorPlugin,
25
+
26
+ remarkAddOrderInListPlugin,
27
+ remarkInlineLinkPlugin,
28
+ remarkLineBreak,
29
+ remarkHtmlTransformer,
30
+ remarkMarker,
31
+ remarkPreserveEmptyLinePlugin,
32
+
33
+ syncHeadingIdPlugin,
34
+ syncListOrderPlugin,
35
+ ].flat()
@@ -0,0 +1,92 @@
1
+ import type { MilkdownPlugin } from '@jvs-milkdown/ctx'
2
+
3
+ import {
4
+ emphasisAttr,
5
+ emphasisSchema,
6
+ inlineCodeAttr,
7
+ inlineCodeSchema,
8
+ linkAttr,
9
+ linkSchema,
10
+ strongAttr,
11
+ strongSchema,
12
+ } from '../mark'
13
+ import {
14
+ blockquoteAttr,
15
+ blockquoteSchema,
16
+ bulletListAttr,
17
+ bulletListSchema,
18
+ codeBlockAttr,
19
+ codeBlockSchema,
20
+ docSchema,
21
+ hardbreakAttr,
22
+ hardbreakSchema,
23
+ headingAttr,
24
+ headingIdGenerator,
25
+ headingSchema,
26
+ hrAttr,
27
+ hrSchema,
28
+ htmlAttr,
29
+ htmlSchema,
30
+ imageAttr,
31
+ imageSchema,
32
+ listItemAttr,
33
+ listItemSchema,
34
+ orderedListAttr,
35
+ orderedListSchema,
36
+ paragraphAttr,
37
+ paragraphSchema,
38
+ textSchema,
39
+ } from '../node'
40
+
41
+ /// @internal
42
+ export const schema: MilkdownPlugin[] = [
43
+ docSchema,
44
+
45
+ paragraphAttr,
46
+ paragraphSchema,
47
+
48
+ headingIdGenerator,
49
+ headingAttr,
50
+ headingSchema,
51
+
52
+ hardbreakAttr,
53
+ hardbreakSchema,
54
+
55
+ blockquoteAttr,
56
+ blockquoteSchema,
57
+
58
+ codeBlockAttr,
59
+ codeBlockSchema,
60
+
61
+ hrAttr,
62
+ hrSchema,
63
+
64
+ imageAttr,
65
+ imageSchema,
66
+
67
+ bulletListAttr,
68
+ bulletListSchema,
69
+
70
+ orderedListAttr,
71
+ orderedListSchema,
72
+
73
+ listItemAttr,
74
+ listItemSchema,
75
+
76
+ emphasisAttr,
77
+ emphasisSchema,
78
+
79
+ strongAttr,
80
+ strongSchema,
81
+
82
+ inlineCodeAttr,
83
+ inlineCodeSchema,
84
+
85
+ linkAttr,
86
+ linkSchema,
87
+
88
+ htmlAttr,
89
+ htmlSchema,
90
+
91
+ textSchema,
92
+ ].flat()
package/src/index.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { MilkdownPlugin } from '@jvs-milkdown/ctx'
2
+
3
+ import {
4
+ commands,
5
+ inputRules,
6
+ keymap,
7
+ markInputRules,
8
+ plugins,
9
+ schema,
10
+ } from './composed'
11
+
12
+ export * from './node'
13
+ export * from './mark'
14
+ export * from './plugin'
15
+ export * from './composed'
16
+ export * from './commands'
17
+
18
+ /// The commonmark preset, includes all the plugins.
19
+ export const commonmark: MilkdownPlugin[] = [
20
+ schema,
21
+ inputRules,
22
+ markInputRules,
23
+ commands,
24
+ keymap,
25
+ plugins,
26
+ ].flat()
@@ -0,0 +1,130 @@
1
+ import { commandsCtx, remarkStringifyOptionsCtx } from '@jvs-milkdown/core'
2
+ import { markRule } from '@jvs-milkdown/prose'
3
+ import { toggleMark } from '@jvs-milkdown/prose/commands'
4
+ import {
5
+ $command,
6
+ $inputRule,
7
+ $markAttr,
8
+ $markSchema,
9
+ $useKeymap,
10
+ } from '@jvs-milkdown/utils'
11
+
12
+ import { withMeta } from '../__internal__'
13
+
14
+ /// HTML attributes for the emphasis mark.
15
+ export const emphasisAttr = $markAttr('emphasis')
16
+
17
+ withMeta(emphasisAttr, {
18
+ displayName: 'Attr<emphasis>',
19
+ group: 'Emphasis',
20
+ })
21
+
22
+ /// Emphasis mark schema.
23
+ export const emphasisSchema = $markSchema('emphasis', (ctx) => ({
24
+ attrs: {
25
+ marker: {
26
+ default: ctx.get(remarkStringifyOptionsCtx).emphasis || '*',
27
+ validate: 'string',
28
+ },
29
+ },
30
+ parseDOM: [
31
+ { tag: 'i' },
32
+ { tag: 'em' },
33
+ { style: 'font-style', getAttrs: (value) => (value === 'italic') as false },
34
+ ],
35
+ toDOM: (mark) => ['em', ctx.get(emphasisAttr.key)(mark)],
36
+ parseMarkdown: {
37
+ match: (node) => node.type === 'emphasis',
38
+ runner: (state, node, markType) => {
39
+ state.openMark(markType, { marker: node.marker })
40
+ state.next(node.children)
41
+ state.closeMark(markType)
42
+ },
43
+ },
44
+ toMarkdown: {
45
+ match: (mark) => mark.type.name === 'emphasis',
46
+ runner: (state, mark) => {
47
+ state.withMark(mark, 'emphasis', undefined, {
48
+ marker: mark.attrs.marker,
49
+ })
50
+ },
51
+ },
52
+ }))
53
+
54
+ withMeta(emphasisSchema.mark, {
55
+ displayName: 'MarkSchema<emphasis>',
56
+ group: 'Emphasis',
57
+ })
58
+
59
+ withMeta(emphasisSchema.ctx, {
60
+ displayName: 'MarkSchemaCtx<emphasis>',
61
+ group: 'Emphasis',
62
+ })
63
+
64
+ /// A command to toggle the emphasis mark.
65
+ export const toggleEmphasisCommand = $command('ToggleEmphasis', (ctx) => () => {
66
+ return toggleMark(emphasisSchema.type(ctx))
67
+ })
68
+
69
+ withMeta(toggleEmphasisCommand, {
70
+ displayName: 'Command<toggleEmphasisCommand>',
71
+ group: 'Emphasis',
72
+ })
73
+
74
+ /// Input rule for use `*` to create emphasis mark.
75
+ export const emphasisStarInputRule = $inputRule((ctx) => {
76
+ return markRule(/(?:^|[^*])\*([^*]+)\*$/, emphasisSchema.type(ctx), {
77
+ getAttr: () => ({
78
+ marker: '*',
79
+ }),
80
+ updateCaptured: ({ fullMatch, start }) =>
81
+ !fullMatch.startsWith('*')
82
+ ? { fullMatch: fullMatch.slice(1), start: start + 1 }
83
+ : {},
84
+ })
85
+ })
86
+
87
+ withMeta(emphasisStarInputRule, {
88
+ displayName: 'InputRule<emphasis>|Star',
89
+ group: 'Emphasis',
90
+ })
91
+
92
+ /// Input rule for use `_` to create emphasis mark.
93
+ export const emphasisUnderscoreInputRule = $inputRule((ctx) => {
94
+ return markRule(/\b_(?![_\s])(.*?[^_\s])_\b/, emphasisSchema.type(ctx), {
95
+ getAttr: () => ({
96
+ marker: '_',
97
+ }),
98
+ updateCaptured: ({ fullMatch, start }) =>
99
+ !fullMatch.startsWith('_')
100
+ ? { fullMatch: fullMatch.slice(1), start: start + 1 }
101
+ : {},
102
+ })
103
+ })
104
+
105
+ withMeta(emphasisUnderscoreInputRule, {
106
+ displayName: 'InputRule<emphasis>|Underscore',
107
+ group: 'Emphasis',
108
+ })
109
+
110
+ /// Keymap for the emphasis mark.
111
+ /// - `Mod-i` - Toggle the emphasis mark.
112
+ export const emphasisKeymap = $useKeymap('emphasisKeymap', {
113
+ ToggleEmphasis: {
114
+ shortcuts: 'Mod-i',
115
+ command: (ctx) => {
116
+ const commands = ctx.get(commandsCtx)
117
+ return () => commands.call(toggleEmphasisCommand.key)
118
+ },
119
+ },
120
+ })
121
+
122
+ withMeta(emphasisKeymap.ctx, {
123
+ displayName: 'KeymapCtx<emphasis>',
124
+ group: 'Emphasis',
125
+ })
126
+
127
+ withMeta(emphasisKeymap.shortcuts, {
128
+ displayName: 'Keymap<emphasis>',
129
+ group: 'Emphasis',
130
+ })
@@ -0,0 +1,4 @@
1
+ export * from './emphasis'
2
+ export * from './strong'
3
+ export * from './inline-code'
4
+ export * from './link'
@@ -0,0 +1,123 @@
1
+ import type { MarkType } from '@jvs-milkdown/prose/model'
2
+
3
+ import { commandsCtx } from '@jvs-milkdown/core'
4
+ import { markRule } from '@jvs-milkdown/prose'
5
+ import {
6
+ $command,
7
+ $inputRule,
8
+ $markAttr,
9
+ $markSchema,
10
+ $useKeymap,
11
+ } from '@jvs-milkdown/utils'
12
+
13
+ import { withMeta } from '../__internal__'
14
+
15
+ /// HTML attributes for the inlineCode mark.
16
+ export const inlineCodeAttr = $markAttr('inlineCode')
17
+
18
+ withMeta(inlineCodeAttr, {
19
+ displayName: 'Attr<inlineCode>',
20
+ group: 'InlineCode',
21
+ })
22
+
23
+ /// InlineCode mark schema.
24
+ export const inlineCodeSchema = $markSchema('inlineCode', (ctx) => ({
25
+ priority: 100,
26
+ code: true,
27
+ parseDOM: [{ tag: 'code' }],
28
+ toDOM: (mark) => ['code', ctx.get(inlineCodeAttr.key)(mark)],
29
+ parseMarkdown: {
30
+ match: (node) => node.type === 'inlineCode',
31
+ runner: (state, node, markType) => {
32
+ state.openMark(markType)
33
+ state.addText(node.value as string)
34
+ state.closeMark(markType)
35
+ },
36
+ },
37
+ toMarkdown: {
38
+ match: (mark) => mark.type.name === 'inlineCode',
39
+ runner: (state, mark, node) => {
40
+ state.withMark(mark, 'inlineCode', node.text || '')
41
+ return true
42
+ },
43
+ },
44
+ }))
45
+
46
+ withMeta(inlineCodeSchema.mark, {
47
+ displayName: 'MarkSchema<inlineCode>',
48
+ group: 'InlineCode',
49
+ })
50
+
51
+ withMeta(inlineCodeSchema.ctx, {
52
+ displayName: 'MarkSchemaCtx<inlineCode>',
53
+ group: 'InlineCode',
54
+ })
55
+
56
+ /// A command to toggle the inlineCode mark.
57
+ export const toggleInlineCodeCommand = $command(
58
+ 'ToggleInlineCode',
59
+ (ctx) => () => (state, dispatch) => {
60
+ const { selection, tr } = state
61
+ if (selection.empty) return false
62
+ const { from, to } = selection
63
+
64
+ const has = state.doc.rangeHasMark(from, to, inlineCodeSchema.type(ctx))
65
+ // remove exists inlineCode mark if have
66
+ if (has) {
67
+ dispatch?.(tr.removeMark(from, to, inlineCodeSchema.type(ctx)))
68
+ return true
69
+ }
70
+
71
+ const restMarksName = Object.keys(state.schema.marks).filter(
72
+ (x) => x !== inlineCodeSchema.type.name
73
+ )
74
+
75
+ // remove other marks
76
+ restMarksName
77
+ .map((name) => state.schema.marks[name] as MarkType)
78
+ .forEach((t) => {
79
+ tr.removeMark(from, to, t)
80
+ })
81
+
82
+ // add inlineCode mark
83
+ dispatch?.(tr.addMark(from, to, inlineCodeSchema.type(ctx).create()))
84
+ return true
85
+ }
86
+ )
87
+
88
+ withMeta(toggleInlineCodeCommand, {
89
+ displayName: 'Command<toggleInlineCodeCommand>',
90
+ group: 'InlineCode',
91
+ })
92
+
93
+ /// Input rule for create inlineCode mark.
94
+ export const inlineCodeInputRule = $inputRule((ctx) => {
95
+ return markRule(/(?:`)([^`]+)(?:`)$/, inlineCodeSchema.type(ctx))
96
+ })
97
+
98
+ withMeta(inlineCodeInputRule, {
99
+ displayName: 'InputRule<inlineCodeInputRule>',
100
+ group: 'InlineCode',
101
+ })
102
+
103
+ /// Keymap for the inlineCode mark.
104
+ /// - `Mod-e` - Toggle the inlineCode mark.
105
+ export const inlineCodeKeymap = $useKeymap('inlineCodeKeymap', {
106
+ ToggleInlineCode: {
107
+ shortcuts: 'Mod-e',
108
+ command: (ctx) => {
109
+ const commands = ctx.get(commandsCtx)
110
+ return () => commands.call(toggleInlineCodeCommand.key)
111
+ },
112
+ },
113
+ })
114
+
115
+ withMeta(inlineCodeKeymap.ctx, {
116
+ displayName: 'KeymapCtx<inlineCode>',
117
+ group: 'InlineCode',
118
+ })
119
+
120
+ withMeta(inlineCodeKeymap.shortcuts, {
121
+ displayName: 'Keymap<inlineCode>',
122
+ group: 'InlineCode',
123
+ })