@milkdown/preset-commonmark
Version:
The commonmark preset of [milkdown](https://milkdown.dev/).
123 lines (104 loc) • 3.16 kB
text/typescript
import type { MarkType } from '@milkdown/prose/model'
import { commandsCtx } from '@milkdown/core'
import { markRule } from '@milkdown/prose'
import {
$command,
$inputRule,
$markAttr,
$markSchema,
$useKeymap,
} from '@milkdown/utils'
import { withMeta } from '../__internal__'
/// HTML attributes for the inlineCode mark.
export const inlineCodeAttr = $markAttr('inlineCode')
withMeta(inlineCodeAttr, {
displayName: 'Attr<inlineCode>',
group: 'InlineCode',
})
/// InlineCode mark schema.
export const inlineCodeSchema = $markSchema('inlineCode', (ctx) => ({
priority: 100,
code: true,
parseDOM: [{ tag: 'code' }],
toDOM: (mark) => ['code', ctx.get(inlineCodeAttr.key)(mark)],
parseMarkdown: {
match: (node) => node.type === 'inlineCode',
runner: (state, node, markType) => {
state.openMark(markType)
state.addText(node.value as string)
state.closeMark(markType)
},
},
toMarkdown: {
match: (mark) => mark.type.name === 'inlineCode',
runner: (state, mark, node) => {
state.withMark(mark, 'inlineCode', node.text || '')
},
},
}))
withMeta(inlineCodeSchema.mark, {
displayName: 'MarkSchema<inlineCode>',
group: 'InlineCode',
})
withMeta(inlineCodeSchema.ctx, {
displayName: 'MarkSchemaCtx<inlineCode>',
group: 'InlineCode',
})
/// A command to toggle the inlineCode mark.
export const toggleInlineCodeCommand = $command(
'ToggleInlineCode',
(ctx) => () => (state, dispatch) => {
const { selection, tr } = state
if (selection.empty) return false
const { from, to } = selection
const has = state.doc.rangeHasMark(from, to, inlineCodeSchema.type(ctx))
// remove exists inlineCode mark if have
if (has) {
dispatch?.(tr.removeMark(from, to, inlineCodeSchema.type(ctx)))
return true
}
const restMarksName = Object.keys(state.schema.marks).filter(
(x) => x !== inlineCodeSchema.type.name
)
// remove other marks
restMarksName
.map((name) => state.schema.marks[name] as MarkType)
.forEach((t) => {
tr.removeMark(from, to, t)
})
// add inlineCode mark
dispatch?.(tr.addMark(from, to, inlineCodeSchema.type(ctx).create()))
return true
}
)
withMeta(toggleInlineCodeCommand, {
displayName: 'Command<toggleInlineCodeCommand>',
group: 'InlineCode',
})
/// Input rule for create inlineCode mark.
export const inlineCodeInputRule = $inputRule((ctx) => {
return markRule(/(?:`)([^`]+)(?:`)$/, inlineCodeSchema.type(ctx))
})
withMeta(inlineCodeInputRule, {
displayName: 'InputRule<inlineCodeInputRule>',
group: 'InlineCode',
})
/// Keymap for the inlineCode mark.
/// - `Mod-e` - Toggle the inlineCode mark.
export const inlineCodeKeymap = $useKeymap('inlineCodeKeymap', {
ToggleInlineCode: {
shortcuts: 'Mod-e',
command: (ctx) => {
const commands = ctx.get(commandsCtx)
return () => commands.call(toggleInlineCodeCommand.key)
},
},
})
withMeta(inlineCodeKeymap.ctx, {
displayName: 'KeymapCtx<inlineCode>',
group: 'InlineCode',
})
withMeta(inlineCodeKeymap.shortcuts, {
displayName: 'Keymap<inlineCode>',
group: 'InlineCode',
})