@milkdown/preset-commonmark
Version:
The commonmark preset of [milkdown](https://milkdown.dev/).
131 lines (115 loc) • 3.37 kB
text/typescript
import { commandsCtx, remarkStringifyOptionsCtx } from '@milkdown/core'
import { markRule } from '@milkdown/prose'
import { toggleMark } from '@milkdown/prose/commands'
import {
$command,
$inputRule,
$markAttr,
$markSchema,
$useKeymap,
} from '@milkdown/utils'
import { withMeta } from '../__internal__'
/// HTML attributes for the emphasis mark.
export const emphasisAttr = $markAttr('emphasis')
withMeta(emphasisAttr, {
displayName: 'Attr<emphasis>',
group: 'Emphasis',
})
/// Emphasis mark schema.
export const emphasisSchema = $markSchema('emphasis', (ctx) => ({
attrs: {
marker: {
default: ctx.get(remarkStringifyOptionsCtx).emphasis || '*',
validate: 'string',
},
},
parseDOM: [
{ tag: 'i' },
{ tag: 'em' },
{ style: 'font-style', getAttrs: (value) => (value === 'italic') as false },
],
toDOM: (mark) => ['em', ctx.get(emphasisAttr.key)(mark)],
parseMarkdown: {
match: (node) => node.type === 'emphasis',
runner: (state, node, markType) => {
state.openMark(markType, { marker: node.marker })
state.next(node.children)
state.closeMark(markType)
},
},
toMarkdown: {
match: (mark) => mark.type.name === 'emphasis',
runner: (state, mark) => {
state.withMark(mark, 'emphasis', undefined, {
marker: mark.attrs.marker,
})
},
},
}))
withMeta(emphasisSchema.mark, {
displayName: 'MarkSchema<emphasis>',
group: 'Emphasis',
})
withMeta(emphasisSchema.ctx, {
displayName: 'MarkSchemaCtx<emphasis>',
group: 'Emphasis',
})
/// A command to toggle the emphasis mark.
export const toggleEmphasisCommand = $command('ToggleEmphasis', (ctx) => () => {
return toggleMark(emphasisSchema.type(ctx))
})
withMeta(toggleEmphasisCommand, {
displayName: 'Command<toggleEmphasisCommand>',
group: 'Emphasis',
})
/// Input rule for use `*` to create emphasis mark.
export const emphasisStarInputRule = $inputRule((ctx) => {
return markRule(/(?:^|[^*])\*([^*]+)\*$/, emphasisSchema.type(ctx), {
getAttr: () => ({
marker: '*',
}),
updateCaptured: ({ fullMatch, start }) =>
!fullMatch.startsWith('*')
? { fullMatch: fullMatch.slice(1), start: start + 1 }
: {},
})
})
withMeta(emphasisStarInputRule, {
displayName: 'InputRule<emphasis>|Star',
group: 'Emphasis',
})
/// Input rule for use `_` to create emphasis mark.
export const emphasisUnderscoreInputRule = $inputRule((ctx) => {
return markRule(/\b_(?![_\s])(.*?[^_\s])_\b/, emphasisSchema.type(ctx), {
getAttr: () => ({
marker: '_',
}),
updateCaptured: ({ fullMatch, start }) =>
!fullMatch.startsWith('_')
? { fullMatch: fullMatch.slice(1), start: start + 1 }
: {},
})
})
withMeta(emphasisUnderscoreInputRule, {
displayName: 'InputRule<emphasis>|Underscore',
group: 'Emphasis',
})
/// Keymap for the emphasis mark.
/// - `Mod-i` - Toggle the emphasis mark.
export const emphasisKeymap = $useKeymap('emphasisKeymap', {
ToggleEmphasis: {
shortcuts: 'Mod-i',
command: (ctx) => {
const commands = ctx.get(commandsCtx)
return () => commands.call(toggleEmphasisCommand.key)
},
},
})
withMeta(emphasisKeymap.ctx, {
displayName: 'KeymapCtx<emphasis>',
group: 'Emphasis',
})
withMeta(emphasisKeymap.shortcuts, {
displayName: 'Keymap<emphasis>',
group: 'Emphasis',
})