@milkdown/preset-commonmark 7.5.0 → 7.5.8
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/__internal__/serialize-text.d.ts.map +1 -1
- package/lib/__internal__/with-meta.d.ts.map +1 -1
- package/lib/composed/commands.d.ts.map +1 -1
- package/lib/composed/inputrules.d.ts.map +1 -1
- package/lib/composed/keymap.d.ts.map +1 -1
- package/lib/composed/schema.d.ts.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.es.js +412 -269
- package/lib/index.es.js.map +1 -1
- package/lib/mark/emphasis.d.ts.map +1 -1
- package/lib/mark/inline-code.d.ts.map +1 -1
- package/lib/mark/link.d.ts.map +1 -1
- package/lib/mark/strong.d.ts.map +1 -1
- package/lib/node/blockquote.d.ts.map +1 -1
- package/lib/node/bullet-list.d.ts.map +1 -1
- package/lib/node/code-block.d.ts.map +1 -1
- package/lib/node/hardbreak.d.ts.map +1 -1
- package/lib/node/heading.d.ts.map +1 -1
- package/lib/node/hr.d.ts.map +1 -1
- package/lib/node/html.d.ts.map +1 -1
- package/lib/node/image.d.ts.map +1 -1
- package/lib/node/list-item.d.ts.map +1 -1
- package/lib/node/ordered-list.d.ts.map +1 -1
- package/lib/node/paragraph.d.ts.map +1 -1
- package/lib/plugin/hardbreak-clear-mark-plugin.d.ts.map +1 -1
- package/lib/plugin/hardbreak-filter-plugin.d.ts.map +1 -1
- package/lib/plugin/inline-nodes-cursor-plugin.d.ts.map +1 -1
- package/lib/plugin/remark-add-order-in-list-plugin.d.ts.map +1 -1
- package/lib/plugin/remark-html-transformer.d.ts.map +1 -1
- package/lib/plugin/remark-inline-link-plugin.d.ts.map +1 -1
- package/lib/plugin/remark-line-break.d.ts.map +1 -1
- package/lib/plugin/remark-marker-plugin.d.ts.map +1 -1
- package/lib/plugin/sync-heading-id-plugin.d.ts.map +1 -1
- package/lib/plugin/sync-list-order-plugin.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/__internal__/serialize-text.ts +3 -4
- package/src/__internal__/with-meta.ts +4 -1
- package/src/composed/commands.ts +7 -1
- package/src/composed/inputrules.ts +14 -2
- package/src/composed/keymap.ts +10 -1
- package/src/composed/schema.ts +10 -1
- package/src/index.ts +16 -2
- package/src/mark/emphasis.ts +19 -9
- package/src/mark/inline-code.ts +40 -30
- package/src/mark/link.ts +55 -45
- package/src/mark/strong.ts +13 -7
- package/src/node/blockquote.ts +34 -20
- package/src/node/bullet-list.ts +20 -7
- package/src/node/code-block.ts +43 -18
- package/src/node/doc.ts +1 -1
- package/src/node/hardbreak.ts +49 -28
- package/src/node/heading.ts +44 -27
- package/src/node/hr.ts +27 -28
- package/src/node/html.ts +10 -8
- package/src/node/image.ts +57 -43
- package/src/node/list-item.ts +35 -18
- package/src/node/ordered-list.ts +31 -15
- package/src/node/paragraph.ts +10 -10
- package/src/node/text.ts +1 -1
- package/src/plugin/hardbreak-clear-mark-plugin.ts +16 -9
- package/src/plugin/hardbreak-filter-plugin.ts +5 -3
- package/src/plugin/inline-nodes-cursor-plugin.ts +13 -6
- package/src/plugin/remark-add-order-in-list-plugin.ts +13 -10
- package/src/plugin/remark-html-transformer.ts +24 -17
- package/src/plugin/remark-inline-link-plugin.ts +4 -1
- package/src/plugin/remark-line-break.ts +39 -26
- package/src/plugin/remark-marker-plugin.ts +14 -7
- package/src/plugin/sync-heading-id-plugin.ts +12 -9
- package/src/plugin/sync-list-order-plugin.ts +12 -11
package/src/mark/strong.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { commandsCtx, remarkStringifyOptionsCtx } from '@milkdown/core'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
$command,
|
|
4
|
+
$inputRule,
|
|
5
|
+
$markAttr,
|
|
6
|
+
$markSchema,
|
|
7
|
+
$useKeymap,
|
|
8
|
+
} from '@milkdown/utils'
|
|
3
9
|
import { toggleMark } from '@milkdown/prose/commands'
|
|
4
10
|
import { markRule } from '@milkdown/prose'
|
|
5
11
|
import { withMeta } from '../__internal__'
|
|
@@ -13,7 +19,7 @@ withMeta(strongAttr, {
|
|
|
13
19
|
})
|
|
14
20
|
|
|
15
21
|
/// Strong mark schema.
|
|
16
|
-
export const strongSchema = $markSchema('strong', ctx => ({
|
|
22
|
+
export const strongSchema = $markSchema('strong', (ctx) => ({
|
|
17
23
|
attrs: {
|
|
18
24
|
marker: {
|
|
19
25
|
default: ctx.get(remarkStringifyOptionsCtx).strong || '*',
|
|
@@ -22,11 +28,11 @@ export const strongSchema = $markSchema('strong', ctx => ({
|
|
|
22
28
|
parseDOM: [
|
|
23
29
|
{ tag: 'b' },
|
|
24
30
|
{ tag: 'strong' },
|
|
25
|
-
{ style: 'font-style', getAttrs: value => (value === 'bold') as false },
|
|
31
|
+
{ style: 'font-style', getAttrs: (value) => (value === 'bold') as false },
|
|
26
32
|
],
|
|
27
|
-
toDOM: mark => ['strong', ctx.get(strongAttr.key)(mark)],
|
|
33
|
+
toDOM: (mark) => ['strong', ctx.get(strongAttr.key)(mark)],
|
|
28
34
|
parseMarkdown: {
|
|
29
|
-
match: node => node.type === 'strong',
|
|
35
|
+
match: (node) => node.type === 'strong',
|
|
30
36
|
runner: (state, node, markType) => {
|
|
31
37
|
state.openMark(markType, { marker: node.marker })
|
|
32
38
|
state.next(node.children)
|
|
@@ -34,7 +40,7 @@ export const strongSchema = $markSchema('strong', ctx => ({
|
|
|
34
40
|
},
|
|
35
41
|
},
|
|
36
42
|
toMarkdown: {
|
|
37
|
-
match: mark => mark.type.name === 'strong',
|
|
43
|
+
match: (mark) => mark.type.name === 'strong',
|
|
38
44
|
runner: (state, mark) => {
|
|
39
45
|
state.withMark(mark, 'strong', undefined, {
|
|
40
46
|
marker: mark.attrs.marker,
|
|
@@ -54,7 +60,7 @@ withMeta(strongSchema.ctx, {
|
|
|
54
60
|
})
|
|
55
61
|
|
|
56
62
|
/// A command to toggle the strong mark.
|
|
57
|
-
export const toggleStrongCommand = $command('ToggleStrong', ctx => () => {
|
|
63
|
+
export const toggleStrongCommand = $command('ToggleStrong', (ctx) => () => {
|
|
58
64
|
return toggleMark(strongSchema.type(ctx))
|
|
59
65
|
})
|
|
60
66
|
|
package/src/node/blockquote.ts
CHANGED
|
@@ -2,7 +2,13 @@ import { commandsCtx } from '@milkdown/core'
|
|
|
2
2
|
import { wrapIn } from '@milkdown/prose/commands'
|
|
3
3
|
import { wrappingInputRule } from '@milkdown/prose/inputrules'
|
|
4
4
|
import type { $NodeSchema } from '@milkdown/utils'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
$command,
|
|
7
|
+
$inputRule,
|
|
8
|
+
$nodeAttr,
|
|
9
|
+
$nodeSchema,
|
|
10
|
+
$useKeymap,
|
|
11
|
+
} from '@milkdown/utils'
|
|
6
12
|
import { withMeta } from '../__internal__'
|
|
7
13
|
|
|
8
14
|
/// HTML attributes for blockquote node.
|
|
@@ -14,25 +20,28 @@ withMeta(blockquoteAttr, {
|
|
|
14
20
|
})
|
|
15
21
|
|
|
16
22
|
/// Schema for blockquote node.
|
|
17
|
-
export const blockquoteSchema: $NodeSchema<'blockquote'> = $nodeSchema(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
export const blockquoteSchema: $NodeSchema<'blockquote'> = $nodeSchema(
|
|
24
|
+
'blockquote',
|
|
25
|
+
(ctx) => ({
|
|
26
|
+
content: 'block+',
|
|
27
|
+
group: 'block',
|
|
28
|
+
defining: true,
|
|
29
|
+
parseDOM: [{ tag: 'blockquote' }],
|
|
30
|
+
toDOM: (node) => ['blockquote', ctx.get(blockquoteAttr.key)(node), 0],
|
|
31
|
+
parseMarkdown: {
|
|
32
|
+
match: ({ type }) => type === 'blockquote',
|
|
33
|
+
runner: (state, node, type) => {
|
|
34
|
+
state.openNode(type).next(node.children).closeNode()
|
|
35
|
+
},
|
|
27
36
|
},
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
toMarkdown: {
|
|
38
|
+
match: (node) => node.type.name === 'blockquote',
|
|
39
|
+
runner: (state, node) => {
|
|
40
|
+
state.openNode('blockquote').next(node.content).closeNode()
|
|
41
|
+
},
|
|
33
42
|
},
|
|
34
|
-
}
|
|
35
|
-
|
|
43
|
+
})
|
|
44
|
+
)
|
|
36
45
|
|
|
37
46
|
withMeta(blockquoteSchema.node, {
|
|
38
47
|
displayName: 'NodeSchema<blockquote>',
|
|
@@ -46,7 +55,9 @@ withMeta(blockquoteSchema.ctx, {
|
|
|
46
55
|
|
|
47
56
|
/// This input rule will convert a line that starts with `> ` into a blockquote.
|
|
48
57
|
/// You can type `> ` at the start of a line to create a blockquote.
|
|
49
|
-
export const wrapInBlockquoteInputRule = $inputRule(ctx =>
|
|
58
|
+
export const wrapInBlockquoteInputRule = $inputRule((ctx) =>
|
|
59
|
+
wrappingInputRule(/^\s*>\s$/, blockquoteSchema.type(ctx))
|
|
60
|
+
)
|
|
50
61
|
|
|
51
62
|
withMeta(wrapInBlockquoteInputRule, {
|
|
52
63
|
displayName: 'InputRule<wrapInBlockquoteInputRule>',
|
|
@@ -54,7 +65,10 @@ withMeta(wrapInBlockquoteInputRule, {
|
|
|
54
65
|
})
|
|
55
66
|
|
|
56
67
|
/// This command will wrap the current selection in a blockquote.
|
|
57
|
-
export const wrapInBlockquoteCommand = $command(
|
|
68
|
+
export const wrapInBlockquoteCommand = $command(
|
|
69
|
+
'WrapInBlockquote',
|
|
70
|
+
(ctx) => () => wrapIn(blockquoteSchema.type(ctx))
|
|
71
|
+
)
|
|
58
72
|
|
|
59
73
|
withMeta(wrapInBlockquoteCommand, {
|
|
60
74
|
displayName: 'Command<wrapInBlockquoteCommand>',
|
package/src/node/bullet-list.ts
CHANGED
|
@@ -2,7 +2,13 @@ import { commandsCtx } from '@milkdown/core'
|
|
|
2
2
|
import { expectDomTypeError } from '@milkdown/exception'
|
|
3
3
|
import { wrapIn } from '@milkdown/prose/commands'
|
|
4
4
|
import { wrappingInputRule } from '@milkdown/prose/inputrules'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
$command,
|
|
7
|
+
$inputRule,
|
|
8
|
+
$nodeAttr,
|
|
9
|
+
$nodeSchema,
|
|
10
|
+
$useKeymap,
|
|
11
|
+
} from '@milkdown/utils'
|
|
6
12
|
import { withMeta } from '../__internal__'
|
|
7
13
|
|
|
8
14
|
/// HTML attributes for bullet list node.
|
|
@@ -27,8 +33,7 @@ export const bulletListSchema = $nodeSchema('bullet_list', (ctx) => {
|
|
|
27
33
|
{
|
|
28
34
|
tag: 'ul',
|
|
29
35
|
getAttrs: (dom) => {
|
|
30
|
-
if (!(dom instanceof HTMLElement))
|
|
31
|
-
throw expectDomTypeError(dom)
|
|
36
|
+
if (!(dom instanceof HTMLElement)) throw expectDomTypeError(dom)
|
|
32
37
|
|
|
33
38
|
return {
|
|
34
39
|
spread: dom.dataset.spread,
|
|
@@ -54,10 +59,13 @@ export const bulletListSchema = $nodeSchema('bullet_list', (ctx) => {
|
|
|
54
59
|
},
|
|
55
60
|
},
|
|
56
61
|
toMarkdown: {
|
|
57
|
-
match: node => node.type.name === 'bullet_list',
|
|
62
|
+
match: (node) => node.type.name === 'bullet_list',
|
|
58
63
|
runner: (state, node) => {
|
|
59
64
|
state
|
|
60
|
-
.openNode('list', undefined, {
|
|
65
|
+
.openNode('list', undefined, {
|
|
66
|
+
ordered: false,
|
|
67
|
+
spread: node.attrs.spread === 'true',
|
|
68
|
+
})
|
|
61
69
|
.next(node.content)
|
|
62
70
|
.closeNode()
|
|
63
71
|
},
|
|
@@ -76,7 +84,9 @@ withMeta(bulletListSchema.ctx, {
|
|
|
76
84
|
})
|
|
77
85
|
|
|
78
86
|
/// Input rule for wrapping a block in bullet list node.
|
|
79
|
-
export const wrapInBulletListInputRule = $inputRule(ctx =>
|
|
87
|
+
export const wrapInBulletListInputRule = $inputRule((ctx) =>
|
|
88
|
+
wrappingInputRule(/^\s*([-+*])\s$/, bulletListSchema.type(ctx))
|
|
89
|
+
)
|
|
80
90
|
|
|
81
91
|
withMeta(wrapInBulletListInputRule, {
|
|
82
92
|
displayName: 'InputRule<wrapInBulletListInputRule>',
|
|
@@ -84,7 +94,10 @@ withMeta(wrapInBulletListInputRule, {
|
|
|
84
94
|
})
|
|
85
95
|
|
|
86
96
|
/// Command for creating bullet list node.
|
|
87
|
-
export const wrapInBulletListCommand = $command(
|
|
97
|
+
export const wrapInBulletListCommand = $command(
|
|
98
|
+
'WrapInBulletList',
|
|
99
|
+
(ctx) => () => wrapIn(bulletListSchema.type(ctx))
|
|
100
|
+
)
|
|
88
101
|
|
|
89
102
|
withMeta(wrapInBulletListCommand, {
|
|
90
103
|
displayName: 'Command<wrapInBulletListCommand>',
|
package/src/node/code-block.ts
CHANGED
|
@@ -2,7 +2,13 @@ import { commandsCtx } from '@milkdown/core'
|
|
|
2
2
|
import { expectDomTypeError } from '@milkdown/exception'
|
|
3
3
|
import { setBlockType } from '@milkdown/prose/commands'
|
|
4
4
|
import { textblockTypeInputRule } from '@milkdown/prose/inputrules'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
$command,
|
|
7
|
+
$inputRule,
|
|
8
|
+
$nodeAttr,
|
|
9
|
+
$nodeSchema,
|
|
10
|
+
$useKeymap,
|
|
11
|
+
} from '@milkdown/utils'
|
|
6
12
|
import { withMeta } from '../__internal__'
|
|
7
13
|
|
|
8
14
|
/// HTML attributes for code block node.
|
|
@@ -34,8 +40,7 @@ export const codeBlockSchema = $nodeSchema('code_block', (ctx) => {
|
|
|
34
40
|
tag: 'pre',
|
|
35
41
|
preserveWhitespace: 'full',
|
|
36
42
|
getAttrs: (dom) => {
|
|
37
|
-
if (!(dom instanceof HTMLElement))
|
|
38
|
-
throw expectDomTypeError(dom)
|
|
43
|
+
if (!(dom instanceof HTMLElement)) throw expectDomTypeError(dom)
|
|
39
44
|
|
|
40
45
|
return { language: dom.dataset.language }
|
|
41
46
|
},
|
|
@@ -58,14 +63,13 @@ export const codeBlockSchema = $nodeSchema('code_block', (ctx) => {
|
|
|
58
63
|
const language = node.lang as string
|
|
59
64
|
const value = node.value as string
|
|
60
65
|
state.openNode(type, { language })
|
|
61
|
-
if (value)
|
|
62
|
-
state.addText(value)
|
|
66
|
+
if (value) state.addText(value)
|
|
63
67
|
|
|
64
68
|
state.closeNode()
|
|
65
69
|
},
|
|
66
70
|
},
|
|
67
71
|
toMarkdown: {
|
|
68
|
-
match: node => node.type.name === 'code_block',
|
|
72
|
+
match: (node) => node.type.name === 'code_block',
|
|
69
73
|
runner: (state, node) => {
|
|
70
74
|
state.addNode('code', undefined, node.content.firstChild?.text || '', {
|
|
71
75
|
lang: node.attrs.language,
|
|
@@ -87,9 +91,15 @@ withMeta(codeBlockSchema.ctx, {
|
|
|
87
91
|
|
|
88
92
|
/// A input rule for creating code block.
|
|
89
93
|
/// For example, ` ```javascript ` will create a code block with language javascript.
|
|
90
|
-
export const createCodeBlockInputRule = $inputRule(
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
export const createCodeBlockInputRule = $inputRule((ctx) =>
|
|
95
|
+
textblockTypeInputRule(
|
|
96
|
+
/^```(?<language>[a-z]*)?[\s\n]$/,
|
|
97
|
+
codeBlockSchema.type(ctx),
|
|
98
|
+
(match) => ({
|
|
99
|
+
language: match.groups?.language ?? '',
|
|
100
|
+
})
|
|
101
|
+
)
|
|
102
|
+
)
|
|
93
103
|
|
|
94
104
|
withMeta(createCodeBlockInputRule, {
|
|
95
105
|
displayName: 'InputRule<createCodeBlockInputRule>',
|
|
@@ -98,7 +108,12 @@ withMeta(createCodeBlockInputRule, {
|
|
|
98
108
|
|
|
99
109
|
/// A command for creating code block.
|
|
100
110
|
/// You can pass the language of the code block as the parameter.
|
|
101
|
-
export const createCodeBlockCommand = $command(
|
|
111
|
+
export const createCodeBlockCommand = $command(
|
|
112
|
+
'CreateCodeBlock',
|
|
113
|
+
(ctx) =>
|
|
114
|
+
(language = '') =>
|
|
115
|
+
setBlockType(codeBlockSchema.type(ctx), { language })
|
|
116
|
+
)
|
|
102
117
|
|
|
103
118
|
withMeta(createCodeBlockCommand, {
|
|
104
119
|
displayName: 'Command<createCodeBlockCommand>',
|
|
@@ -106,14 +121,24 @@ withMeta(createCodeBlockCommand, {
|
|
|
106
121
|
})
|
|
107
122
|
|
|
108
123
|
/// A command for updating the code block language of the target position.
|
|
109
|
-
export const updateCodeBlockLanguageCommand = $command(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
124
|
+
export const updateCodeBlockLanguageCommand = $command(
|
|
125
|
+
'UpdateCodeBlockLanguage',
|
|
126
|
+
() =>
|
|
127
|
+
(
|
|
128
|
+
{ pos, language }: { pos: number; language: string } = {
|
|
129
|
+
pos: -1,
|
|
130
|
+
language: '',
|
|
131
|
+
}
|
|
132
|
+
) =>
|
|
133
|
+
(state, dispatch) => {
|
|
134
|
+
if (pos >= 0) {
|
|
135
|
+
dispatch?.(state.tr.setNodeAttribute(pos, 'language', language))
|
|
136
|
+
return true
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return false
|
|
140
|
+
}
|
|
141
|
+
)
|
|
117
142
|
|
|
118
143
|
withMeta(updateCodeBlockLanguageCommand, {
|
|
119
144
|
displayName: 'Command<updateCodeBlockLanguageCommand>',
|
package/src/node/doc.ts
CHANGED
package/src/node/hardbreak.ts
CHANGED
|
@@ -20,7 +20,7 @@ withMeta(hardbreakAttr, {
|
|
|
20
20
|
})
|
|
21
21
|
|
|
22
22
|
/// Hardbreak node schema.
|
|
23
|
-
export const hardbreakSchema = $nodeSchema('hardbreak', ctx => ({
|
|
23
|
+
export const hardbreakSchema = $nodeSchema('hardbreak', (ctx) => ({
|
|
24
24
|
inline: true,
|
|
25
25
|
group: 'inline',
|
|
26
26
|
attrs: {
|
|
@@ -29,23 +29,33 @@ export const hardbreakSchema = $nodeSchema('hardbreak', ctx => ({
|
|
|
29
29
|
},
|
|
30
30
|
},
|
|
31
31
|
selectable: false,
|
|
32
|
-
parseDOM: [
|
|
33
|
-
|
|
32
|
+
parseDOM: [
|
|
33
|
+
{ tag: 'br' },
|
|
34
|
+
{
|
|
35
|
+
tag: 'span[data-type="hardbreak"]',
|
|
36
|
+
getAttrs: () => ({ isInline: true }),
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
toDOM: (node) =>
|
|
40
|
+
node.attrs.isInline
|
|
41
|
+
? ['span', ctx.get(hardbreakAttr.key)(node), ' ']
|
|
42
|
+
: ['br', ctx.get(hardbreakAttr.key)(node)],
|
|
34
43
|
parseMarkdown: {
|
|
35
44
|
match: ({ type }) => type === 'break',
|
|
36
45
|
runner: (state, node, type) => {
|
|
37
|
-
state.addNode(type, {
|
|
46
|
+
state.addNode(type, {
|
|
47
|
+
isInline: Boolean(
|
|
48
|
+
(node.data as undefined | { isInline: boolean })?.isInline
|
|
49
|
+
),
|
|
50
|
+
})
|
|
38
51
|
},
|
|
39
52
|
},
|
|
40
53
|
leafText: () => '\n',
|
|
41
54
|
toMarkdown: {
|
|
42
|
-
match: node => node.type.name === 'hardbreak',
|
|
55
|
+
match: (node) => node.type.name === 'hardbreak',
|
|
43
56
|
runner: (state, node) => {
|
|
44
|
-
if (node.attrs.isInline)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
else
|
|
48
|
-
state.addNode('break')
|
|
57
|
+
if (node.attrs.isInline) state.addNode('text', undefined, '\n')
|
|
58
|
+
else state.addNode('break')
|
|
49
59
|
},
|
|
50
60
|
},
|
|
51
61
|
}))
|
|
@@ -61,27 +71,38 @@ withMeta(hardbreakSchema.ctx, {
|
|
|
61
71
|
})
|
|
62
72
|
|
|
63
73
|
/// Command to insert a hardbreak.
|
|
64
|
-
export const insertHardbreakCommand = $command(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
export const insertHardbreakCommand = $command(
|
|
75
|
+
'InsertHardbreak',
|
|
76
|
+
(ctx) => () => (state, dispatch) => {
|
|
77
|
+
const { selection, tr } = state
|
|
78
|
+
if (!(selection instanceof TextSelection)) return false
|
|
68
79
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
if (selection.empty) {
|
|
81
|
+
// Transform two successive hardbreak into a new line
|
|
82
|
+
const node = selection.$from.node()
|
|
83
|
+
if (node.childCount > 0 && node.lastChild?.type.name === 'hardbreak') {
|
|
84
|
+
dispatch?.(
|
|
85
|
+
tr
|
|
86
|
+
.replaceRangeWith(
|
|
87
|
+
selection.to - 1,
|
|
88
|
+
selection.to,
|
|
89
|
+
state.schema.node('paragraph')
|
|
90
|
+
)
|
|
91
|
+
.setSelection(Selection.near(tr.doc.resolve(selection.to)))
|
|
92
|
+
.scrollIntoView()
|
|
93
|
+
)
|
|
94
|
+
return true
|
|
95
|
+
}
|
|
80
96
|
}
|
|
97
|
+
dispatch?.(
|
|
98
|
+
tr
|
|
99
|
+
.setMeta('hardbreak', true)
|
|
100
|
+
.replaceSelectionWith(hardbreakSchema.type(ctx).create())
|
|
101
|
+
.scrollIntoView()
|
|
102
|
+
)
|
|
103
|
+
return true
|
|
81
104
|
}
|
|
82
|
-
|
|
83
|
-
return true
|
|
84
|
-
})
|
|
105
|
+
)
|
|
85
106
|
|
|
86
107
|
withMeta(insertHardbreakCommand, {
|
|
87
108
|
displayName: 'Command<insertHardbreakCommand>',
|
package/src/node/heading.ts
CHANGED
|
@@ -3,7 +3,14 @@ import { expectDomTypeError } from '@milkdown/exception'
|
|
|
3
3
|
import { setBlockType } from '@milkdown/prose/commands'
|
|
4
4
|
import { textblockTypeInputRule } from '@milkdown/prose/inputrules'
|
|
5
5
|
import type { Node } from '@milkdown/prose/model'
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
$command,
|
|
8
|
+
$ctx,
|
|
9
|
+
$inputRule,
|
|
10
|
+
$nodeAttr,
|
|
11
|
+
$nodeSchema,
|
|
12
|
+
$useKeymap,
|
|
13
|
+
} from '@milkdown/utils'
|
|
7
14
|
import slugify from '@sindresorhus/slugify'
|
|
8
15
|
import { serializeText, withMeta } from '../__internal__'
|
|
9
16
|
import { paragraphSchema } from './paragraph'
|
|
@@ -18,7 +25,10 @@ function defaultHeadingIdGenerator(node: Node) {
|
|
|
18
25
|
|
|
19
26
|
/// This is a slice contains a function to generate heading id.
|
|
20
27
|
/// You can configure it to generate id in your own way.
|
|
21
|
-
export const headingIdGenerator = $ctx(
|
|
28
|
+
export const headingIdGenerator = $ctx(
|
|
29
|
+
defaultHeadingIdGenerator,
|
|
30
|
+
'headingIdGenerator'
|
|
31
|
+
)
|
|
22
32
|
|
|
23
33
|
withMeta(headingIdGenerator, {
|
|
24
34
|
displayName: 'Ctx<HeadingIdGenerator>',
|
|
@@ -48,11 +58,10 @@ export const headingSchema = $nodeSchema('heading', (ctx) => {
|
|
|
48
58
|
default: 1,
|
|
49
59
|
},
|
|
50
60
|
},
|
|
51
|
-
parseDOM: headingIndex.map(x => ({
|
|
61
|
+
parseDOM: headingIndex.map((x) => ({
|
|
52
62
|
tag: `h${x}`,
|
|
53
63
|
getAttrs: (node) => {
|
|
54
|
-
if (!(node instanceof HTMLElement))
|
|
55
|
-
throw expectDomTypeError(node)
|
|
64
|
+
if (!(node instanceof HTMLElement)) throw expectDomTypeError(node)
|
|
56
65
|
|
|
57
66
|
return { level: x, id: node.id }
|
|
58
67
|
},
|
|
@@ -77,7 +86,7 @@ export const headingSchema = $nodeSchema('heading', (ctx) => {
|
|
|
77
86
|
},
|
|
78
87
|
},
|
|
79
88
|
toMarkdown: {
|
|
80
|
-
match: node => node.type.name === 'heading',
|
|
89
|
+
match: (node) => node.type.name === 'heading',
|
|
81
90
|
runner: (state, node) => {
|
|
82
91
|
state.openNode('heading', undefined, { depth: node.attrs.level })
|
|
83
92
|
serializeText(state, node)
|
|
@@ -100,21 +109,24 @@ withMeta(headingSchema.ctx, {
|
|
|
100
109
|
/// This input rule can turn the selected block into heading.
|
|
101
110
|
/// You can input numbers of `#` and a `space` to create heading.
|
|
102
111
|
export const wrapInHeadingInputRule = $inputRule((ctx) => {
|
|
103
|
-
return textblockTypeInputRule(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
return textblockTypeInputRule(
|
|
113
|
+
/^(?<hashes>#+)\s$/,
|
|
114
|
+
headingSchema.type(ctx),
|
|
115
|
+
(match) => {
|
|
116
|
+
const x = match.groups?.hashes?.length || 0
|
|
117
|
+
|
|
118
|
+
const view = ctx.get(editorViewCtx)
|
|
119
|
+
const { $from } = view.state.selection
|
|
120
|
+
const node = $from.node()
|
|
121
|
+
if (node.type.name === 'heading') {
|
|
122
|
+
let level = Number(node.attrs.level) + Number(x)
|
|
123
|
+
if (level > 6) level = 6
|
|
124
|
+
|
|
125
|
+
return { level }
|
|
126
|
+
}
|
|
127
|
+
return { level: x }
|
|
115
128
|
}
|
|
116
|
-
|
|
117
|
-
})
|
|
129
|
+
)
|
|
118
130
|
})
|
|
119
131
|
|
|
120
132
|
withMeta(wrapInHeadingInputRule, {
|
|
@@ -129,8 +141,7 @@ export const wrapInHeadingCommand = $command('WrapInHeading', (ctx) => {
|
|
|
129
141
|
return (level?: number) => {
|
|
130
142
|
level ??= 1
|
|
131
143
|
|
|
132
|
-
if (level < 1)
|
|
133
|
-
return setBlockType(paragraphSchema.type(ctx))
|
|
144
|
+
if (level < 1) return setBlockType(paragraphSchema.type(ctx))
|
|
134
145
|
|
|
135
146
|
return setBlockType(headingSchema.type(ctx), { level })
|
|
136
147
|
}
|
|
@@ -144,11 +155,16 @@ withMeta(wrapInHeadingCommand, {
|
|
|
144
155
|
/// This command can downgrade the selected heading.
|
|
145
156
|
/// For example, if you have a `h2` element, and you call this command, you will get a `h1` element.
|
|
146
157
|
/// If the element is already a `h1` element, it will turn it into a `p` element.
|
|
147
|
-
export const downgradeHeadingCommand = $command(
|
|
148
|
-
|
|
158
|
+
export const downgradeHeadingCommand = $command(
|
|
159
|
+
'DowngradeHeading',
|
|
160
|
+
(ctx) => () => (state, dispatch, view) => {
|
|
149
161
|
const { $from } = state.selection
|
|
150
162
|
const node = $from.node()
|
|
151
|
-
if (
|
|
163
|
+
if (
|
|
164
|
+
node.type !== headingSchema.type(ctx) ||
|
|
165
|
+
!state.selection.empty ||
|
|
166
|
+
$from.parentOffset !== 0
|
|
167
|
+
)
|
|
152
168
|
return false
|
|
153
169
|
|
|
154
170
|
const level = node.attrs.level - 1
|
|
@@ -159,10 +175,11 @@ export const downgradeHeadingCommand = $command('DowngradeHeading', ctx => () =>
|
|
|
159
175
|
state.tr.setNodeMarkup(state.selection.$from.before(), undefined, {
|
|
160
176
|
...node.attrs,
|
|
161
177
|
level,
|
|
162
|
-
})
|
|
178
|
+
})
|
|
163
179
|
)
|
|
164
180
|
return true
|
|
165
|
-
}
|
|
181
|
+
}
|
|
182
|
+
)
|
|
166
183
|
|
|
167
184
|
withMeta(downgradeHeadingCommand, {
|
|
168
185
|
displayName: 'Command<downgradeHeadingCommand>',
|
package/src/node/hr.ts
CHANGED
|
@@ -13,10 +13,10 @@ withMeta(hrAttr, {
|
|
|
13
13
|
})
|
|
14
14
|
|
|
15
15
|
/// Hr node schema.
|
|
16
|
-
export const hrSchema = $nodeSchema('hr', ctx => ({
|
|
16
|
+
export const hrSchema = $nodeSchema('hr', (ctx) => ({
|
|
17
17
|
group: 'block',
|
|
18
18
|
parseDOM: [{ tag: 'hr' }],
|
|
19
|
-
toDOM: node => ['hr', ctx.get(hrAttr.key)(node)],
|
|
19
|
+
toDOM: (node) => ['hr', ctx.get(hrAttr.key)(node)],
|
|
20
20
|
parseMarkdown: {
|
|
21
21
|
match: ({ type }) => type === 'thematicBreak',
|
|
22
22
|
runner: (state, _, type) => {
|
|
@@ -24,7 +24,7 @@ export const hrSchema = $nodeSchema('hr', ctx => ({
|
|
|
24
24
|
},
|
|
25
25
|
},
|
|
26
26
|
toMarkdown: {
|
|
27
|
-
match: node => node.type.name === 'hr',
|
|
27
|
+
match: (node) => node.type.name === 'hr',
|
|
28
28
|
runner: (state) => {
|
|
29
29
|
state.addNode('thematicBreak')
|
|
30
30
|
},
|
|
@@ -43,17 +43,16 @@ withMeta(hrSchema.ctx, {
|
|
|
43
43
|
|
|
44
44
|
/// Input rule to insert a hr.
|
|
45
45
|
/// For example, `---` will be converted to a hr.
|
|
46
|
-
export const insertHrInputRule = $inputRule(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
export const insertHrInputRule = $inputRule(
|
|
47
|
+
(ctx) =>
|
|
48
|
+
new InputRule(/^(?:---|___\s|\*\*\*\s)$/, (state, match, start, end) => {
|
|
49
|
+
const { tr } = state
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
tr.replaceWith(start - 1, end, hrSchema.type(ctx).create())
|
|
51
|
+
if (match[0]) tr.replaceWith(start - 1, end, hrSchema.type(ctx).create())
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
)
|
|
53
|
+
return tr
|
|
54
|
+
})
|
|
55
|
+
)
|
|
57
56
|
|
|
58
57
|
withMeta(insertHrInputRule, {
|
|
59
58
|
displayName: 'InputRule<insertHrInputRule>',
|
|
@@ -61,25 +60,25 @@ withMeta(insertHrInputRule, {
|
|
|
61
60
|
})
|
|
62
61
|
|
|
63
62
|
/// Command to insert a hr.
|
|
64
|
-
export const insertHrCommand = $command(
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
export const insertHrCommand = $command(
|
|
64
|
+
'InsertHr',
|
|
65
|
+
(ctx) => () => (state, dispatch) => {
|
|
66
|
+
if (!dispatch) return true
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return true
|
|
68
|
+
const paragraph = paragraphSchema.node.type(ctx).create()
|
|
69
|
+
const { tr, selection } = state
|
|
70
|
+
const { from } = selection
|
|
71
|
+
const node = hrSchema.type(ctx).create()
|
|
72
|
+
if (!node) return true
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return true
|
|
74
|
+
const _tr = tr.replaceSelectionWith(node).insert(from, paragraph)
|
|
75
|
+
const sel = Selection.findFrom(_tr.doc.resolve(from), 1, true)
|
|
76
|
+
if (!sel) return true
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
78
|
+
dispatch(_tr.setSelection(sel).scrollIntoView())
|
|
79
|
+
return true
|
|
80
|
+
}
|
|
81
|
+
)
|
|
83
82
|
|
|
84
83
|
withMeta(insertHrCommand, {
|
|
85
84
|
displayName: 'Command<insertHrCommand>',
|