Skip to content

Commit

Permalink
desktop: fix issues with codeblock toggling
Browse files Browse the repository at this point in the history
Signed-off-by: Sean-Wyn Ng <[email protected]>
  • Loading branch information
seanwynwins committed Sep 16, 2024
1 parent 3fe5352 commit 8e0774e
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 5 deletions.
31 changes: 26 additions & 5 deletions packages/editor/src/extensions/code-block/code-block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,32 @@ export const CodeBlock = Node.create<CodeBlockOptions>({
},
toggleCodeBlock:
(attributes) =>
({ commands }) => {
return commands.toggleNode(this.name, "paragraph", {
...attributes,
id: createCodeblockId()
});
({ commands, state }) => {
const { from, to } = state.selection;

const hasCodeBlock: boolean = this.editor.isActive(this.type.name)
? true
: false;

if (!hasCodeBlock) {
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) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

exports[`Adding a new codeblock & changing the language should apply the new highlighting 1`] = `"<div><div contenteditable="true" translate="no" class="tiptap ProseMirror" tabindex="0"><div class="codeblock-view-content-wrap"><pre class="node-content-wrapper language-xyz" style="white-space: pre; min-width: 20px;"><span class="token keyword">function</span> <span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span></pre></div></div></div>"`;
exports[`Toggling from a codeblock should make codeblock disappear 1`] = `"<div><div contenteditable="true" translate="no" class="tiptap ProseMirror" tabindex="0"><p><span class="token keyword">function</span> <span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span></p><p><span class="token keyword">function</span> <span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span></p></div></div>"`;
exports[`Toggling multiple paragraphs into a codeblock should make one codeblock 1`] = `"<div><div contenteditable="true" translate="no" class="tiptap ProseMirror" tabindex="0"><div class="codeblock-view-content-wrap"><pre class="node-content-wrapper language-xyz" style="white-space: pre; min-width: 20px;"><span class="token keyword">function</span> <span class="token function">helloWorld</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Hello, World!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span></pre></div></div></div>"`;
exports[`codeblocks should get highlighted after pasting 1`] = `"<div><div contenteditable="true" translate="no" class="tiptap ProseMirror" tabindex="0"><div class="codeblock-view-content-wrap"><pre class="node-content-wrapper language-javascript" style="white-space: pre; min-width: 20px;"><span class="token keyword">function</span> <span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span></pre></div><div class="codeblock-view-content-wrap"><pre class="node-content-wrapper language-typescript" style="white-space: pre; min-width: 20px;"><span class="token keyword">function</span> <span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span></pre></div></div></div>"`;
exports[`codeblocks should get highlighted on init 1`] = `"<div><div contenteditable="true" translate="no" class="tiptap ProseMirror" tabindex="0"><div class="codeblock-view-content-wrap"><pre class="node-content-wrapper language-javascript" style="white-space: pre; min-width: 20px;"><span class="token keyword">function</span> <span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span></pre></div><div class="codeblock-view-content-wrap"><pre class="node-content-wrapper language-typescript" style="white-space: pre; min-width: 20px;"><span class="token keyword">function</span> <span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span></pre></div></div></div>"`;
Expand Down
81 changes: 81 additions & 0 deletions packages/editor/src/extensions/code-block/tests/code-block.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down Expand Up @@ -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);
});

0 comments on commit 8e0774e

Please sign in to comment.