[release-2.14] fix: code block content insertion location error (#5773)

* fix: code block content insertion location error

* fix: code block content insertion location error

---------

Co-authored-by: LIlGG <1103069291@qq.com>
pull/5774/head
Halo Dev Bot 2024-04-23 14:33:13 +08:00 committed by GitHub
parent dea79b2154
commit 8de668bb1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 73 additions and 1 deletions

View File

@ -6,7 +6,13 @@ import {
findParentNode,
VueNodeViewRenderer,
} from "@/tiptap/vue-3";
import { EditorState, TextSelection, type Transaction } from "@/tiptap/pm";
import {
EditorState,
Plugin,
PluginKey,
TextSelection,
type Transaction,
} from "@/tiptap/pm";
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
import type { CodeBlockLowlightOptions } from "@tiptap/extension-code-block-lowlight";
import CodeBlockViewRenderer from "./CodeBlockViewRenderer.vue";
@ -237,4 +243,70 @@ export default CodeBlockLowlight.extend<
},
};
},
addProseMirrorPlugins() {
return [
// Solve the paste problem. Because the upstream has not been
// able to deal with this problem for a long time, it is
// handled manually locally.
// see: https://github.com/ueberdosis/tiptap/pull/3606
new Plugin({
key: new PluginKey("codeBlockVSCodeHandlerFixPaste"),
props: {
handlePaste: (view, event) => {
if (!event.clipboardData) {
return false;
}
// dont 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, schema } = view.state;
// add text to code block
// strip carriage return chars from text pasted as code
// see: https://github.com/ProseMirror/prosemirror-view/commit/a50a6bcceb4ce52ac8fcc6162488d8875613aacd
const contentTextNode = schema.text(text.replace(/\r\n?/g, "\n"));
// create an empty code block
tr.replaceSelectionWith(
this.type.create({ language }, contentTextNode)
);
const { selection } = tr;
// Whether the current position is code block, if not, move forward to code block.
let codeBlockPos = Math.max(0, selection.from - 1);
while (
codeBlockPos > 0 &&
tr.doc.resolve(codeBlockPos).parent.type.name !== this.type.name
) {
codeBlockPos--;
}
// put cursor inside the newly created code block
tr.setSelection(TextSelection.near(tr.doc.resolve(codeBlockPos)));
// store meta information
// this is useful for other plugins that depends on the paste event
// like the paste rule plugin
tr.setMeta("paste", true);
view.dispatch(tr);
return true;
},
},
}),
...(this.parent?.() || []),
];
},
});