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) diff --git a/plugins/official/stack-snippets/src/commands.ts b/plugins/official/stack-snippets/src/commands.ts index 327639f1..7b4aa48a 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..741eeff8 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..aaf49d00 100644 --- a/plugins/official/stack-snippets/test/commands.test.ts +++ b/plugins/official/stack-snippets/test/commands.test.ts @@ -227,17 +227,28 @@ 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 +261,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 +281,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); + }); }); });