From 0e0b0b6a8c1d80ef9084d1913a51dd9bff8a69d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20Ku=CC=88hn?= Date: Tue, 12 Oct 2021 10:20:13 +0200 Subject: [PATCH] fix: add support for pasted content from VS Code, fix #2022 --- packages/extension-code-block/package.json | 3 ++ .../extension-code-block/src/code-block.ts | 49 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/packages/extension-code-block/package.json b/packages/extension-code-block/package.json index e64cd516..9045cf56 100644 --- a/packages/extension-code-block/package.json +++ b/packages/extension-code-block/package.json @@ -23,6 +23,9 @@ "peerDependencies": { "@tiptap/core": "^2.0.0-beta.1" }, + "dependencies": { + "prosemirror-state": "^1.3.4" + }, "repository": { "type": "git", "url": "https://github.com/ueberdosis/tiptap", diff --git a/packages/extension-code-block/src/code-block.ts b/packages/extension-code-block/src/code-block.ts index 125cba0a..c9591de7 100644 --- a/packages/extension-code-block/src/code-block.ts +++ b/packages/extension-code-block/src/code-block.ts @@ -1,4 +1,5 @@ import { Node, textblockTypeInputRule } from '@tiptap/core' +import { Plugin, PluginKey, TextSelection } from 'prosemirror-state' export interface CodeBlockOptions { languageClassPrefix: string, @@ -132,4 +133,52 @@ export const CodeBlock = Node.create({ }), ] }, + + addProseMirrorPlugins() { + return [ + // this plugin creates a code block for pasted content from VS Code + // we can also detect the copied code language + new Plugin({ + key: new PluginKey('codeBlockVSCodeHandler'), + props: { + handlePaste: (view, event) => { + if (!event.clipboardData) { + return false + } + + // don’t create a new code block within code blocks + if (this.editor.isActive(this.type.name)) { + return false + } + + const text = event.clipboardData.getData('text/plain') + const vscode = event.clipboardData.getData('vscode-editor-data') + const vscodeData = vscode + ? JSON.parse(vscode) + : undefined + const language = vscodeData.mode + + if (!text || !language) { + return false + } + + const { tr } = view.state + + // create an empty code block + tr.replaceSelectionWith(this.type.create({ language })) + + // put cursor inside the newly created code block + tr.setSelection(TextSelection.near(tr.doc.resolve(Math.max(0, tr.selection.from - 2)))) + + // add text to code block + tr.insertText(text) + + view.dispatch(tr) + + return true + }, + }, + }), + ] + }, })