diff --git a/packages/editor/src/extensions/code-block/code-block.ts b/packages/editor/src/extensions/code-block/code-block.ts index 3d085872c8..c9a704b538 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; + + let hasParagraph = false; + + state.doc.nodesBetween(from, to, (node) => { + if (node.type.name === "paragraph") { + hasParagraph = true; + } }); + + if (hasParagraph) { + return commands.insertContent({ + type: this.name, + attrs: { + ...attributes, + id: createCodeblockId() + }, + content: [ + { + type: "text", + text: state.doc.textBetween(from, to, "\n") + } + ] + }); + } 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 0501ccadf5..6a6ecac4c5 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..deb87e96c1 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,65 @@ 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" + ); + + expect(codeBlockNodes).toHaveLength(1); +}); + +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" + ); + + expect(codeBlockNodes).toHaveLength(0); +});