🎨 Improve right-click menu paste (#15325)

This commit is contained in:
Jeffrey Chen 2025-07-18 10:33:26 +08:00 committed by GitHub
parent f61a0d6f85
commit 0019a6d8d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 27 additions and 10 deletions

View file

@ -3,20 +3,37 @@ import {fetchPost} from "../../util/fetch";
import {Constants} from "../../constants";
export const encodeBase64 = (text: string): string => {
const encoder = new TextEncoder();
const bytes = encoder.encode(text);
return btoa(String.fromCharCode(...bytes));
if (typeof Buffer !== "undefined") {
return Buffer.from(text, "utf8").toString("base64");
} else {
const encoder = new TextEncoder();
const bytes = encoder.encode(text);
let binary = "";
const chunkSize = 0x8000; // 避免栈溢出
for (let i = 0; i < bytes.length; i += chunkSize) {
const chunk = bytes.subarray(i, Math.min(i + chunkSize, bytes.length));
binary += String.fromCharCode.apply(null, chunk);
}
return btoa(binary);
}
};
const getSiyuanHTML = (text: IClipboardData) => {
const siyuanMatch = text.textHTML.match(/<!--siyuan-data:([^>]+)-->/);
const siyuanMatch = text.textHTML.match(/<!--data-siyuan='([^']+)'-->/);
if (siyuanMatch) {
try {
const decoder = new TextDecoder();
const bytes = Uint8Array.from(atob(siyuanMatch[1]), char => char.charCodeAt(0));
text.siyuanHTML = decoder.decode(bytes);
if (typeof Buffer !== "undefined") {
const decodedBytes = Buffer.from(siyuanMatch[1], "base64");
text.siyuanHTML = decodedBytes.toString("utf8");
} else {
const decoder = new TextDecoder();
const bytes = Uint8Array.from(atob(siyuanMatch[1]), char => char.charCodeAt(0));
text.siyuanHTML = decoder.decode(bytes);
}
// 移除注释节点,保持原有的 text/html 内容
text.textHTML = text.textHTML.replace(/<!--siyuan-data:[^>]+-->/, "");
text.textHTML = text.textHTML.replace(/<!--data-siyuan='[^']+'-->/, "");
} catch (e) {
console.log("Failed to decode siyuan data from HTML comment:", e);
}

View file

@ -450,7 +450,7 @@ export class WYSIWYG {
restoreLuteMarkdownSyntax(protyle);
// 在 text/html 中插入注释节点,用于右键菜单粘贴时获取 text/siyuan 数据
event.clipboardData.setData("text/html", `<!--siyuan-data:${encodeBase64(siyuanHTML)}-->` + (selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html)));
event.clipboardData.setData("text/html", `<!--data-siyuan='${encodeBase64(siyuanHTML)}'-->` + (selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html)));
});
this.element.addEventListener("mousedown", (event: MouseEvent) => {
@ -1953,7 +1953,7 @@ export class WYSIWYG {
restoreLuteMarkdownSyntax(protyle);
// 在 text/html 中插入注释节点,用于右键菜单粘贴时获取 text/siyuan 数据
event.clipboardData.setData("text/html", `<!--siyuan-data:${encodeBase64(siyuanHTML)}-->` + (selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html)));
event.clipboardData.setData("text/html", `<!--data-siyuan='${encodeBase64(siyuanHTML)}'-->` + (selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html)));
});
let beforeContextmenuRange: Range;