Postulate is the best way to take and share notes for classes, research, and other learning.
While building the editor for Postulate, I wanted users to be able to add links with the shortcut Ctrl+K
. Unlike marks, for some reason this fairly standard shortcut is not built into the default link plugin, so I went about implementing it myself.
I looked into createBoldPlugin
to see how it creates a Ctrl+B
shortcut for adding bold marks. Turns out, all that createBoldPlugin
does is return an object of the type SlatePlugin
:
export const createBoldPlugin = (): SlatePlugin => ({ pluginKeys: MARK_BOLD, renderLeaf: getRenderLeaf(MARK_BOLD), deserialize: getBoldDeserialize(), onKeyDown: getToggleMarkOnKeyDown(MARK_BOLD), });
And right at the bottom is onKeyDown
! getToggleMarkOnKeyDown
looks like this:
export const getToggleMarkOnKeyDown = (pluginKey: string): OnKeyDown => ( editor ) => (e) => { const { hotkey, type, clear } = getSlatePluginOptions(editor, pluginKey); if (!hotkey) return; if (isHotkey(hotkey, e)) { e.preventDefault(); toggleMark(editor, type, clear); } };
There's a little more going on here, but what's returned is a function editor => e => { ...whatever you want }
, where e => { ...whatever you want }
is added to Slate's onKeyDown
handler.
To add your own keyboard shortcut, then, all you need to do is add a new object with an onKeyDown
function to your plugins list:
const plugins = [ ... { onKeydown: editor => e => { if (isHotkey("YOUR HOTKEY", e)) { // WHATEVER YOU WANT } } } ];
Use this for whatever shortcut, with whatever functionality, you want! For my Ctrl+K
to link shortcut, the custom mini-plugin looks like this:
const plugins = [ ... { onKeydown: editor => e => { if (isHotkey("mod+k", e)) { e.preventDefault(); const type = getSlatePluginType(editor, ELEMENT_LINK); const isLink = someNode(editor, { match: { type } }); // if there is a link at the cursor, get rid of the link if (isLink) unwrapNodes(editor, {at: editor.selection, match: {type: getSlatePluginType(editor, ELEMENT_LINK)}}); // else if there is a selection, not just a point, create a link on that selection else if (editor.selection.anchor !== editor.selection.focus) { // taken from ToolbarLink.tsx with modifications const url = normalizeUrl(window.prompt(`Enter the URL of the link:`)); if (url) { upsertLinkAtSelection(editor, { url, wrap: true }); } } } } } ];
Founder and dev notes from building Postulate