From d242cfca53a4ff92dbb60e431afec5e9a028b43d Mon Sep 17 00:00:00 2001 From: James Boyden Date: Thu, 1 May 2025 12:23:21 +0100 Subject: [PATCH 1/3] Actually register the snippet shortcut --- .../official/stack-snippets/src/commands.ts | 25 ++++--- .../stack-snippets/src/stackSnippetPlugin.ts | 7 +- .../stack-snippets/test/commands.test.ts | 68 +++++++++++++++---- 3 files changed, 75 insertions(+), 25 deletions(-) diff --git a/plugins/official/stack-snippets/src/commands.ts b/plugins/official/stack-snippets/src/commands.ts index 327639f1..ecfb75ef 100644 --- a/plugins/official/stack-snippets/src/commands.ts +++ b/plugins/official/stack-snippets/src/commands.ts @@ -118,6 +118,13 @@ export function openSnippetModal(options?: StackSnippetOptions): MenuCommand { }; } +/** + * Snippets are comprised of a container around customized codeblocks. Some of the default behaviour for key-binds makes them behave + * very strangely. + * + * In these cases, we override the command to (contextually) do nothing if the current context is a snippet + * This is possible because returning truthy consumes the event. + * **/ const swallowSnippetCommand = (state: EditorState): boolean => { const fromNodeType = state.selection.$from.node().type.name; @@ -129,18 +136,14 @@ const swallowSnippetCommand = (state: EditorState): boolean => { } }; -export const swallowedCommandList = { +export const OPEN_SNIPPET_SHORTCUT = "Mod-9"; + +export const commandList = (opts?: StackSnippetOptions) => ({ "Mod-Enter": swallowSnippetCommand, "Shift-Enter": swallowSnippetCommand, "Mod-r": swallowSnippetCommand, -}; + [OPEN_SNIPPET_SHORTCUT]: openSnippetModal(opts) +}); -/** - * Snippets are comprised of a container around customized codeblocks. Some of the default behaviour for key-binds makes them behave - * very strangely. - * - * In these cases, we override the command to (contextually) do nothing if the current context is a snippet - * This is possible because returning truthy consumes the event. - * **/ -export const stackSnippetCommandRedactor = - caseNormalizeKeymap(swallowedCommandList); +export const stackSnippetCommandShortcuts = (opts?: StackSnippetOptions) => + caseNormalizeKeymap(commandList(opts)); diff --git a/plugins/official/stack-snippets/src/stackSnippetPlugin.ts b/plugins/official/stack-snippets/src/stackSnippetPlugin.ts index ba9d3a8f..e1d0c29b 100644 --- a/plugins/official/stack-snippets/src/stackSnippetPlugin.ts +++ b/plugins/official/stack-snippets/src/stackSnippetPlugin.ts @@ -11,7 +11,7 @@ import { EditorView } from "prosemirror-view"; import { StackSnippetView } from "./snippet-view"; import { StackSnippetOptions } from "./common"; import { stackSnippetPasteHandler } from "./paste-handler"; -import { openSnippetModal, stackSnippetCommandRedactor } from "./commands"; +import { openSnippetModal, stackSnippetCommandShortcuts } from "./commands"; /** * Build the StackSnippet plugin using hoisted options that can be specified at runtime @@ -30,7 +30,10 @@ export const stackSnippetPlugin: (opts?: StackSnippetOptions) => EditorPlugin = return new StackSnippetView(node, view, getPos, opts); }, }, - plugins: [stackSnippetPasteHandler, stackSnippetCommandRedactor], + plugins: [ + stackSnippetPasteHandler, + stackSnippetCommandShortcuts(opts) + ], }, extendSchema: (schema) => { schema.nodes = schema.nodes.append(stackSnippetRichTextNodeSpec); diff --git a/plugins/official/stack-snippets/test/commands.test.ts b/plugins/official/stack-snippets/test/commands.test.ts index 3fff649a..63744210 100644 --- a/plugins/official/stack-snippets/test/commands.test.ts +++ b/plugins/official/stack-snippets/test/commands.test.ts @@ -227,17 +227,25 @@ describe("commands", () => { ); }); - describe("redactor", () => { - //Note: we're testing this functionality once with a command that is universal across Macs and PC. - // In the pipeline this is likely using a Linux environment, in which case "Mod" means "Ctrl" too, but - // the main concern is on other development environments. + describe("shortcuts", () => { + //Stolen eagerly from the Prosemirror-keymap git https://github.com/ProseMirror/prosemirror-keymap/blob/9df35bd441aa60b3ad620da66e0e3f75cd774075/src/keymap.ts#L5 + const mac = typeof navigator != "undefined" ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) : false + it("should swallow commands when in a Snippet context", () => { const view = richView(`${validBegin}${validJs}${validEnd}`); const expectedHTML = view.editorView.dom.innerHTML; - const event = new KeyboardEvent("keydown", { - ctrlKey: true, - key: "Enter", - }); + let event: KeyboardEvent; + if(mac){ + event = new KeyboardEvent("keydown", { + metaKey: true, + key: "Enter" + }) + } else { + event = new KeyboardEvent("keydown", { + ctrlKey: true, + key: "Enter", + }); + } view.editorView.someProp("handleKeyDown", (f) => f(view.editorView, event) @@ -250,10 +258,18 @@ describe("commands", () => { it("should not swallow commands when in a non-Snippet context", () => { const view = richView("```javascript\nconsole.log('test');\n```"); const expectedHTML = view.editorView.dom.innerHTML; - const event = new KeyboardEvent("keydown", { - ctrlKey: true, - key: "Enter", - }); + let event: KeyboardEvent; + if(mac){ + event = new KeyboardEvent("keydown", { + metaKey: true, + key: "Enter" + }) + } else { + event = new KeyboardEvent("keydown", { + ctrlKey: true, + key: "Enter", + }); + } view.editorView.someProp("handleKeyDown", (f) => f(view.editorView, event) @@ -262,5 +278,33 @@ describe("commands", () => { //The Dom is not the same - a change has occured expect(view.editorView.dom.innerHTML).not.toBe(expectedHTML); }); + + it("should trigger the openModal event when shortcut pressed", () => { + let openSnippetTriggered = false; + const view = richView("```javascript\nconsole.log('test');\n```", { + openSnippetsModal: () => { + openSnippetTriggered = true; + }, + renderer: () => Promise.resolve(null), + }); + let event: KeyboardEvent; + if(mac){ + event = new KeyboardEvent("keydown", { + metaKey: true, + key: "9" + }) + } else { + event = new KeyboardEvent("keydown", { + ctrlKey: true, + key: "9", + }); + } + + view.editorView.someProp("handleKeyDown", (f) => + f(view.editorView, event) + ); + + expect(openSnippetTriggered).toBe(true); + }) }); }); From d532d3e98430bf8f7ca32bdcbf863fa6bbd90212 Mon Sep 17 00:00:00 2001 From: James Boyden Date: Thu, 1 May 2025 12:28:46 +0100 Subject: [PATCH 2/3] Linting. --- .../official/stack-snippets/src/commands.ts | 2 +- .../stack-snippets/src/stackSnippetPlugin.ts | 2 +- .../stack-snippets/test/commands.test.ts | 25 +++++++++++-------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/plugins/official/stack-snippets/src/commands.ts b/plugins/official/stack-snippets/src/commands.ts index ecfb75ef..7b4aa48a 100644 --- a/plugins/official/stack-snippets/src/commands.ts +++ b/plugins/official/stack-snippets/src/commands.ts @@ -142,7 +142,7 @@ export const commandList = (opts?: StackSnippetOptions) => ({ "Mod-Enter": swallowSnippetCommand, "Shift-Enter": swallowSnippetCommand, "Mod-r": swallowSnippetCommand, - [OPEN_SNIPPET_SHORTCUT]: openSnippetModal(opts) + [OPEN_SNIPPET_SHORTCUT]: openSnippetModal(opts), }); export const stackSnippetCommandShortcuts = (opts?: StackSnippetOptions) => diff --git a/plugins/official/stack-snippets/src/stackSnippetPlugin.ts b/plugins/official/stack-snippets/src/stackSnippetPlugin.ts index e1d0c29b..741eeff8 100644 --- a/plugins/official/stack-snippets/src/stackSnippetPlugin.ts +++ b/plugins/official/stack-snippets/src/stackSnippetPlugin.ts @@ -32,7 +32,7 @@ export const stackSnippetPlugin: (opts?: StackSnippetOptions) => EditorPlugin = }, plugins: [ stackSnippetPasteHandler, - stackSnippetCommandShortcuts(opts) + stackSnippetCommandShortcuts(opts), ], }, extendSchema: (schema) => { diff --git a/plugins/official/stack-snippets/test/commands.test.ts b/plugins/official/stack-snippets/test/commands.test.ts index 63744210..aaf49d00 100644 --- a/plugins/official/stack-snippets/test/commands.test.ts +++ b/plugins/official/stack-snippets/test/commands.test.ts @@ -229,17 +229,20 @@ describe("commands", () => { describe("shortcuts", () => { //Stolen eagerly from the Prosemirror-keymap git https://github.com/ProseMirror/prosemirror-keymap/blob/9df35bd441aa60b3ad620da66e0e3f75cd774075/src/keymap.ts#L5 - const mac = typeof navigator != "undefined" ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) : false + const mac = + typeof navigator != "undefined" + ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) + : false; it("should swallow commands when in a Snippet context", () => { const view = richView(`${validBegin}${validJs}${validEnd}`); const expectedHTML = view.editorView.dom.innerHTML; let event: KeyboardEvent; - if(mac){ + if (mac) { event = new KeyboardEvent("keydown", { metaKey: true, - key: "Enter" - }) + key: "Enter", + }); } else { event = new KeyboardEvent("keydown", { ctrlKey: true, @@ -259,11 +262,11 @@ describe("commands", () => { const view = richView("```javascript\nconsole.log('test');\n```"); const expectedHTML = view.editorView.dom.innerHTML; let event: KeyboardEvent; - if(mac){ + if (mac) { event = new KeyboardEvent("keydown", { metaKey: true, - key: "Enter" - }) + key: "Enter", + }); } else { event = new KeyboardEvent("keydown", { ctrlKey: true, @@ -288,11 +291,11 @@ describe("commands", () => { renderer: () => Promise.resolve(null), }); let event: KeyboardEvent; - if(mac){ + if (mac) { event = new KeyboardEvent("keydown", { metaKey: true, - key: "9" - }) + key: "9", + }); } else { event = new KeyboardEvent("keydown", { ctrlKey: true, @@ -305,6 +308,6 @@ describe("commands", () => { ); expect(openSnippetTriggered).toBe(true); - }) + }); }); }); From eb559f6793d6a7a6257b06fbbb5c9919e616556e Mon Sep 17 00:00:00 2001 From: James Boyden Date: Thu, 1 May 2025 12:29:35 +0100 Subject: [PATCH 3/3] missing changeset --- .changeset/olive-snakes-wink.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/olive-snakes-wink.md diff --git a/.changeset/olive-snakes-wink.md b/.changeset/olive-snakes-wink.md new file mode 100644 index 00000000..5fbde735 --- /dev/null +++ b/.changeset/olive-snakes-wink.md @@ -0,0 +1,5 @@ +--- +"@stackoverflow/stacks-editor": patch +--- + +Actually register the Snippets open command (rather than just showing it in the tooltip)