@atlaskit/editor-plugin-code-block-advanced
Version:
CodeBlockAdvanced plugin for @atlaskit/editor-core
212 lines (204 loc) • 4.86 kB
text/typescript
import { defaultKeymap, indentWithTab } from '@codemirror/commands';
import type { Extension } from '@codemirror/state';
import { keymap as cmKeymap } from '@codemirror/view';
import type { KeyBinding } from '@codemirror/view';
import { getBrowserInfo } from '@atlaskit/editor-common/browser';
import type { RelativeSelectionPos } from '@atlaskit/editor-common/selection';
import type { getPosHandlerNode } from '@atlaskit/editor-common/types';
import { exitCode, selectAll } from '@atlaskit/editor-prosemirror/commands';
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
import { undo, redo } from '@atlaskit/prosemirror-history';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import { backspaceKeymap } from './backspace';
import { maybeEscapeKeymap } from './maybeEscape';
interface KeymapProps {
customFindReplace: boolean;
getNode: () => PMNode;
getPos: getPosHandlerNode;
onMaybeNodeSelection: () => void;
selectCodeBlockNode: (relativeSelectionPos: RelativeSelectionPos | undefined) => void;
view: EditorView;
}
export const keymapExtension = ({
view,
getNode,
getPos,
selectCodeBlockNode,
onMaybeNodeSelection,
customFindReplace,
}: KeymapProps): Extension => {
return cmKeymap.of(
codeBlockKeymap({
view,
getNode,
getPos,
selectCodeBlockNode,
onMaybeNodeSelection,
customFindReplace,
}),
);
};
const codeBlockKeymap = ({
view,
getNode,
getPos,
selectCodeBlockNode,
onMaybeNodeSelection,
customFindReplace,
}: KeymapProps): readonly KeyBinding[] => {
const browser = getBrowserInfo();
return [
{
key: 'ArrowUp',
run: (cm) =>
maybeEscapeKeymap({
unit: 'line',
dir: -1,
cm,
view,
getNode,
getPos,
selectCodeBlockNode,
onMaybeNodeSelection,
}),
},
{
key: 'ArrowLeft',
run: (cm) =>
maybeEscapeKeymap({
unit: 'char',
dir: -1,
cm,
view,
getNode,
getPos,
selectCodeBlockNode,
onMaybeNodeSelection,
}),
},
{
key: 'ArrowDown',
run: (cm) =>
maybeEscapeKeymap({
unit: 'line',
dir: 1,
cm,
view,
getNode,
getPos,
selectCodeBlockNode,
onMaybeNodeSelection,
}),
},
{
key: 'Ctrl-a',
mac: 'Cmd-a',
run: (cm) => {
const isFullBlockSelection =
cm.state.selection.main.from === 0 &&
cm.state.selection.main.to === getNode().content.size;
// Allow codemirror to handle
if (!isFullBlockSelection) {
return false;
}
// Move the selection and focus into prosemirror
onMaybeNodeSelection();
view.focus();
selectAll(view.state, view.dispatch);
return true;
},
},
{
key: 'ArrowRight',
run: (cm) =>
maybeEscapeKeymap({
unit: 'char',
dir: 1,
cm,
view,
getNode,
getPos,
selectCodeBlockNode,
onMaybeNodeSelection,
}),
},
{
key: 'Ctrl-f',
mac: 'Cmd-f',
run: () => {
// Pass synthetic event to prosemirror
if (customFindReplace) {
view.dispatchEvent(
new KeyboardEvent('keydown', {
key: 'f',
code: 'KeyF',
metaKey: browser.mac ? true : false,
ctrlKey: browser.mac ? false : true,
}),
);
return true;
}
return false;
},
},
{
key: 'Ctrl-Enter',
run: () => {
if (!exitCode(view.state, view.dispatch)) {
return false;
}
view.focus();
return true;
},
},
{ key: 'Ctrl-z', mac: 'Cmd-z', run: () => undo(view.state, view.dispatch) },
{ key: 'Shift-Ctrl-z', mac: 'Shift-Cmd-z', run: () => redo(view.state, view.dispatch) },
{ key: 'Ctrl-y', mac: 'Cmd-y', run: () => redo(view.state, view.dispatch) },
{
key: 'Backspace',
run: (cm) => backspaceKeymap({ cm, view, getNode, getPos }),
},
{
key: 'Ctrl-Alt-]',
mac: 'Cmd-Alt-]',
run: () => {
// Pass synthetic event to prosemirror
if (expValEquals('platform_editor_breakout_resizing', 'isEnabled', true)) {
view.dispatchEvent(
new KeyboardEvent('keydown', {
key: ']',
code: 'BracketRight',
metaKey: browser.mac ? true : false,
ctrlKey: browser.mac ? false : true,
altKey: true,
}),
);
return true;
}
return false;
},
},
{
key: 'Ctrl-Alt-[',
mac: 'Cmd-Alt-[',
run: () => {
// Pass synthetic event to prosemirror
if (expValEquals('platform_editor_breakout_resizing', 'isEnabled', true)) {
view.dispatchEvent(
new KeyboardEvent('keydown', {
key: ']',
code: 'BracketLeft',
metaKey: browser.mac ? true : false,
ctrlKey: browser.mac ? false : true,
altKey: true,
}),
);
return true;
}
return false;
},
},
...defaultKeymap.concat(indentWithTab),
];
};