diff --git a/packages/editor/src/extensions/code-block/code-block.ts b/packages/editor/src/extensions/code-block/code-block.ts index 3d085872c8..8568d929ef 100644 --- a/packages/editor/src/extensions/code-block/code-block.ts +++ b/packages/editor/src/extensions/code-block/code-block.ts @@ -234,11 +234,34 @@ export const CodeBlock = Node.create({ }, toggleCodeBlock: (attributes) => - ({ commands }) => { - return commands.toggleNode(this.name, "paragraph", { - ...attributes, - id: createCodeblockId() - }); + ({ commands, state }) => { + const { from, to } = state.selection; + + const isInsideCodeBlock: boolean = this.editor.isActive( + this.type.name + ) + ? true + : false; + + if (!isInsideCodeBlock) { + const text = state.doc.textBetween(from, to, "\n"); + + const newNode = this.type.create( + { ...attributes, id: createCodeblockId() }, + state.schema.text(text) + ); + + state.tr.replaceSelectionWith(newNode); + + commands.setTextSelection({ + from: from, + to: to + }); + + return true; + } else { + return commands.clearNodes(); + } }, changeCodeBlockIndentation: (options) => diff --git a/packages/editor/src/extensions/code-block/tests/__snapshots__/code-block.test.ts.snap b/packages/editor/src/extensions/code-block/tests/__snapshots__/code-block.test.ts.snap index 450f8bf5c7..a497f7d37e 100644 --- a/packages/editor/src/extensions/code-block/tests/__snapshots__/code-block.test.ts.snap +++ b/packages/editor/src/extensions/code-block/tests/__snapshots__/code-block.test.ts.snap @@ -2,6 +2,10 @@ exports[`Adding a new codeblock & changing the language should apply the new highlighting 1`] = `"
function hello() { }
"`; +exports[`Toggling from a codeblock should make codeblock disappear 1`] = `"

function hello() { }

function hello() { }

"`; + +exports[`Toggling multiple paragraphs into a codeblock should make one codeblock 1`] = `"
function helloWorld() { console.log('Hello, World!'); }
"`; + exports[`codeblocks should get highlighted after pasting 1`] = `"
function hello() { }
function hello() { }
"`; exports[`codeblocks should get highlighted on init 1`] = `"
function hello() { }
function hello() { }
"`; diff --git a/packages/editor/src/extensions/code-block/tests/code-block.test.ts b/packages/editor/src/extensions/code-block/tests/code-block.test.ts index 42f3eec057..fe40e64e36 100644 --- a/packages/editor/src/extensions/code-block/tests/code-block.test.ts +++ b/packages/editor/src/extensions/code-block/tests/code-block.test.ts @@ -33,6 +33,17 @@ const CODEBLOCKS_HTML = h("div", [ }) ]).innerHTML; +const CODE_PARAGRAPH = `function helloWorld() { + console.log('Hello, World!'); +}`; + +interface DocumentNode { + type: string; + attrs?: { [key: string]: any }; + content?: DocumentNode[]; + text?: string; +} + test("codeblocks should get highlighted on init", async () => { const editorElement = h("div"); createEditor({ @@ -243,3 +254,73 @@ test("Switching codeblock language should register the new language", async () = await new Promise((resolve) => setTimeout(resolve, 100)); expect(refractor.registered("java")).toBe(true); }); + +test("Toggling multiple paragraphs into a codeblock should make one codeblock", async () => { + const editorElement = h("div"); + const { editor } = createEditor({ + element: editorElement, + initialContent: CODE_PARAGRAPH, + extensions: { + codeblock: CodeBlock, + codeBlock: false, + code: false + } + }); + + const docLength = editor.state.doc.nodeSize - 2; + + editor.commands.setTextSelection({ from: 0, to: docLength }); + editor.commands.toggleCodeBlock(); + editor.commands.updateAttributes(CodeBlock.name, { language: "javascript" }); + + await new Promise((resolve) => setTimeout(resolve, 100)); + + expect(editorElement.outerHTML).toMatchSnapshot(); + + const docJSON = editor.state.doc.toJSON(); + const content = docJSON.content; + const codeBlockNodes = content.filter( + (node: DocumentNode) => node.type === "codeblock" + ); + const otherNodes = content.filter( + (node: DocumentNode) => node.type !== "codeblock" + ); + + expect(codeBlockNodes).toHaveLength(1); + expect(otherNodes).toHaveLength(0); +}); + +test("Toggling from a codeblock should make codeblock disappear", async () => { + const editorElement = document.createElement("div"); + const { editor } = createEditor({ + element: editorElement, + initialContent: CODEBLOCKS_HTML, + extensions: { + codeblock: CodeBlock, + codeBlock: false, + code: false + } + }); + + const docLength = editor.state.doc.nodeSize - 2; + + editor.commands.setTextSelection({ from: 0, to: docLength }); + + editor.commands.toggleCodeBlock(); + + await new Promise((resolve) => setTimeout(resolve, 100)); + + expect(editorElement.outerHTML).toMatchSnapshot(); + + const docJSON = editor.state.doc.toJSON(); + const content = docJSON.content; + const codeBlockNodes = content.filter( + (node: DocumentNode) => node.type === "codeblock" + ); + const paragraphNodes = content.filter( + (node: DocumentNode) => node.type === "paragraph" + ); + + expect(codeBlockNodes).toHaveLength(0); + expect(paragraphNodes).toHaveLength(2); +});