@milkdown/preset-commonmark 6.5.4 → 7.0.0-next.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 (153) hide show
  1. package/lib/composed/commands.d.ts +3 -0
  2. package/lib/composed/commands.d.ts.map +1 -0
  3. package/lib/composed/index.d.ts +6 -0
  4. package/lib/composed/index.d.ts.map +1 -0
  5. package/lib/composed/inputrules.d.ts +3 -0
  6. package/lib/composed/inputrules.d.ts.map +1 -0
  7. package/lib/composed/keymap.d.ts +3 -0
  8. package/lib/composed/keymap.d.ts.map +1 -0
  9. package/lib/composed/plugins.d.ts +2 -0
  10. package/lib/composed/plugins.d.ts.map +1 -0
  11. package/lib/composed/schema.d.ts +3 -0
  12. package/lib/composed/schema.d.ts.map +1 -0
  13. package/lib/index.d.ts +4 -29
  14. package/lib/index.d.ts.map +1 -1
  15. package/lib/index.es.js +1101 -1386
  16. package/lib/index.es.js.map +1 -1
  17. package/lib/mark/emphasis.d.ts +5 -0
  18. package/lib/mark/emphasis.d.ts.map +1 -0
  19. package/lib/mark/index.d.ts +3 -4
  20. package/lib/mark/index.d.ts.map +1 -1
  21. package/lib/mark/inline-code.d.ts +5 -0
  22. package/lib/mark/inline-code.d.ts.map +1 -0
  23. package/lib/mark/link.d.ts +8 -10
  24. package/lib/mark/link.d.ts.map +1 -1
  25. package/lib/mark/strong.d.ts +4 -2
  26. package/lib/mark/strong.d.ts.map +1 -1
  27. package/lib/node/blockquote.d.ts +6 -2
  28. package/lib/node/blockquote.d.ts.map +1 -1
  29. package/lib/node/bullet-list.d.ts +5 -2
  30. package/lib/node/bullet-list.d.ts.map +1 -1
  31. package/lib/node/code-block.d.ts +10 -0
  32. package/lib/node/code-block.d.ts.map +1 -0
  33. package/lib/node/doc.d.ts +1 -1
  34. package/lib/node/doc.d.ts.map +1 -1
  35. package/lib/node/hardbreak.d.ts +4 -6
  36. package/lib/node/hardbreak.d.ts.map +1 -1
  37. package/lib/node/heading.d.ts +7 -12
  38. package/lib/node/heading.d.ts.map +1 -1
  39. package/lib/node/hr.d.ts +4 -2
  40. package/lib/node/hr.d.ts.map +1 -1
  41. package/lib/node/image.d.ts +10 -11
  42. package/lib/node/image.d.ts.map +1 -1
  43. package/lib/node/index.d.ts +6 -8
  44. package/lib/node/index.d.ts.map +1 -1
  45. package/lib/node/list-item.d.ts +6 -7
  46. package/lib/node/list-item.d.ts.map +1 -1
  47. package/lib/node/ordered-list.d.ts +5 -2
  48. package/lib/node/ordered-list.d.ts.map +1 -1
  49. package/lib/node/paragraph.d.ts +4 -2
  50. package/lib/node/paragraph.d.ts.map +1 -1
  51. package/lib/node/text.d.ts +1 -1
  52. package/lib/node/text.d.ts.map +1 -1
  53. package/lib/plugin/hardbreak-clear-mark-plugin.d.ts +2 -0
  54. package/lib/plugin/hardbreak-clear-mark-plugin.d.ts.map +1 -0
  55. package/lib/plugin/hardbreak-filter-plugin.d.ts +3 -0
  56. package/lib/plugin/hardbreak-filter-plugin.d.ts.map +1 -0
  57. package/lib/plugin/index.d.ts +9 -3
  58. package/lib/plugin/index.d.ts.map +1 -1
  59. package/lib/plugin/{inline-nodes-cursor.d.ts → inline-nodes-cursor-plugin.d.ts} +2 -3
  60. package/lib/plugin/inline-nodes-cursor-plugin.d.ts.map +1 -0
  61. package/lib/plugin/{inline-sync → inline-sync-plugin}/config.d.ts +2 -2
  62. package/lib/plugin/inline-sync-plugin/config.d.ts.map +1 -0
  63. package/lib/plugin/{inline-sync → inline-sync-plugin}/context.d.ts +1 -2
  64. package/lib/plugin/inline-sync-plugin/context.d.ts.map +1 -0
  65. package/lib/plugin/inline-sync-plugin/index.d.ts +3 -0
  66. package/lib/plugin/inline-sync-plugin/index.d.ts.map +1 -0
  67. package/lib/plugin/inline-sync-plugin/inline-sync-plugin.d.ts +2 -0
  68. package/lib/plugin/inline-sync-plugin/inline-sync-plugin.d.ts.map +1 -0
  69. package/lib/plugin/{inline-sync → inline-sync-plugin}/regexp.d.ts +0 -0
  70. package/lib/plugin/inline-sync-plugin/regexp.d.ts.map +1 -0
  71. package/lib/plugin/{inline-sync → inline-sync-plugin}/replacer.d.ts +1 -1
  72. package/lib/plugin/inline-sync-plugin/replacer.d.ts.map +1 -0
  73. package/lib/plugin/{inline-sync → inline-sync-plugin}/utils.d.ts +0 -0
  74. package/lib/plugin/inline-sync-plugin/utils.d.ts.map +1 -0
  75. package/lib/plugin/remark-add-order-in-list-plugin.d.ts +2 -0
  76. package/lib/plugin/remark-add-order-in-list-plugin.d.ts.map +1 -0
  77. package/lib/plugin/remark-inline-link-plugin.d.ts +2 -0
  78. package/lib/plugin/remark-inline-link-plugin.d.ts.map +1 -0
  79. package/lib/plugin/remark-line-break.d.ts +2 -0
  80. package/lib/plugin/remark-line-break.d.ts.map +1 -0
  81. package/lib/plugin/sync-heading-id-plugin.d.ts +2 -0
  82. package/lib/plugin/sync-heading-id-plugin.d.ts.map +1 -0
  83. package/lib/plugin/sync-list-order-plugin.d.ts +2 -0
  84. package/lib/plugin/sync-list-order-plugin.d.ts.map +1 -0
  85. package/package.json +9 -7
  86. package/src/composed/commands.ts +30 -0
  87. package/src/composed/index.ts +6 -0
  88. package/src/composed/inputrules.ts +12 -0
  89. package/src/composed/keymap.ts +19 -0
  90. package/src/composed/plugins.ts +21 -0
  91. package/src/composed/schema.ts +54 -0
  92. package/src/index.ts +5 -52
  93. package/src/mark/emphasis.ts +42 -0
  94. package/src/mark/index.ts +3 -10
  95. package/src/mark/inline-code.ts +64 -0
  96. package/src/mark/link.ts +87 -247
  97. package/src/mark/strong.ts +35 -36
  98. package/src/node/blockquote.ts +32 -33
  99. package/src/node/bullet-list.ts +56 -56
  100. package/src/node/code-block.ts +93 -0
  101. package/src/node/doc.ts +17 -22
  102. package/src/node/hardbreak.ts +60 -117
  103. package/src/node/heading.ts +158 -281
  104. package/src/node/hr.ts +51 -57
  105. package/src/node/image.ts +102 -209
  106. package/src/node/index.ts +6 -35
  107. package/src/node/list-item.ts +81 -142
  108. package/src/node/ordered-list.ts +64 -65
  109. package/src/node/paragraph.ts +48 -50
  110. package/src/node/text.ts +13 -16
  111. package/src/plugin/hardbreak-clear-mark-plugin.ts +44 -0
  112. package/src/plugin/hardbreak-filter-plugin.ts +31 -0
  113. package/src/plugin/index.ts +12 -14
  114. package/src/plugin/{inline-nodes-cursor.ts → inline-nodes-cursor-plugin.ts} +4 -4
  115. package/src/plugin/{inline-sync → inline-sync-plugin}/config.ts +4 -3
  116. package/src/plugin/{inline-sync → inline-sync-plugin}/context.ts +4 -6
  117. package/src/plugin/inline-sync-plugin/index.ts +4 -0
  118. package/src/plugin/{inline-sync/index.ts → inline-sync-plugin/inline-sync-plugin.ts} +9 -11
  119. package/src/plugin/{inline-sync → inline-sync-plugin}/regexp.ts +0 -0
  120. package/src/plugin/{inline-sync → inline-sync-plugin}/replacer.ts +3 -3
  121. package/src/plugin/{inline-sync → inline-sync-plugin}/utils.ts +0 -0
  122. package/src/plugin/remark-add-order-in-list-plugin.ts +15 -0
  123. package/src/plugin/remark-inline-link-plugin.ts +5 -0
  124. package/src/plugin/remark-line-break.ts +41 -0
  125. package/src/plugin/sync-heading-id-plugin.ts +53 -0
  126. package/src/plugin/sync-list-order-plugin.ts +57 -0
  127. package/lib/mark/code-inline.d.ts +0 -3
  128. package/lib/mark/code-inline.d.ts.map +0 -1
  129. package/lib/mark/em.d.ts +0 -3
  130. package/lib/mark/em.d.ts.map +0 -1
  131. package/lib/node/code-fence.d.ts +0 -7
  132. package/lib/node/code-fence.d.ts.map +0 -1
  133. package/lib/plugin/add-order-in-list.d.ts +0 -3
  134. package/lib/plugin/add-order-in-list.d.ts.map +0 -1
  135. package/lib/plugin/filter-html.d.ts +0 -3
  136. package/lib/plugin/filter-html.d.ts.map +0 -1
  137. package/lib/plugin/inline-nodes-cursor.d.ts.map +0 -1
  138. package/lib/plugin/inline-sync/config.d.ts.map +0 -1
  139. package/lib/plugin/inline-sync/context.d.ts.map +0 -1
  140. package/lib/plugin/inline-sync/index.d.ts +0 -6
  141. package/lib/plugin/inline-sync/index.d.ts.map +0 -1
  142. package/lib/plugin/inline-sync/regexp.d.ts.map +0 -1
  143. package/lib/plugin/inline-sync/replacer.d.ts.map +0 -1
  144. package/lib/plugin/inline-sync/utils.d.ts.map +0 -1
  145. package/lib/supported-keys.d.ts +0 -23
  146. package/lib/supported-keys.d.ts.map +0 -1
  147. package/src/mark/code-inline.ts +0 -66
  148. package/src/mark/em.ts +0 -42
  149. package/src/node/code-fence.ts +0 -245
  150. package/src/plugin/add-order-in-list.ts +0 -19
  151. package/src/plugin/filter-html.ts +0 -43
  152. package/src/supported-keys.ts +0 -25
  153. package/src/types.d.ts +0 -5
@@ -1,42 +1,41 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
- import { createCmd, createCmdKey } from '@milkdown/core'
2
+ import { commandsCtx } from '@milkdown/core'
3
3
  import { toggleMark } from '@milkdown/prose/commands'
4
- import { createMark, createShortcut } from '@milkdown/utils'
4
+ import { $command, $markAttr, $markSchema, $useKeymap } from '@milkdown/utils'
5
5
 
6
- import { SupportedKeys } from '../supported-keys'
6
+ export const strongAttr = $markAttr('strong')
7
+ export const strongSchema = $markSchema('strong', ctx => ({
8
+ inclusive: false,
9
+ parseDOM: [
10
+ { tag: 'b' },
11
+ { tag: 'strong' },
12
+ { style: 'font-style', getAttrs: value => (value === 'bold') as false },
13
+ ],
14
+ toDOM: mark => ['strong', ctx.get(strongAttr.key)(mark)],
15
+ parseMarkdown: {
16
+ match: node => node.type === 'strong',
17
+ runner: (state, node, markType) => {
18
+ state.openMark(markType)
19
+ state.next(node.children)
20
+ state.closeMark(markType)
21
+ },
22
+ },
23
+ toMarkdown: {
24
+ match: mark => mark.type.name === 'strong',
25
+ runner: (state, mark) => {
26
+ state.withMark(mark, 'strong')
27
+ },
28
+ },
29
+ }))
30
+
31
+ export const toggleStrongCommand = $command('ToggleStrong', () => () => toggleMark(strongSchema.type()))
7
32
 
8
- type Keys = SupportedKeys['Bold']
9
- const id = 'strong'
10
- export const ToggleBold = createCmdKey('ToggleBold')
11
- export const strong = createMark<Keys>((utils) => {
12
- return {
13
- id,
14
- schema: () => ({
15
- inclusive: false,
16
- parseDOM: [
17
- { tag: 'b' },
18
- { tag: 'strong' },
19
- { style: 'font-style', getAttrs: value => (value === 'bold') as false },
20
- ],
21
- toDOM: mark => ['strong', { class: utils.getClassName(mark.attrs, id) }],
22
- parseMarkdown: {
23
- match: node => node.type === 'strong',
24
- runner: (state, node, markType) => {
25
- state.openMark(markType)
26
- state.next(node.children)
27
- state.closeMark(markType)
28
- },
29
- },
30
- toMarkdown: {
31
- match: mark => mark.type.name === id,
32
- runner: (state, mark) => {
33
- state.withMark(mark, 'strong')
34
- },
35
- },
36
- }),
37
- commands: markType => [createCmd(ToggleBold, () => toggleMark(markType))],
38
- shortcuts: {
39
- [SupportedKeys.Bold]: createShortcut(ToggleBold, 'Mod-b'),
33
+ export const strongKeymap = $useKeymap('strongKeymap', {
34
+ ToggleBold: {
35
+ shortcuts: ['Mod-b'],
36
+ command: (ctx) => {
37
+ const commands = ctx.get(commandsCtx)
38
+ return () => commands.call(toggleStrongCommand.key)
40
39
  },
41
- }
40
+ },
42
41
  })
@@ -1,43 +1,42 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
- import { createCmd, createCmdKey } from '@milkdown/core'
2
+ import { commandsCtx } from '@milkdown/core'
3
3
  import { wrapIn } from '@milkdown/prose/commands'
4
4
  import { wrappingInputRule } from '@milkdown/prose/inputrules'
5
- import { createNode, createShortcut } from '@milkdown/utils'
5
+ import type { $NodeSchema } from '@milkdown/utils'
6
+ import { $command, $inputRule, $nodeAttr, $nodeSchema, $useKeymap } from '@milkdown/utils'
6
7
 
7
- import { SupportedKeys } from '../supported-keys'
8
+ export const blockquoteAttr = $nodeAttr('blockquote')
8
9
 
9
- type Keys = SupportedKeys['Blockquote']
10
+ export const blockquoteSchema: $NodeSchema<'blockquote'> = $nodeSchema('blockquote', ctx => ({
11
+ content: 'block+',
12
+ group: 'block',
13
+ defining: true,
14
+ parseDOM: [{ tag: 'blockquote' }],
15
+ toDOM: node => ['blockquote', ctx.get(blockquoteAttr.key)(node), 0],
16
+ parseMarkdown: {
17
+ match: ({ type }) => type === 'blockquote',
18
+ runner: (state, node, type) => {
19
+ state.openNode(type).next(node.children).closeNode()
20
+ },
21
+ },
22
+ toMarkdown: {
23
+ match: node => node.type.name === 'blockquote',
24
+ runner: (state, node) => {
25
+ state.openNode('blockquote').next(node.content).closeNode()
26
+ },
27
+ },
28
+ }))
10
29
 
11
- const id = 'blockquote'
30
+ export const wrapInBlockquoteInputRule = $inputRule(() => wrappingInputRule(/^\s*>\s$/, blockquoteSchema.type()))
12
31
 
13
- export const WrapInBlockquote = createCmdKey('WrapInBlockquote')
32
+ export const wrapInBlockquoteCommand = $command('WrapInBlockquote', () => () => wrapIn(blockquoteSchema.type()))
14
33
 
15
- export const blockquote = createNode<Keys>((utils) => {
16
- return {
17
- id,
18
- schema: () => ({
19
- content: 'block+',
20
- group: 'block',
21
- defining: true,
22
- parseDOM: [{ tag: 'blockquote' }],
23
- toDOM: node => ['blockquote', { class: utils.getClassName(node.attrs, id) }, 0],
24
- parseMarkdown: {
25
- match: ({ type }) => type === id,
26
- runner: (state, node, type) => {
27
- state.openNode(type).next(node.children).closeNode()
28
- },
29
- },
30
- toMarkdown: {
31
- match: node => node.type.name === id,
32
- runner: (state, node) => {
33
- state.openNode('blockquote').next(node.content).closeNode()
34
- },
35
- },
36
- }),
37
- inputRules: nodeType => [wrappingInputRule(/^\s*>\s$/, nodeType)],
38
- commands: nodeType => [createCmd(WrapInBlockquote, () => wrapIn(nodeType))],
39
- shortcuts: {
40
- [SupportedKeys.Blockquote]: createShortcut(WrapInBlockquote, 'Mod-Shift-b'),
34
+ export const blockquoteKeymap = $useKeymap('blockquoteKeymap', {
35
+ WrapInBlockquote: {
36
+ shortcuts: 'Mod-Shift-b',
37
+ command: (ctx) => {
38
+ const commands = ctx.get(commandsCtx)
39
+ return () => commands.call(wrapInBlockquoteCommand.key)
41
40
  },
42
- }
41
+ },
43
42
  })
@@ -1,72 +1,72 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
- import { createCmd, createCmdKey } from '@milkdown/core'
2
+ import { commandsCtx } from '@milkdown/core'
3
3
  import { expectDomTypeError } from '@milkdown/exception'
4
4
  import { wrapIn } from '@milkdown/prose/commands'
5
5
  import { wrappingInputRule } from '@milkdown/prose/inputrules'
6
- import { createNode, createShortcut } from '@milkdown/utils'
6
+ import { $command, $inputRule, $nodeAttr, $nodeSchema, $useKeymap } from '@milkdown/utils'
7
7
 
8
- import { SupportedKeys } from '../supported-keys'
9
-
10
- type Keys = SupportedKeys['BulletList']
11
-
12
- export const WrapInBulletList = createCmdKey('WrapInBulletList')
13
-
14
- export const bulletList = createNode<Keys>((utils) => {
15
- const id = 'bullet_list'
8
+ export const bulletListAttr = $nodeAttr('bulletList')
9
+ export const bulletListSchema = $nodeSchema('bullet_list', (ctx) => {
16
10
  return {
17
- id,
18
- schema: () => ({
19
- content: 'listItem+',
20
- group: 'block',
21
- attrs: {
22
- spread: {
23
- default: false,
24
- },
11
+ content: 'listItem+',
12
+ group: 'block',
13
+ attrs: {
14
+ spread: {
15
+ default: false,
25
16
  },
26
- parseDOM: [
27
- {
28
- tag: 'ul',
29
- getAttrs: (dom) => {
30
- if (!(dom instanceof HTMLElement))
31
- throw expectDomTypeError(dom)
17
+ },
18
+ parseDOM: [
19
+ {
20
+ tag: 'ul',
21
+ getAttrs: (dom) => {
22
+ if (!(dom instanceof HTMLElement))
23
+ throw expectDomTypeError(dom)
32
24
 
33
- return {
34
- spread: dom.dataset.spread,
35
- }
36
- },
25
+ return {
26
+ spread: dom.dataset.spread,
27
+ }
37
28
  },
38
- ],
39
- toDOM: (node) => {
40
- return [
41
- 'ul',
42
- {
43
- 'data-spread': node.attrs.spread,
44
- 'class': utils.getClassName(node.attrs, 'bullet-list'),
45
- },
46
- 0,
47
- ]
48
29
  },
49
- parseMarkdown: {
50
- match: ({ type, ordered }) => type === 'list' && !ordered,
51
- runner: (state, node, type) => {
52
- const spread = node.spread != null ? `${node.spread}` : 'false'
53
- state.openNode(type, { spread }).next(node.children).closeNode()
30
+ ],
31
+ toDOM: (node) => {
32
+ return [
33
+ 'ul',
34
+ {
35
+ ...ctx.get(bulletListAttr.key)(node),
36
+ 'data-spread': node.attrs.spread,
54
37
  },
38
+ 0,
39
+ ]
40
+ },
41
+ parseMarkdown: {
42
+ match: ({ type, ordered }) => type === 'list' && !ordered,
43
+ runner: (state, node, type) => {
44
+ const spread = node.spread != null ? `${node.spread}` : 'false'
45
+ state.openNode(type, { spread }).next(node.children).closeNode()
55
46
  },
56
- toMarkdown: {
57
- match: node => node.type.name === id,
58
- runner: (state, node) => {
59
- state
60
- .openNode('list', undefined, { ordered: false, spread: node.attrs.spread === 'true' })
61
- .next(node.content)
62
- .closeNode()
63
- },
47
+ },
48
+ toMarkdown: {
49
+ match: node => node.type.name === 'bullet_list',
50
+ runner: (state, node) => {
51
+ state
52
+ .openNode('list', undefined, { ordered: false, spread: node.attrs.spread === 'true' })
53
+ .next(node.content)
54
+ .closeNode()
64
55
  },
65
- }),
66
- inputRules: nodeType => [wrappingInputRule(/^\s*([-+*])\s$/, nodeType)],
67
- commands: nodeType => [createCmd(WrapInBulletList, () => wrapIn(nodeType))],
68
- shortcuts: {
69
- [SupportedKeys.BulletList]: createShortcut(WrapInBulletList, 'Mod-Alt-8'),
70
56
  },
71
57
  }
72
58
  })
59
+
60
+ export const wrapInBulletListInputRule = $inputRule(() => wrappingInputRule(/^\s*([-+*])\s$/, bulletListSchema.type()))
61
+
62
+ export const wrapInBulletListCommand = $command('WrapInBulletList', () => () => wrapIn(bulletListSchema.type()))
63
+
64
+ export const bulletListKeymap = $useKeymap('bulletListKeymap', {
65
+ WrapInBulletList: {
66
+ shortcuts: 'Mod-Alt-8',
67
+ command: (ctx) => {
68
+ const commands = ctx.get(commandsCtx)
69
+ return () => commands.call(wrapInBulletListCommand.key)
70
+ },
71
+ },
72
+ })
@@ -0,0 +1,93 @@
1
+ /* Copyright 2021, Milkdown by Mirone. */
2
+ import { commandsCtx } from '@milkdown/core'
3
+ import { expectDomTypeError } from '@milkdown/exception'
4
+ import { setBlockType } from '@milkdown/prose/commands'
5
+ import { textblockTypeInputRule } from '@milkdown/prose/inputrules'
6
+ import { $command, $inputRule, $nodeAttr, $nodeSchema, $useKeymap } from '@milkdown/utils'
7
+
8
+ export const codeBlockAttr = $nodeAttr('codeBlock', () => ({
9
+ pre: {},
10
+ code: {},
11
+ }))
12
+
13
+ export const codeBlockSchema = $nodeSchema('code_block', (ctx) => {
14
+ return {
15
+ content: 'text*',
16
+ group: 'block',
17
+ marks: '',
18
+ defining: true,
19
+ code: true,
20
+ attrs: {
21
+ language: {
22
+ default: '',
23
+ },
24
+ },
25
+ parseDOM: [
26
+ {
27
+ tag: 'pre',
28
+ preserveWhitespace: 'full',
29
+ getAttrs: (dom) => {
30
+ if (!(dom instanceof HTMLElement))
31
+ throw expectDomTypeError(dom)
32
+
33
+ return { language: dom.dataset.language }
34
+ },
35
+ },
36
+ ],
37
+ toDOM: (node) => {
38
+ const attr = ctx.get(codeBlockAttr.key)(node)
39
+ return [
40
+ 'pre',
41
+ {
42
+ ...attr.pre,
43
+ 'data-language': node.attrs.language,
44
+ },
45
+ ['code', attr.code, 0],
46
+ ]
47
+ },
48
+ parseMarkdown: {
49
+ match: ({ type }) => type === 'code',
50
+ runner: (state, node, type) => {
51
+ const language = node.lang as string
52
+ const value = node.value as string
53
+ state.openNode(type, { language })
54
+ if (value)
55
+ state.addText(value)
56
+
57
+ state.closeNode()
58
+ },
59
+ },
60
+ toMarkdown: {
61
+ match: node => node.type.name === 'code_block',
62
+ runner: (state, node) => {
63
+ state.addNode('code', undefined, node.content.firstChild?.text || '', {
64
+ lang: node.attrs.language,
65
+ })
66
+ },
67
+ },
68
+ }
69
+ })
70
+
71
+ export const createCodeBlockInputRule = $inputRule(() => textblockTypeInputRule(/^```(?<language>[a-z]*)?[\s\n]$/, codeBlockSchema.type(), match => ({
72
+ language: match.groups?.language ?? '',
73
+ })))
74
+
75
+ export const createCodeBlockCommand = $command('CreateCodeBlock', () => (language = '') => setBlockType(codeBlockSchema.type(), { language }))
76
+ export const updateCodeBlockLanguageCommand = $command('UpdateCodeBlockLanguage', () => ({ pos, language }: { pos: number; language: string } = { pos: -1, language: '' }) => (state, dispatch) => {
77
+ if (pos >= 0) {
78
+ dispatch?.(state.tr.setNodeAttribute(pos, 'language', language))
79
+ return true
80
+ }
81
+
82
+ return false
83
+ })
84
+
85
+ export const codeBlockKeymap = $useKeymap('codeBlockKeymap', {
86
+ CreateCodeBlock: {
87
+ shortcuts: 'Mod-Alt-c',
88
+ command: (ctx) => {
89
+ const commands = ctx.get(commandsCtx)
90
+ return () => commands.call(createCodeBlockCommand.key)
91
+ },
92
+ },
93
+ })
package/src/node/doc.ts CHANGED
@@ -1,24 +1,19 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
- import { createNode } from '@milkdown/utils'
2
+ import { $node } from '@milkdown/utils'
3
3
 
4
- export const doc = createNode(() => {
5
- return {
6
- id: 'doc',
7
- schema: () => ({
8
- content: 'block+',
9
- parseMarkdown: {
10
- match: ({ type }) => type === 'root',
11
- runner: (state, node, type) => {
12
- state.injectRoot(node, type)
13
- },
14
- },
15
- toMarkdown: {
16
- match: node => node.type.name === 'doc',
17
- runner: (state, node) => {
18
- state.openNode('root')
19
- state.next(node.content)
20
- },
21
- },
22
- }),
23
- }
24
- })
4
+ export const docSchema = $node('doc', () => ({
5
+ content: 'block+',
6
+ parseMarkdown: {
7
+ match: ({ type }) => type === 'root',
8
+ runner: (state, node, type) => {
9
+ state.injectRoot(node, type)
10
+ },
11
+ },
12
+ toMarkdown: {
13
+ match: node => node.type.name === 'doc',
14
+ runner: (state, node) => {
15
+ state.openNode('root')
16
+ state.next(node.content)
17
+ },
18
+ },
19
+ }))
@@ -1,125 +1,68 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
- import { createCmd, createCmdKey } from '@milkdown/core'
3
- import { Plugin, PluginKey, Selection } from '@milkdown/prose/state'
4
- import { AddMarkStep, ReplaceStep } from '@milkdown/prose/transform'
5
- import { createNode, createShortcut } from '@milkdown/utils'
2
+ import { commandsCtx } from '@milkdown/core'
3
+ import { Selection } from '@milkdown/prose/state'
4
+ import { $command, $nodeAttr, $nodeSchema, $useKeymap } from '@milkdown/utils'
6
5
 
7
- import { SupportedKeys } from '../supported-keys'
8
-
9
- type Keys = SupportedKeys['HardBreak']
10
-
11
- export const InsertHardbreak = createCmdKey('InsertHardbreak')
12
-
13
- export const HardbreakFilterPluginKey = new PluginKey('MILKDOWN_HARDBREAK_FILTER')
14
-
15
- export const hardbreak = createNode<
16
- Keys,
17
- {
18
- notIn: string[]
19
- }
20
- >((utils, options) => {
21
- const notIn = options?.notIn ?? ['table', 'fence']
6
+ export const hardbreakAttr = $nodeAttr('hardbreak', (node) => {
22
7
  return {
23
- id: 'hardbreak',
24
- schema: () => ({
25
- inline: true,
26
- group: 'inline',
27
- selectable: false,
28
- parseDOM: [{ tag: 'br' }],
29
- toDOM: node => ['br', { class: utils.getClassName(node.attrs, 'hardbreak') }],
30
- parseMarkdown: {
31
- match: ({ type }) => type === 'break',
32
- runner: (state, _, type) => {
33
- state.addNode(type)
34
- },
35
- },
36
- toMarkdown: {
37
- match: node => node.type.name === 'hardbreak',
38
- runner: (state) => {
39
- state.addNode('break')
40
- },
41
- },
42
- }),
43
- commands: type => [
44
- createCmd(InsertHardbreak, () => (state, dispatch) => {
45
- const { selection, tr } = state
46
- if (selection.empty) {
47
- // Transform two successive hardbreak into a new line
48
- const node = selection.$from.node()
49
- if (node.childCount > 0 && node.lastChild?.type.name === 'hardbreak') {
50
- dispatch?.(
51
- tr
52
- .replaceRangeWith(selection.to - 1, selection.to, state.schema.node('paragraph'))
53
- .setSelection(Selection.near(tr.doc.resolve(selection.to)))
54
- .scrollIntoView(),
55
- )
56
- return true
57
- }
58
- }
59
- dispatch?.(tr.setMeta('hardbreak', true).replaceSelectionWith(type.create()).scrollIntoView())
60
- return true
61
- }),
62
- ],
63
- shortcuts: {
64
- [SupportedKeys.HardBreak]: createShortcut(InsertHardbreak, 'Shift-Enter'),
65
- },
66
- prosePlugins: type => [
67
- new Plugin({
68
- key: HardbreakFilterPluginKey,
69
- filterTransaction: (tr, state) => {
70
- const isInsertHr = tr.getMeta('hardbreak')
71
- const [step] = tr.steps
72
- if (isInsertHr && step) {
73
- const { from } = step as unknown as { from: number }
74
- const $from = state.doc.resolve(from)
75
- let curDepth = $from.depth
76
- let canApply = true
77
- while (curDepth > 0) {
78
- if (notIn.includes($from.node(curDepth).type.name))
79
- canApply = false
80
-
81
- curDepth--
82
- }
83
- return canApply
84
- }
85
- return true
86
- },
87
- }),
88
- new Plugin({
89
- key: new PluginKey('MILKDOWN_HARDBREAK_MARKS'),
90
- appendTransaction: (trs, _oldState, newState) => {
91
- if (!trs.length)
92
- return
93
- const [tr] = trs
94
- if (!tr)
95
- return
96
-
97
- const [step] = tr.steps
98
-
99
- const isInsertHr = tr.getMeta('hardbreak')
100
- if (isInsertHr) {
101
- if (!(step instanceof ReplaceStep))
102
- return
103
-
104
- const { from } = step as unknown as { from: number }
105
- return newState.tr.setNodeMarkup(from, type, undefined, [])
106
- }
8
+ 'data-is-inline': node.attrs.isInline,
9
+ }
10
+ })
107
11
 
108
- const isAddMarkStep = step instanceof AddMarkStep
109
- if (isAddMarkStep) {
110
- let _tr = newState.tr
111
- const { from, to } = step as unknown as { from: number; to: number }
112
- newState.doc.nodesBetween(from, to, (node, pos) => {
113
- if (node.type === type)
114
- _tr = _tr.setNodeMarkup(pos, type, undefined, [])
115
- })
12
+ export const hardbreakSchema = $nodeSchema('hardbreak', ctx => ({
13
+ inline: true,
14
+ group: 'inline',
15
+ attrs: {
16
+ isInline: {
17
+ default: false,
18
+ },
19
+ },
20
+ selectable: false,
21
+ parseDOM: [{ tag: 'br' }],
22
+ toDOM: node => ['br', ctx.get(hardbreakAttr.key)(node)],
23
+ parseMarkdown: {
24
+ match: ({ type }) => type === 'break',
25
+ runner: (state, node, type) => {
26
+ state.addNode(type, { isInline: Boolean(node.data?.isInline) })
27
+ },
28
+ },
29
+ toMarkdown: {
30
+ match: node => node.type.name === 'hardbreak',
31
+ runner: (state, node) => {
32
+ if (node.attrs.isInline)
33
+ state.addNode('text', undefined, '\n')
116
34
 
117
- return _tr
118
- }
35
+ else
36
+ state.addNode('break')
37
+ },
38
+ },
39
+ }))
119
40
 
120
- return undefined
121
- },
122
- }),
123
- ],
41
+ export const insertHardbreakCommand = $command('InsertHardbreak', () => () => (state, dispatch) => {
42
+ const { selection, tr } = state
43
+ if (selection.empty) {
44
+ // Transform two successive hardbreak into a new line
45
+ const node = selection.$from.node()
46
+ if (node.childCount > 0 && node.lastChild?.type.name === 'hardbreak') {
47
+ dispatch?.(
48
+ tr
49
+ .replaceRangeWith(selection.to - 1, selection.to, state.schema.node('paragraph'))
50
+ .setSelection(Selection.near(tr.doc.resolve(selection.to)))
51
+ .scrollIntoView(),
52
+ )
53
+ return true
54
+ }
124
55
  }
56
+ dispatch?.(tr.setMeta('hardbreak', true).replaceSelectionWith(hardbreakSchema.type().create()).scrollIntoView())
57
+ return true
58
+ })
59
+
60
+ export const hardbreakKeymap = $useKeymap('hardbreakKeymap', {
61
+ InsertHardbreak: {
62
+ shortcuts: 'Shift-Enter',
63
+ command: (ctx) => {
64
+ const commands = ctx.get(commandsCtx)
65
+ return () => commands.call(insertHardbreakCommand.key)
66
+ },
67
+ },
125
68
  })