@atlaskit/editor-plugin-code-block-advanced
Version:
CodeBlockAdvanced plugin for @atlaskit/editor-core
70 lines (64 loc) • 2.12 kB
text/typescript
import type { EditorView as CodeMirror } from '@codemirror/view';
import { RelativeSelectionPos } from '@atlaskit/editor-common/selection';
import type { getPosHandlerNode } from '@atlaskit/editor-common/types';
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
import { Selection } from '@atlaskit/editor-prosemirror/state';
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
interface MaybeEscapeProps {
cm: CodeMirror;
dir: -1 | 1;
getNode: () => PMNode;
getPos: getPosHandlerNode;
onMaybeNodeSelection: () => void;
selectCodeBlockNode: (relativeSelectionPos: RelativeSelectionPos | undefined) => void;
unit: 'line' | 'char';
view: EditorView;
}
export const maybeEscapeKeymap = ({
unit,
dir,
view,
cm,
getPos,
getNode,
onMaybeNodeSelection,
selectCodeBlockNode,
}: MaybeEscapeProps): boolean => {
if (unit === 'char') {
onMaybeNodeSelection();
}
const node = getNode();
const { state } = cm;
let main: { empty: boolean; from: number; head: number; to: number } = state.selection.main;
if (!main.empty) {
return false;
}
if (unit === 'line') {
main = { ...state.doc.lineAt(main.head), head: 0, empty: false };
}
if (dir < 0 ? main.from > 0 : main.to < state.doc.length) {
return false;
}
const targetPos = (getPos?.() ?? 0) + (dir < 0 ? 0 : node.nodeSize);
if (unit === 'char') {
view.focus();
selectCodeBlockNode(dir === -1 ? RelativeSelectionPos.Start : RelativeSelectionPos.End);
return true;
} else {
createParagraphIfEndOfDoc(view, targetPos);
const tr = view.state.tr;
const selection = Selection.near(tr.doc.resolve(targetPos), dir);
tr.setSelection(selection).scrollIntoView();
view.dispatch(tr);
view.focus();
return true;
}
};
const createParagraphIfEndOfDoc = (view: EditorView, targetPos: number) => {
if (targetPos === view.state.doc.content.size) {
const paragraph = view.state.schema.nodes.paragraph.createChecked({});
const tr = view.state.tr.insert(targetPos, paragraph);
// Note: we purposefully do a multi-dispatch here, otherwise we get stuck in codemirror
view.dispatch(tr);
}
};