99 lines
3.4 KiB
JavaScript
99 lines
3.4 KiB
JavaScript
import {wrapIn, setBlockType, chainCommands, toggleMark, exitCode,
|
|
joinUp, joinDown, lift, selectParentNode} from 'prosemirror-commands'
|
|
import {splitListItem, liftListItem} from './godo-additional-commands.mjs'
|
|
import {undo, redo} from 'prosemirror-history'
|
|
|
|
const mac = typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false
|
|
|
|
// :: (Schema, ?Object) → Object
|
|
// Inspect the given schema looking for marks and nodes from the
|
|
// basic schema, and if found, add key bindings related to them.
|
|
// This will add:
|
|
//
|
|
// * **Mod-b** for toggling [strong](#schema-basic.StrongMark)
|
|
// * **Mod-i** for toggling [emphasis](#schema-basic.EmMark)
|
|
// * **Mod-`** for toggling [code font](#schema-basic.CodeMark)
|
|
// * **Ctrl-Shift-0** for making the current textblock a paragraph
|
|
// * **Ctrl-Shift-1** to **Ctrl-Shift-Digit6** for making the current
|
|
// textblock a heading of the corresponding level
|
|
// * **Ctrl-Shift-Backslash** to make the current textblock a code block
|
|
// * **Ctrl->** to wrap the selection in a block quote
|
|
// * **Enter** to split a non-empty textblock in a list item while at
|
|
// the same time splitting the list item
|
|
// * **Mod-Enter** to insert a hard break
|
|
// * **Mod-_** to insert a horizontal rule
|
|
// * **Backspace** to undo an input rule
|
|
// * **Alt-ArrowUp** to `joinUp`
|
|
// * **Alt-ArrowDown** to `joinDown`
|
|
// * **Mod-BracketLeft** to `lift`
|
|
// * **Escape** to `selectParentNode`
|
|
//
|
|
// You can suppress or map these bindings by passing a `mapKeys`
|
|
// argument, which maps key names (say `"Mod-B"` to either `false`, to
|
|
// remove the binding, or a new key name string.
|
|
export function buildKeymap (schema, mapKeys, options) {
|
|
let keys = {}; let type
|
|
function bind (key, cmd) {
|
|
if (mapKeys) {
|
|
let mapped = mapKeys[key]
|
|
if (mapped === false) return
|
|
if (mapped) key = mapped
|
|
}
|
|
keys[key] = cmd
|
|
}
|
|
|
|
bind('Mod-z', undo)
|
|
bind('Shift-Mod-z', redo)
|
|
if (!mac) bind('Mod-y', redo)
|
|
|
|
bind('Alt-ArrowUp', joinUp)
|
|
bind('Alt-ArrowDown', joinDown)
|
|
bind('Mod-BracketLeft', lift)
|
|
bind('Escape', selectParentNode)
|
|
|
|
if ((type = schema.marks.strong)) {
|
|
bind('Mod-b', toggleMark(type))
|
|
bind('Mod-B', toggleMark(type))
|
|
}
|
|
if ((type = schema.marks.em)) {
|
|
bind('Mod-i', toggleMark(type))
|
|
bind('Mod-I', toggleMark(type))
|
|
}
|
|
if ((type = schema.marks.code)) bind('Mod-`', toggleMark(type))
|
|
if ((type = schema.nodes.blockquote)) bind('Ctrl->', wrapIn(type))
|
|
if ((type = schema.nodes.list_item)) {
|
|
bind('Enter', splitListItem(type))
|
|
bind('Mod-[', liftListItem(type))
|
|
}
|
|
|
|
if ((type = schema.nodes.hard_break)) {
|
|
let br = type; let cmd = chainCommands(exitCode, (state, dispatch) => {
|
|
dispatch(state.tr.replaceSelectionWith(br.create()).scrollIntoView())
|
|
return true
|
|
})
|
|
bind('Mod-Enter', cmd)
|
|
bind('Shift-Enter', cmd)
|
|
if (mac) bind('Ctrl-Enter', cmd)
|
|
}
|
|
|
|
if ((type = schema.nodes.paragraph)) bind('Shift-Ctrl-0', setBlockType(type))
|
|
|
|
if ((type = schema.nodes.code_block)) bind('Shift-Ctrl-\\', setBlockType(type))
|
|
|
|
if ((type = schema.nodes.heading)) {
|
|
options.heading_levels.forEach((level, index) => {
|
|
bind(`Shift-Ctrl-${index + 1}`, setBlockType(type, {level: level}))
|
|
})
|
|
}
|
|
|
|
if ((type = schema.nodes.horizontal_rule)) {
|
|
let hr = type
|
|
bind('Mod-_', (state, dispatch) => {
|
|
dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView())
|
|
return true
|
|
})
|
|
}
|
|
|
|
return keys
|
|
}
|