diff --git a/app/src/protyle/util/compatibility.ts b/app/src/protyle/util/compatibility.ts index 16601362f..9201f7fb8 100644 --- a/app/src/protyle/util/compatibility.ts +++ b/app/src/protyle/util/compatibility.ts @@ -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(//); + const siyuanMatch = text.textHTML.match(//); 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(//, ""); + text.textHTML = text.textHTML.replace(//, ""); } catch (e) { console.log("Failed to decode siyuan data from HTML comment:", e); } diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 1a38c1522..718111696 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -450,7 +450,7 @@ export class WYSIWYG { restoreLuteMarkdownSyntax(protyle); // 在 text/html 中插入注释节点,用于右键菜单粘贴时获取 text/siyuan 数据 - event.clipboardData.setData("text/html", `` + (selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html))); + event.clipboardData.setData("text/html", `` + (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", `` + (selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html))); + event.clipboardData.setData("text/html", `` + (selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html))); }); let beforeContextmenuRange: Range;