@milkdown/preset-commonmark 6.5.4 → 7.0.0-next.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.
- package/lib/composed/commands.d.ts +3 -0
- package/lib/composed/commands.d.ts.map +1 -0
- package/lib/composed/index.d.ts +6 -0
- package/lib/composed/index.d.ts.map +1 -0
- package/lib/composed/inputrules.d.ts +3 -0
- package/lib/composed/inputrules.d.ts.map +1 -0
- package/lib/composed/keymap.d.ts +3 -0
- package/lib/composed/keymap.d.ts.map +1 -0
- package/lib/composed/plugins.d.ts +3 -0
- package/lib/composed/plugins.d.ts.map +1 -0
- package/lib/composed/schema.d.ts +3 -0
- package/lib/composed/schema.d.ts.map +1 -0
- package/lib/index.d.ts +4 -29
- package/lib/index.d.ts.map +1 -1
- package/lib/index.es.js +1099 -1386
- package/lib/index.es.js.map +1 -1
- package/lib/mark/emphasis.d.ts +5 -0
- package/lib/mark/emphasis.d.ts.map +1 -0
- package/lib/mark/index.d.ts +3 -4
- package/lib/mark/index.d.ts.map +1 -1
- package/lib/mark/inline-code.d.ts +5 -0
- package/lib/mark/inline-code.d.ts.map +1 -0
- package/lib/mark/link.d.ts +8 -10
- package/lib/mark/link.d.ts.map +1 -1
- package/lib/mark/strong.d.ts +4 -2
- package/lib/mark/strong.d.ts.map +1 -1
- package/lib/node/blockquote.d.ts +6 -2
- package/lib/node/blockquote.d.ts.map +1 -1
- package/lib/node/bullet-list.d.ts +5 -2
- package/lib/node/bullet-list.d.ts.map +1 -1
- package/lib/node/code-block.d.ts +10 -0
- package/lib/node/code-block.d.ts.map +1 -0
- package/lib/node/doc.d.ts +1 -1
- package/lib/node/doc.d.ts.map +1 -1
- package/lib/node/hardbreak.d.ts +4 -6
- package/lib/node/hardbreak.d.ts.map +1 -1
- package/lib/node/heading.d.ts +7 -12
- package/lib/node/heading.d.ts.map +1 -1
- package/lib/node/hr.d.ts +4 -2
- package/lib/node/hr.d.ts.map +1 -1
- package/lib/node/image.d.ts +10 -11
- package/lib/node/image.d.ts.map +1 -1
- package/lib/node/index.d.ts +6 -8
- package/lib/node/index.d.ts.map +1 -1
- package/lib/node/list-item.d.ts +6 -7
- package/lib/node/list-item.d.ts.map +1 -1
- package/lib/node/ordered-list.d.ts +5 -2
- package/lib/node/ordered-list.d.ts.map +1 -1
- package/lib/node/paragraph.d.ts +4 -2
- package/lib/node/paragraph.d.ts.map +1 -1
- package/lib/node/text.d.ts +1 -1
- package/lib/node/text.d.ts.map +1 -1
- package/lib/plugin/hardbreak-clear-mark-plugin.d.ts +2 -0
- package/lib/plugin/hardbreak-clear-mark-plugin.d.ts.map +1 -0
- package/lib/plugin/hardbreak-filter-plugin.d.ts +3 -0
- package/lib/plugin/hardbreak-filter-plugin.d.ts.map +1 -0
- package/lib/plugin/index.d.ts +9 -3
- package/lib/plugin/index.d.ts.map +1 -1
- package/lib/plugin/inline-nodes-cursor-plugin.d.ts +2 -0
- package/lib/plugin/inline-nodes-cursor-plugin.d.ts.map +1 -0
- package/lib/plugin/{inline-sync → inline-sync-plugin}/config.d.ts +2 -2
- package/lib/plugin/inline-sync-plugin/config.d.ts.map +1 -0
- package/lib/plugin/{inline-sync → inline-sync-plugin}/context.d.ts +1 -2
- package/lib/plugin/inline-sync-plugin/context.d.ts.map +1 -0
- package/lib/plugin/inline-sync-plugin/index.d.ts +3 -0
- package/lib/plugin/inline-sync-plugin/index.d.ts.map +1 -0
- package/lib/plugin/inline-sync-plugin/inline-sync-plugin.d.ts +2 -0
- package/lib/plugin/inline-sync-plugin/inline-sync-plugin.d.ts.map +1 -0
- package/lib/plugin/{inline-sync → inline-sync-plugin}/regexp.d.ts +0 -0
- package/lib/plugin/inline-sync-plugin/regexp.d.ts.map +1 -0
- package/lib/plugin/{inline-sync → inline-sync-plugin}/replacer.d.ts +1 -1
- package/lib/plugin/inline-sync-plugin/replacer.d.ts.map +1 -0
- package/lib/plugin/{inline-sync → inline-sync-plugin}/utils.d.ts +0 -0
- package/lib/plugin/inline-sync-plugin/utils.d.ts.map +1 -0
- package/lib/plugin/remark-add-order-in-list-plugin.d.ts +2 -0
- package/lib/plugin/remark-add-order-in-list-plugin.d.ts.map +1 -0
- package/lib/plugin/remark-inline-link-plugin.d.ts +2 -0
- package/lib/plugin/remark-inline-link-plugin.d.ts.map +1 -0
- package/lib/plugin/remark-line-break.d.ts +2 -0
- package/lib/plugin/remark-line-break.d.ts.map +1 -0
- package/lib/plugin/sync-heading-id-plugin.d.ts +2 -0
- package/lib/plugin/sync-heading-id-plugin.d.ts.map +1 -0
- package/lib/plugin/sync-list-order-plugin.d.ts +2 -0
- package/lib/plugin/sync-list-order-plugin.d.ts.map +1 -0
- package/package.json +9 -7
- package/src/composed/commands.ts +31 -0
- package/src/composed/index.ts +6 -0
- package/src/composed/inputrules.ts +13 -0
- package/src/composed/keymap.ts +20 -0
- package/src/composed/plugins.ts +23 -0
- package/src/composed/schema.ts +55 -0
- package/src/index.ts +6 -52
- package/src/mark/emphasis.ts +47 -0
- package/src/mark/index.ts +3 -10
- package/src/mark/inline-code.ts +70 -0
- package/src/mark/link.ts +96 -247
- package/src/mark/strong.ts +41 -36
- package/src/node/blockquote.ts +39 -33
- package/src/node/bullet-list.ts +62 -55
- package/src/node/code-block.ts +103 -0
- package/src/node/doc.ts +18 -22
- package/src/node/hardbreak.ts +68 -117
- package/src/node/heading.ts +175 -284
- package/src/node/hr.ts +57 -57
- package/src/node/image.ts +113 -209
- package/src/node/index.ts +6 -35
- package/src/node/list-item.ts +125 -141
- package/src/node/ordered-list.ts +70 -65
- package/src/node/paragraph.ts +54 -50
- package/src/node/text.ts +14 -16
- package/src/plugin/hardbreak-clear-mark-plugin.ts +45 -0
- package/src/plugin/hardbreak-filter-plugin.ts +33 -0
- package/src/plugin/index.ts +12 -14
- package/src/plugin/{inline-nodes-cursor.ts → inline-nodes-cursor-plugin.ts} +5 -8
- package/src/plugin/{inline-sync → inline-sync-plugin}/config.ts +18 -3
- package/src/plugin/{inline-sync → inline-sync-plugin}/context.ts +4 -6
- package/src/plugin/inline-sync-plugin/index.ts +4 -0
- package/src/plugin/{inline-sync/index.ts → inline-sync-plugin/inline-sync-plugin.ts} +14 -11
- package/src/plugin/{inline-sync → inline-sync-plugin}/regexp.ts +0 -0
- package/src/plugin/{inline-sync → inline-sync-plugin}/replacer.ts +3 -3
- package/src/plugin/{inline-sync → inline-sync-plugin}/utils.ts +0 -0
- package/src/plugin/remark-add-order-in-list-plugin.ts +16 -0
- package/src/plugin/remark-inline-link-plugin.ts +6 -0
- package/src/plugin/remark-line-break.ts +44 -0
- package/src/plugin/sync-heading-id-plugin.ts +55 -0
- package/src/plugin/sync-list-order-plugin.ts +57 -0
- package/lib/mark/code-inline.d.ts +0 -3
- package/lib/mark/code-inline.d.ts.map +0 -1
- package/lib/mark/em.d.ts +0 -3
- package/lib/mark/em.d.ts.map +0 -1
- package/lib/node/code-fence.d.ts +0 -7
- package/lib/node/code-fence.d.ts.map +0 -1
- package/lib/plugin/add-order-in-list.d.ts +0 -3
- package/lib/plugin/add-order-in-list.d.ts.map +0 -1
- package/lib/plugin/filter-html.d.ts +0 -3
- package/lib/plugin/filter-html.d.ts.map +0 -1
- package/lib/plugin/inline-nodes-cursor.d.ts +0 -7
- package/lib/plugin/inline-nodes-cursor.d.ts.map +0 -1
- package/lib/plugin/inline-sync/config.d.ts.map +0 -1
- package/lib/plugin/inline-sync/context.d.ts.map +0 -1
- package/lib/plugin/inline-sync/index.d.ts +0 -6
- package/lib/plugin/inline-sync/index.d.ts.map +0 -1
- package/lib/plugin/inline-sync/regexp.d.ts.map +0 -1
- package/lib/plugin/inline-sync/replacer.d.ts.map +0 -1
- package/lib/plugin/inline-sync/utils.d.ts.map +0 -1
- package/lib/supported-keys.d.ts +0 -23
- package/lib/supported-keys.d.ts.map +0 -1
- package/src/mark/code-inline.ts +0 -66
- package/src/mark/em.ts +0 -42
- package/src/node/code-fence.ts +0 -245
- package/src/plugin/add-order-in-list.ts +0 -19
- package/src/plugin/filter-html.ts +0 -43
- package/src/supported-keys.ts +0 -25
- package/src/types.d.ts +0 -5
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import type { MilkdownPlugin } from '@milkdown/ctx'
|
|
3
|
+
import { createCodeBlockInputRule, insertHrInputRule, wrapInBlockquoteInputRule, wrapInBulletListInputRule, wrapInHeadingInputRule, wrapInOrderedListInputRule } from '../node'
|
|
4
|
+
|
|
5
|
+
/// @internal
|
|
6
|
+
export const inputrules: MilkdownPlugin[] = [
|
|
7
|
+
wrapInBlockquoteInputRule,
|
|
8
|
+
wrapInBulletListInputRule,
|
|
9
|
+
wrapInOrderedListInputRule,
|
|
10
|
+
createCodeBlockInputRule,
|
|
11
|
+
insertHrInputRule,
|
|
12
|
+
wrapInHeadingInputRule,
|
|
13
|
+
].flat()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import type { MilkdownPlugin } from '@milkdown/ctx'
|
|
3
|
+
import { emphasisKeymap, inlineCodeKeymap, strongKeymap } from '../mark'
|
|
4
|
+
import { blockquoteKeymap, bulletListKeymap, codeBlockKeymap, hardbreakKeymap, headingKeymap, listItemKeymap, orderedListKeymap, paragraphKeymap } from '../node'
|
|
5
|
+
|
|
6
|
+
/// @internal
|
|
7
|
+
export const keymap: MilkdownPlugin[] = [
|
|
8
|
+
blockquoteKeymap,
|
|
9
|
+
codeBlockKeymap,
|
|
10
|
+
hardbreakKeymap,
|
|
11
|
+
headingKeymap,
|
|
12
|
+
listItemKeymap,
|
|
13
|
+
orderedListKeymap,
|
|
14
|
+
bulletListKeymap,
|
|
15
|
+
paragraphKeymap,
|
|
16
|
+
|
|
17
|
+
emphasisKeymap,
|
|
18
|
+
inlineCodeKeymap,
|
|
19
|
+
strongKeymap,
|
|
20
|
+
].flat()
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
|
|
3
|
+
import type { MilkdownPlugin } from '@milkdown/ctx'
|
|
4
|
+
import { hardbreakClearMarkPlugin, hardbreakFilterNodes, hardbreakFilterPlugin, inlineNodesCursorPlugin, inlineSyncConfig, inlineSyncPlugin, remarkAddOrderInListPlugin, remarkInlineLinkPlugin, remarkLineBreak, syncHeadingIdPlugin, syncListOrderPlugin } from '../plugin'
|
|
5
|
+
|
|
6
|
+
/// @internal
|
|
7
|
+
export const plugins: MilkdownPlugin[] = [
|
|
8
|
+
inlineSyncConfig,
|
|
9
|
+
inlineSyncPlugin,
|
|
10
|
+
|
|
11
|
+
hardbreakClearMarkPlugin,
|
|
12
|
+
hardbreakFilterNodes,
|
|
13
|
+
hardbreakFilterPlugin,
|
|
14
|
+
|
|
15
|
+
inlineNodesCursorPlugin,
|
|
16
|
+
|
|
17
|
+
remarkAddOrderInListPlugin,
|
|
18
|
+
remarkInlineLinkPlugin,
|
|
19
|
+
remarkLineBreak,
|
|
20
|
+
|
|
21
|
+
syncHeadingIdPlugin,
|
|
22
|
+
syncListOrderPlugin,
|
|
23
|
+
]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
|
|
3
|
+
import type { MilkdownPlugin } from '@milkdown/ctx'
|
|
4
|
+
import { emphasisAttr, emphasisSchema, inlineCodeAttr, inlineCodeSchema, linkAttr, linkSchema, strongAttr, strongSchema } from '../mark'
|
|
5
|
+
import { blockquoteAttr, blockquoteSchema, bulletListAttr, bulletListSchema, codeBlockAttr, codeBlockSchema, docSchema, hardbreakAttr, hardbreakSchema, headingAttr, headingIdGenerator, headingSchema, hrAttr, hrSchema, imageAttr, imageSchema, listItemAttr, listItemSchema, orderedListAttr, orderedListSchema, paragraphAttr, paragraphSchema, textSchema } from '../node'
|
|
6
|
+
|
|
7
|
+
/// @internal
|
|
8
|
+
export const schema: MilkdownPlugin[] = [
|
|
9
|
+
docSchema,
|
|
10
|
+
|
|
11
|
+
paragraphAttr,
|
|
12
|
+
paragraphSchema,
|
|
13
|
+
|
|
14
|
+
headingIdGenerator,
|
|
15
|
+
headingAttr,
|
|
16
|
+
headingSchema,
|
|
17
|
+
|
|
18
|
+
hardbreakAttr,
|
|
19
|
+
hardbreakSchema,
|
|
20
|
+
|
|
21
|
+
blockquoteAttr,
|
|
22
|
+
blockquoteSchema,
|
|
23
|
+
|
|
24
|
+
codeBlockAttr,
|
|
25
|
+
codeBlockSchema,
|
|
26
|
+
|
|
27
|
+
hrAttr,
|
|
28
|
+
hrSchema,
|
|
29
|
+
|
|
30
|
+
imageAttr,
|
|
31
|
+
imageSchema,
|
|
32
|
+
|
|
33
|
+
bulletListAttr,
|
|
34
|
+
bulletListSchema,
|
|
35
|
+
|
|
36
|
+
orderedListAttr,
|
|
37
|
+
orderedListSchema,
|
|
38
|
+
|
|
39
|
+
listItemAttr,
|
|
40
|
+
listItemSchema,
|
|
41
|
+
|
|
42
|
+
emphasisAttr,
|
|
43
|
+
emphasisSchema,
|
|
44
|
+
|
|
45
|
+
strongAttr,
|
|
46
|
+
strongSchema,
|
|
47
|
+
|
|
48
|
+
inlineCodeAttr,
|
|
49
|
+
inlineCodeSchema,
|
|
50
|
+
|
|
51
|
+
linkAttr,
|
|
52
|
+
linkSchema,
|
|
53
|
+
|
|
54
|
+
textSchema,
|
|
55
|
+
].flat()
|
package/src/index.ts
CHANGED
|
@@ -1,57 +1,11 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
-
import { AtomList } from '@milkdown/utils'
|
|
3
2
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
InsertHardbreak,
|
|
7
|
-
InsertHr,
|
|
8
|
-
InsertImage,
|
|
9
|
-
LiftListItem,
|
|
10
|
-
ModifyImage,
|
|
11
|
-
SinkListItem,
|
|
12
|
-
SplitListItem,
|
|
13
|
-
TurnIntoCodeFence,
|
|
14
|
-
TurnIntoHeading,
|
|
15
|
-
TurnIntoText,
|
|
16
|
-
WrapInBlockquote,
|
|
17
|
-
WrapInBulletList,
|
|
18
|
-
WrapInOrderedList,
|
|
19
|
-
nodes,
|
|
20
|
-
} from './node'
|
|
21
|
-
import { commonmarkPlugins } from './plugin'
|
|
3
|
+
import { commands, inputrules, keymap, plugins, schema } from './composed'
|
|
22
4
|
|
|
23
|
-
export * from './mark'
|
|
24
5
|
export * from './node'
|
|
25
|
-
export
|
|
26
|
-
export * from './
|
|
27
|
-
|
|
28
|
-
export const commonmarkNodes = AtomList.create([...nodes, ...marks])
|
|
29
|
-
export { commonmarkPlugins }
|
|
30
|
-
export const commonmark = AtomList.create([...commonmarkPlugins, ...commonmarkNodes])
|
|
31
|
-
|
|
32
|
-
export const commands = {
|
|
33
|
-
ToggleInlineCode,
|
|
34
|
-
ToggleItalic,
|
|
35
|
-
ToggleLink,
|
|
36
|
-
ToggleBold,
|
|
37
|
-
|
|
38
|
-
ModifyLink,
|
|
39
|
-
ModifyImage,
|
|
40
|
-
|
|
41
|
-
WrapInBlockquote,
|
|
42
|
-
WrapInBulletList,
|
|
43
|
-
WrapInOrderedList,
|
|
44
|
-
|
|
45
|
-
TurnIntoCodeFence,
|
|
46
|
-
TurnIntoHeading,
|
|
47
|
-
TurnIntoText,
|
|
48
|
-
|
|
49
|
-
InsertHardbreak,
|
|
50
|
-
InsertHr,
|
|
51
|
-
InsertImage,
|
|
6
|
+
export * from './mark'
|
|
7
|
+
export * from './plugin'
|
|
8
|
+
export * from './composed'
|
|
52
9
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
LiftListItem,
|
|
56
|
-
} as const
|
|
57
|
-
export type Commands = typeof commands
|
|
10
|
+
/// The commonmark preset, includes all the plugins.
|
|
11
|
+
export const commonmark = [schema, inputrules, commands, keymap, plugins].flat()
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import { commandsCtx } from '@milkdown/core'
|
|
3
|
+
import { toggleMark } from '@milkdown/prose/commands'
|
|
4
|
+
import { $command, $markAttr, $markSchema, $useKeymap } from '@milkdown/utils'
|
|
5
|
+
|
|
6
|
+
/// HTML attributes for the emphasis mark.
|
|
7
|
+
export const emphasisAttr = $markAttr('emphasis')
|
|
8
|
+
|
|
9
|
+
/// Emphasis mark schema.
|
|
10
|
+
export const emphasisSchema = $markSchema('emphasis', ctx => ({
|
|
11
|
+
inclusive: false,
|
|
12
|
+
parseDOM: [
|
|
13
|
+
{ tag: 'i' },
|
|
14
|
+
{ tag: 'em' },
|
|
15
|
+
{ style: 'font-style', getAttrs: value => (value === 'italic') as false },
|
|
16
|
+
],
|
|
17
|
+
toDOM: mark => ['em', ctx.get(emphasisAttr.key)(mark)],
|
|
18
|
+
parseMarkdown: {
|
|
19
|
+
match: node => node.type === 'emphasis',
|
|
20
|
+
runner: (state, node, markType) => {
|
|
21
|
+
state.openMark(markType)
|
|
22
|
+
state.next(node.children)
|
|
23
|
+
state.closeMark(markType)
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
toMarkdown: {
|
|
27
|
+
match: mark => mark.type.name === 'emphasis',
|
|
28
|
+
runner: (state, mark) => {
|
|
29
|
+
state.withMark(mark, 'emphasis')
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
}))
|
|
33
|
+
|
|
34
|
+
/// A command to toggle the emphasis mark.
|
|
35
|
+
export const toggleEmphasisCommand = $command('ToggleEmphasis', () => () => toggleMark(emphasisSchema.type()))
|
|
36
|
+
|
|
37
|
+
/// Keymap for the emphasis mark.
|
|
38
|
+
/// - `Mod-i` - Toggle the emphasis mark.
|
|
39
|
+
export const emphasisKeymap = $useKeymap('emphasisKeymap', {
|
|
40
|
+
ToggleEmphasis: {
|
|
41
|
+
shortcuts: 'Mod-i',
|
|
42
|
+
command: (ctx) => {
|
|
43
|
+
const commands = ctx.get(commandsCtx)
|
|
44
|
+
return () => commands.call(toggleEmphasisCommand.key)
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
})
|
package/src/mark/index.ts
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
-
|
|
3
|
-
import { em } from './em'
|
|
4
|
-
import { link } from './link'
|
|
5
|
-
import { strong } from './strong'
|
|
6
|
-
|
|
7
|
-
export const marks = [codeInline(), em(), strong(), link()]
|
|
8
|
-
|
|
9
|
-
export * from './code-inline'
|
|
10
|
-
export * from './em'
|
|
11
|
-
export * from './link'
|
|
2
|
+
export * from './emphasis'
|
|
12
3
|
export * from './strong'
|
|
4
|
+
export * from './inline-code'
|
|
5
|
+
export * from './link'
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import { commandsCtx } from '@milkdown/core'
|
|
3
|
+
import type { MarkType } from '@milkdown/prose/model'
|
|
4
|
+
import { $command, $markAttr, $markSchema, $useKeymap } from '@milkdown/utils'
|
|
5
|
+
|
|
6
|
+
/// HTML attributes for the inlineCode mark.
|
|
7
|
+
export const inlineCodeAttr = $markAttr('inlineCode')
|
|
8
|
+
|
|
9
|
+
/// InlineCode mark schema.
|
|
10
|
+
export const inlineCodeSchema = $markSchema('inlineCode', ctx => ({
|
|
11
|
+
priority: 100,
|
|
12
|
+
code: true,
|
|
13
|
+
inclusive: false,
|
|
14
|
+
parseDOM: [{ tag: 'code' }],
|
|
15
|
+
toDOM: mark => ['code', ctx.get(inlineCodeAttr.key)(mark)],
|
|
16
|
+
parseMarkdown: {
|
|
17
|
+
match: node => node.type === 'inlineCode',
|
|
18
|
+
runner: (state, node, markType) => {
|
|
19
|
+
state.openMark(markType)
|
|
20
|
+
state.addText(node.value as string)
|
|
21
|
+
state.closeMark(markType)
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
toMarkdown: {
|
|
25
|
+
match: mark => mark.type.name === 'inlineCode',
|
|
26
|
+
runner: (state, mark, node) => {
|
|
27
|
+
state.withMark(mark, 'inlineCode', node.text || '')
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
}))
|
|
31
|
+
|
|
32
|
+
/// A command to toggle the inlineCode mark.
|
|
33
|
+
export const toggleInlineCodeCommand = $command('ToggleInlineCode', () => () => (state, dispatch) => {
|
|
34
|
+
const { selection, tr } = state
|
|
35
|
+
if (selection.empty)
|
|
36
|
+
return false
|
|
37
|
+
const { from, to } = selection
|
|
38
|
+
|
|
39
|
+
const has = state.doc.rangeHasMark(from, to, inlineCodeSchema.type())
|
|
40
|
+
// remove exists inlineCode mark if have
|
|
41
|
+
if (has) {
|
|
42
|
+
dispatch?.(tr.removeMark(from, to, inlineCodeSchema.type()))
|
|
43
|
+
return true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const restMarksName = Object.keys(state.schema.marks).filter(x => x !== inlineCodeSchema.type.name)
|
|
47
|
+
|
|
48
|
+
// remove other marks
|
|
49
|
+
restMarksName
|
|
50
|
+
.map(name => state.schema.marks[name] as MarkType)
|
|
51
|
+
.forEach((t) => {
|
|
52
|
+
tr.removeMark(from, to, t)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// add inlineCode mark
|
|
56
|
+
dispatch?.(tr.addMark(from, to, inlineCodeSchema.type().create()))
|
|
57
|
+
return true
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
/// Keymap for the inlineCode mark.
|
|
61
|
+
/// - `Mod-e` - Toggle the inlineCode mark.
|
|
62
|
+
export const inlineCodeKeymap = $useKeymap('inlineCodeKeymap', {
|
|
63
|
+
ToggleInlineCode: {
|
|
64
|
+
shortcuts: 'Mod-e',
|
|
65
|
+
command: (ctx) => {
|
|
66
|
+
const commands = ctx.get(commandsCtx)
|
|
67
|
+
return () => commands.call(toggleInlineCodeCommand.key)
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
})
|
package/src/mark/link.ts
CHANGED
|
@@ -1,253 +1,102 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
-
import
|
|
3
|
-
import { commandsCtx, createCmd, createCmdKey } from '@milkdown/core'
|
|
4
|
-
import { expectDomTypeError, missingRootElement } from '@milkdown/exception'
|
|
5
|
-
import { calculateTextPosition } from '@milkdown/prose'
|
|
2
|
+
import { expectDomTypeError } from '@milkdown/exception'
|
|
6
3
|
import { toggleMark } from '@milkdown/prose/commands'
|
|
7
4
|
import type { Node as ProseNode } from '@milkdown/prose/model'
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
attrs: {
|
|
29
|
-
href: {},
|
|
30
|
-
title: { default: null },
|
|
31
|
-
},
|
|
32
|
-
parseDOM: [
|
|
33
|
-
{
|
|
34
|
-
tag: 'a[href]',
|
|
35
|
-
getAttrs: (dom) => {
|
|
36
|
-
if (!(dom instanceof HTMLElement))
|
|
37
|
-
throw expectDomTypeError(dom)
|
|
38
|
-
|
|
39
|
-
return { href: dom.getAttribute('href'), title: dom.getAttribute('title') }
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
],
|
|
43
|
-
toDOM: mark => ['a', { ...mark.attrs, class: utils.getClassName(mark.attrs, id) }],
|
|
44
|
-
parseMarkdown: {
|
|
45
|
-
match: node => node.type === 'link',
|
|
46
|
-
runner: (state, node, markType) => {
|
|
47
|
-
const url = node.url as string
|
|
48
|
-
const title = node.title as string
|
|
49
|
-
state.openMark(markType, { href: url, title })
|
|
50
|
-
state.next(node.children)
|
|
51
|
-
state.closeMark(markType)
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
toMarkdown: {
|
|
55
|
-
match: mark => mark.type.name === id,
|
|
56
|
-
runner: (state, mark) => {
|
|
57
|
-
state.withMark(mark, 'link', undefined, {
|
|
58
|
-
title: mark.attrs.title,
|
|
59
|
-
url: mark.attrs.href,
|
|
60
|
-
})
|
|
61
|
-
},
|
|
5
|
+
import { TextSelection } from '@milkdown/prose/state'
|
|
6
|
+
import { $command, $markAttr, $markSchema } from '@milkdown/utils'
|
|
7
|
+
|
|
8
|
+
/// HTML attributes for the link mark.
|
|
9
|
+
export const linkAttr = $markAttr('link')
|
|
10
|
+
|
|
11
|
+
/// Link mark schema.
|
|
12
|
+
export const linkSchema = $markSchema('link', ctx => ({
|
|
13
|
+
attrs: {
|
|
14
|
+
href: {},
|
|
15
|
+
title: { default: null },
|
|
16
|
+
},
|
|
17
|
+
parseDOM: [
|
|
18
|
+
{
|
|
19
|
+
tag: 'a[href]',
|
|
20
|
+
getAttrs: (dom) => {
|
|
21
|
+
if (!(dom instanceof HTMLElement))
|
|
22
|
+
throw expectDomTypeError(dom)
|
|
23
|
+
|
|
24
|
+
return { href: dom.getAttribute('href'), title: dom.getAttribute('title') }
|
|
62
25
|
},
|
|
63
|
-
}),
|
|
64
|
-
commands: markType => [
|
|
65
|
-
createCmd(ToggleLink, (href = '') => toggleMark(markType, { href })),
|
|
66
|
-
createCmd(ModifyLink, (href = '') => (state, dispatch) => {
|
|
67
|
-
if (!dispatch)
|
|
68
|
-
return false
|
|
69
|
-
|
|
70
|
-
const { marks } = state.schema
|
|
71
|
-
|
|
72
|
-
let node: ProseNode | undefined
|
|
73
|
-
let pos = -1
|
|
74
|
-
const { selection } = state
|
|
75
|
-
const { from, to } = selection
|
|
76
|
-
state.doc.nodesBetween(from, from === to ? to + 1 : to, (n, p) => {
|
|
77
|
-
if (marks.link?.isInSet(n.marks)) {
|
|
78
|
-
node = n
|
|
79
|
-
pos = p
|
|
80
|
-
return false
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return undefined
|
|
84
|
-
})
|
|
85
|
-
if (!node)
|
|
86
|
-
return false
|
|
87
|
-
|
|
88
|
-
const mark = node.marks.find(({ type }) => type === markType)
|
|
89
|
-
if (!mark)
|
|
90
|
-
return false
|
|
91
|
-
|
|
92
|
-
const start = pos
|
|
93
|
-
const end = pos + node.nodeSize
|
|
94
|
-
const { tr } = state
|
|
95
|
-
const linkMark = marks.link?.create({ ...mark.attrs, href })
|
|
96
|
-
if (!linkMark)
|
|
97
|
-
return false
|
|
98
|
-
dispatch(
|
|
99
|
-
tr
|
|
100
|
-
.removeMark(start, end, mark)
|
|
101
|
-
.addMark(start, end, linkMark)
|
|
102
|
-
.setSelection(new TextSelection(tr.selection.$anchor))
|
|
103
|
-
.scrollIntoView(),
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
return true
|
|
107
|
-
}),
|
|
108
|
-
],
|
|
109
|
-
prosePlugins: (type, ctx) => {
|
|
110
|
-
let renderOnTop = false
|
|
111
|
-
return [
|
|
112
|
-
new Plugin({
|
|
113
|
-
key,
|
|
114
|
-
view: (editorView) => {
|
|
115
|
-
const inputChipRenderer = utils.themeManager.get<ThemeInputChipType>('input-chip', {
|
|
116
|
-
placeholder: options?.input?.placeholder ?? 'Input Web Link',
|
|
117
|
-
buttonText: options?.input?.buttonText,
|
|
118
|
-
onUpdate: (value) => {
|
|
119
|
-
ctx.get(commandsCtx).call(ModifyLink, value)
|
|
120
|
-
},
|
|
121
|
-
calculatePosition: (view, input) => {
|
|
122
|
-
calculateTextPosition(view, input, (start, end, target, parent) => {
|
|
123
|
-
const $editor = view.dom.parentElement
|
|
124
|
-
if (!$editor)
|
|
125
|
-
throw missingRootElement()
|
|
126
|
-
|
|
127
|
-
const selectionWidth = end.left - start.left
|
|
128
|
-
let left = start.left - parent.left - (target.width - selectionWidth) / 2
|
|
129
|
-
let top = start.bottom - parent.top + 14 + $editor.scrollTop
|
|
130
|
-
|
|
131
|
-
if (renderOnTop)
|
|
132
|
-
top = start.top - parent.top - target.height - 14 + $editor.scrollTop
|
|
133
|
-
|
|
134
|
-
if (left < 0)
|
|
135
|
-
left = 0
|
|
136
|
-
|
|
137
|
-
const maxLeft = $editor.clientWidth - (target.width + 4)
|
|
138
|
-
if (left > maxLeft)
|
|
139
|
-
left = maxLeft
|
|
140
|
-
|
|
141
|
-
return [top, left]
|
|
142
|
-
})
|
|
143
|
-
},
|
|
144
|
-
})
|
|
145
|
-
if (!inputChipRenderer)
|
|
146
|
-
return {}
|
|
147
|
-
const shouldDisplay = (view: EditorView) => {
|
|
148
|
-
const { selection, doc } = view.state
|
|
149
|
-
const { from, to } = selection
|
|
150
|
-
|
|
151
|
-
if (!view.hasFocus())
|
|
152
|
-
return false
|
|
153
|
-
|
|
154
|
-
if (
|
|
155
|
-
selection instanceof TextSelection
|
|
156
|
-
&& to < doc.content.size
|
|
157
|
-
&& from < doc.content.size
|
|
158
|
-
&& doc.rangeHasMark(from, from === to ? to + 1 : to, type)
|
|
159
|
-
) {
|
|
160
|
-
let shouldDisplay = selection.empty
|
|
161
|
-
if (options?.input?.displayWhenSelected && !shouldDisplay) {
|
|
162
|
-
doc.nodesBetween(from, from === to ? to + 1 : to, (node, pos) => {
|
|
163
|
-
if (
|
|
164
|
-
node.marks.some(
|
|
165
|
-
mark =>
|
|
166
|
-
mark.type === type && from >= pos && to <= pos + node.nodeSize,
|
|
167
|
-
)
|
|
168
|
-
) {
|
|
169
|
-
shouldDisplay = true
|
|
170
|
-
return false
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return undefined
|
|
174
|
-
})
|
|
175
|
-
}
|
|
176
|
-
if (shouldDisplay) {
|
|
177
|
-
renderOnTop = false
|
|
178
|
-
return true
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (selection instanceof NodeSelection) {
|
|
183
|
-
const { node } = selection
|
|
184
|
-
if (
|
|
185
|
-
node.type.name === 'image'
|
|
186
|
-
&& node.marks.findIndex(mark => mark.type.name === id) > -1
|
|
187
|
-
) {
|
|
188
|
-
renderOnTop = true
|
|
189
|
-
return true
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return false
|
|
194
|
-
}
|
|
195
|
-
const getCurrentLink = (view: EditorView) => {
|
|
196
|
-
const { selection } = view.state
|
|
197
|
-
let node: ProseNode | undefined
|
|
198
|
-
const { from, to } = selection
|
|
199
|
-
view.state.doc.nodesBetween(from, from === to ? to + 1 : to, (n) => {
|
|
200
|
-
if (type.isInSet(n.marks)) {
|
|
201
|
-
node = n
|
|
202
|
-
return false
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return undefined
|
|
206
|
-
})
|
|
207
|
-
if (!node)
|
|
208
|
-
return
|
|
209
|
-
|
|
210
|
-
const mark = node.marks.find(m => m.type === type)
|
|
211
|
-
if (!mark)
|
|
212
|
-
return
|
|
213
|
-
|
|
214
|
-
const value = mark.attrs.href
|
|
215
|
-
return value
|
|
216
|
-
}
|
|
217
|
-
const renderByView = (view: EditorView) => {
|
|
218
|
-
if (!view.editable)
|
|
219
|
-
return
|
|
220
|
-
|
|
221
|
-
const display = shouldDisplay(view)
|
|
222
|
-
if (display) {
|
|
223
|
-
inputChipRenderer.show(view)
|
|
224
|
-
inputChipRenderer.update(getCurrentLink(view))
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
inputChipRenderer.hide()
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
inputChipRenderer.init(editorView)
|
|
231
|
-
renderByView(editorView)
|
|
232
|
-
|
|
233
|
-
return {
|
|
234
|
-
update: (view, prevState) => {
|
|
235
|
-
const isEqualSelection
|
|
236
|
-
= prevState?.doc.eq(view.state.doc) && prevState.selection.eq(view.state.selection)
|
|
237
|
-
if (isEqualSelection)
|
|
238
|
-
return
|
|
239
|
-
|
|
240
|
-
requestAnimationFrame(() => {
|
|
241
|
-
renderByView(view)
|
|
242
|
-
})
|
|
243
|
-
},
|
|
244
|
-
destroy: () => {
|
|
245
|
-
inputChipRenderer.destroy()
|
|
246
|
-
},
|
|
247
|
-
}
|
|
248
|
-
},
|
|
249
|
-
}),
|
|
250
|
-
]
|
|
251
26
|
},
|
|
252
|
-
|
|
27
|
+
],
|
|
28
|
+
toDOM: mark => ['a', { ...ctx.get(linkAttr.key)(mark), ...mark.attrs }],
|
|
29
|
+
parseMarkdown: {
|
|
30
|
+
match: node => node.type === 'link',
|
|
31
|
+
runner: (state, node, markType) => {
|
|
32
|
+
const url = node.url as string
|
|
33
|
+
const title = node.title as string
|
|
34
|
+
state.openMark(markType, { href: url, title })
|
|
35
|
+
state.next(node.children)
|
|
36
|
+
state.closeMark(markType)
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
toMarkdown: {
|
|
40
|
+
match: mark => mark.type.name === 'link',
|
|
41
|
+
runner: (state, mark) => {
|
|
42
|
+
state.withMark(mark, 'link', undefined, {
|
|
43
|
+
title: mark.attrs.title,
|
|
44
|
+
url: mark.attrs.href,
|
|
45
|
+
})
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
}))
|
|
49
|
+
|
|
50
|
+
/// @internal
|
|
51
|
+
export type UpdateLinkCommandPayload = {
|
|
52
|
+
href?: string
|
|
53
|
+
title?: string
|
|
54
|
+
}
|
|
55
|
+
/// A command to toggle the link mark.
|
|
56
|
+
/// You can pass the `href` and `title` to the link.
|
|
57
|
+
export const toggleLinkCommand = $command('ToggleLink', () => (payload: UpdateLinkCommandPayload = {}) => toggleMark(linkSchema.type(), payload))
|
|
58
|
+
|
|
59
|
+
/// A command to update the link mark.
|
|
60
|
+
/// You can pass the `href` and `title` to update the link.
|
|
61
|
+
export const updateLinkCommand = $command('UpdateLink', () => (payload: UpdateLinkCommandPayload = {}) => (state, dispatch) => {
|
|
62
|
+
if (!dispatch)
|
|
63
|
+
return false
|
|
64
|
+
|
|
65
|
+
let node: ProseNode | undefined
|
|
66
|
+
let pos = -1
|
|
67
|
+
const { selection } = state
|
|
68
|
+
const { from, to } = selection
|
|
69
|
+
state.doc.nodesBetween(from, from === to ? to + 1 : to, (n, p) => {
|
|
70
|
+
if (linkSchema.type().isInSet(n.marks)) {
|
|
71
|
+
node = n
|
|
72
|
+
pos = p
|
|
73
|
+
return false
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return undefined
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
if (!node)
|
|
80
|
+
return false
|
|
81
|
+
|
|
82
|
+
const mark = node.marks.find(({ type }) => type === linkSchema.type())
|
|
83
|
+
if (!mark)
|
|
84
|
+
return false
|
|
85
|
+
|
|
86
|
+
const start = pos
|
|
87
|
+
const end = pos + node.nodeSize
|
|
88
|
+
const { tr } = state
|
|
89
|
+
const linkMark = linkSchema.type().create({ ...mark.attrs, ...payload })
|
|
90
|
+
if (!linkMark)
|
|
91
|
+
return false
|
|
92
|
+
|
|
93
|
+
dispatch(
|
|
94
|
+
tr
|
|
95
|
+
.removeMark(start, end, mark)
|
|
96
|
+
.addMark(start, end, linkMark)
|
|
97
|
+
.setSelection(new TextSelection(tr.selection.$anchor))
|
|
98
|
+
.scrollIntoView(),
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
return true
|
|
253
102
|
})
|