fix: Ctrl-a/e in code fences
This commit is contained in:
@@ -2,6 +2,13 @@ import { NodeType } from "prosemirror-model";
|
||||
import { EditorState } from "prosemirror-state";
|
||||
import { Dispatch } from "../types";
|
||||
|
||||
/**
|
||||
* Converts the current node to a paragraph when pressing backspace at the
|
||||
* beginning of the node and not already a paragraph.
|
||||
*
|
||||
* @param type The node type
|
||||
* @returns A prosemirror command.
|
||||
*/
|
||||
export default function backspaceToParagraph(type: NodeType) {
|
||||
return (state: EditorState, dispatch: Dispatch) => {
|
||||
const { $from, from, to, empty } = state.selection;
|
||||
|
||||
122
shared/editor/commands/codeFence.ts
Normal file
122
shared/editor/commands/codeFence.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import { EditorState, TextSelection } from "prosemirror-state";
|
||||
import isInCode from "../queries/isInCode";
|
||||
import { Dispatch } from "../types";
|
||||
|
||||
/**
|
||||
* Moves the current selection to the previous newline, this is used inside
|
||||
* code fences only, prosemirror handles this functionality fine in other nodes.
|
||||
*
|
||||
* @returns A prosemirror command.
|
||||
*/
|
||||
export const moveToPreviousNewline = (
|
||||
state: EditorState,
|
||||
dispatch: Dispatch
|
||||
) => {
|
||||
if (!isInCode(state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const $pos = state.selection.$from;
|
||||
if (!$pos.parent.type.isTextblock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The easiest way to find the previous newline is to reverse the string and
|
||||
// perform a forward seach as if looking for the next newline.
|
||||
const beginningOfNode = $pos.pos - $pos.parentOffset;
|
||||
const startOfLine = $pos.parent.textContent
|
||||
.split("")
|
||||
.reverse()
|
||||
.join("")
|
||||
.indexOf("\n", $pos.parent.nodeSize - $pos.parentOffset - 2);
|
||||
|
||||
if (startOfLine === -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dispatch(
|
||||
state.tr.setSelection(
|
||||
TextSelection.create(
|
||||
state.doc,
|
||||
beginningOfNode + ($pos.parent.nodeSize - startOfLine - 2)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Moves the current selection to the next newline, this is used inside code
|
||||
* fences only, prosemirror handles this functionality fine in other nodes.
|
||||
*
|
||||
* @returns A prosemirror command.
|
||||
*/
|
||||
export const moveToNextNewline = (state: EditorState, dispatch: Dispatch) => {
|
||||
if (!isInCode(state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const $pos = state.selection.$to;
|
||||
if (!$pos.parent.type.isTextblock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// find next newline
|
||||
const beginningOfNode = $pos.pos - $pos.parentOffset;
|
||||
const endOfLine = $pos.parent.textContent.indexOf("\n", $pos.parentOffset);
|
||||
if (endOfLine === -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dispatch(
|
||||
state.tr.setSelection(
|
||||
TextSelection.create(state.doc, beginningOfNode + endOfLine)
|
||||
)
|
||||
);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Replace the selection with a newline character preceeded by a number of
|
||||
* spaces to have the new line align with the code on the previous. This is
|
||||
* standard code editor behavior.
|
||||
*
|
||||
* @returns A prosemirror command
|
||||
*/
|
||||
export const newlineInCode = (state: EditorState, dispatch: Dispatch) => {
|
||||
if (!isInCode(state)) {
|
||||
return false;
|
||||
}
|
||||
const { tr, selection } = state;
|
||||
const text = selection?.$anchor?.nodeBefore?.text;
|
||||
|
||||
let newText = "\n";
|
||||
|
||||
if (text) {
|
||||
const splitByNewLine = text.split("\n");
|
||||
const numOfSpaces = splitByNewLine[splitByNewLine.length - 1].search(
|
||||
/\S|$/
|
||||
);
|
||||
newText += " ".repeat(numOfSpaces);
|
||||
}
|
||||
|
||||
dispatch(tr.insertText(newText, selection.from, selection.to));
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Insert two spaces to simulate the tab key.
|
||||
*
|
||||
* @returns A prosemirror command
|
||||
*/
|
||||
export const insertSpaceTab = (state: EditorState, dispatch: Dispatch) => {
|
||||
if (!isInCode(state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { tr, selection } = state;
|
||||
dispatch(tr.insertText(" ", selection.from, selection.to));
|
||||
return true;
|
||||
};
|
||||
Reference in New Issue
Block a user