From 68d4041b1c5a4f1c8182bb3bcaf9626c64cb7d5f Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Tue, 6 Feb 2024 20:44:38 -0500 Subject: [PATCH] feat: Cmd-A inside code block should select block contents, closes #6498 --- app/editor/menus/formatting.tsx | 4 +-- shared/editor/commands/selectAll.ts | 39 +++++++++++++++++++++++++++++ shared/editor/nodes/CodeBlock.ts | 8 ++++++ shared/editor/nodes/CodeFence.ts | 2 ++ 4 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 shared/editor/commands/selectAll.ts diff --git a/app/editor/menus/formatting.tsx b/app/editor/menus/formatting.tsx index d207ccc86..f6aa97f71 100644 --- a/app/editor/menus/formatting.tsx +++ b/app/editor/menus/formatting.tsx @@ -174,13 +174,13 @@ export default function formattingMenuItems( }, { name: "separator", - visible: isCode, + visible: isCode && !isCodeBlock, }, { name: "copyToClipboard", icon: , tooltip: dictionary.copy, - visible: isCode, + visible: isCode && !isCodeBlock, }, ]; } diff --git a/shared/editor/commands/selectAll.ts b/shared/editor/commands/selectAll.ts new file mode 100644 index 000000000..05f5cde3e --- /dev/null +++ b/shared/editor/commands/selectAll.ts @@ -0,0 +1,39 @@ +import { NodeType } from "prosemirror-model"; +import { Command, TextSelection } from "prosemirror-state"; +import { findParentNode } from "../queries/findParentNode"; + +/** + * Selects all the content of the given node type. + * + * @param type The node type + * @returns A prosemirror command. + */ +export function selectAll(type: NodeType): Command { + return (state, dispatch) => { + const code = findParentNode((node) => node.type === type)(state.selection); + + if (code) { + const start = code.pos; + const end = code.pos + code.node.nodeSize; + + if ( + start === state.selection.from - 1 && + end === state.selection.to + 1 + ) { + return false; + } + + dispatch?.( + state.tr.setSelection( + TextSelection.between( + state.doc.resolve(start), + state.doc.resolve(end) + ) + ) + ); + return true; + } + + return false; + }; +} diff --git a/shared/editor/nodes/CodeBlock.ts b/shared/editor/nodes/CodeBlock.ts index 02964825d..a64926d78 100644 --- a/shared/editor/nodes/CodeBlock.ts +++ b/shared/editor/nodes/CodeBlock.ts @@ -1,3 +1,5 @@ +import { NodeType } from "prosemirror-model"; +import { selectAll } from "../commands/selectAll"; import CodeFence from "./CodeFence"; export default class CodeBlock extends CodeFence { @@ -8,4 +10,10 @@ export default class CodeBlock extends CodeFence { get markdownToken() { return "code_block"; } + + keys({ type }: { type: NodeType }) { + return { + "Mod-a": selectAll(type), + }; + } } diff --git a/shared/editor/nodes/CodeFence.ts b/shared/editor/nodes/CodeFence.ts index b65f073b2..afd51c615 100644 --- a/shared/editor/nodes/CodeFence.ts +++ b/shared/editor/nodes/CodeFence.ts @@ -68,6 +68,7 @@ import { moveToNextNewline, moveToPreviousNewline, } from "../commands/codeFence"; +import { selectAll } from "../commands/selectAll"; import toggleBlockType from "../commands/toggleBlockType"; import Mermaid from "../extensions/Mermaid"; import Prism from "../extensions/Prism"; @@ -255,6 +256,7 @@ export default class CodeFence extends Node { return newlineInCode(state, dispatch); }, "Shift-Enter": newlineInCode, + "Mod-a": selectAll(type), }; if (isMac()) {