diff --git a/app/src/menus/protyle.ts b/app/src/menus/protyle.ts index 7eefbb43f..a5e0cf163 100644 --- a/app/src/menus/protyle.ts +++ b/app/src/menus/protyle.ts @@ -302,26 +302,6 @@ export const contentMenu = (protyle: IProtyle, nodeElement: Element) => { copyPlainText(cloneContents.textContent); } }).element); - window.siyuan.menus.menu.append(new MenuItem({ - label: window.siyuan.languages.copy + " HTML", - click() { - focusByRange(getEditorRange(nodeElement)); - let html = ""; - getSelection().getRangeAt(0).cloneContents().childNodes.forEach(item => { - if (item.nodeType === 3) { - html += item.textContent; - } else { - html += (item as Element).outerHTML; - } - }); - if (protyle.disabled) { - html = getEnableHTML(html); - } - const tempElement = document.createElement("template"); - tempElement.innerHTML = protyle.lute.BlockDOM2HTML(html); - writeText(tempElement.content.firstElementChild.innerHTML); - } - }).element); if (protyle.disabled) { return; } diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts index 5324cd36b..666e5dea6 100644 --- a/app/src/protyle/gutter/index.ts +++ b/app/src/protyle/gutter/index.ts @@ -601,18 +601,6 @@ export class Gutter { }); copyPlainText(html.trimEnd()); } - }, { - label: window.siyuan.languages.copy + " HTML", - click() { - let html = ""; - selectsElement.forEach(item => { - html += item.outerHTML; - }); - if (protyle.disabled) { - html = getEnableHTML(html); - } - writeText(protyle.lute.BlockDOM2HTML(html)); - } }, { label: window.siyuan.languages.duplicate, accelerator: window.siyuan.config.keymap.editor.general.duplicate.custom, @@ -989,15 +977,6 @@ export class Gutter { }); copyPlainText(text.trimEnd()); } - }, { - label: window.siyuan.languages.copy + " HTML", - click() { - let html = nodeElement.outerHTML; - if (protyle.disabled) { - html = getEnableHTML(html); - } - writeText(protyle.lute.BlockDOM2HTML(html)); - } }, { label: window.siyuan.languages.duplicate, accelerator: window.siyuan.config.keymap.editor.general.duplicate.custom, diff --git a/app/src/protyle/util/paste.ts b/app/src/protyle/util/paste.ts index bc8e691d4..567f23067 100644 --- a/app/src/protyle/util/paste.ts +++ b/app/src/protyle/util/paste.ts @@ -86,25 +86,24 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven event.preventDefault(); let textHTML; let textPlain; + let siyuanHTML; let files; if ("clipboardData" in event) { textHTML = event.clipboardData.getData("text/html"); textPlain = event.clipboardData.getData("text/plain"); + siyuanHTML = event.clipboardData.getData("text/siyuan"); files = event.clipboardData.files; } else { textHTML = event.dataTransfer.getData("text/html"); textPlain = event.dataTransfer.getData("text/plain"); + siyuanHTML = event.dataTransfer.getData("text/siyuan"); if (event.dataTransfer.types[0] === "Files") { files = event.dataTransfer.items; } } - // 复制标题及其下方块使用 writeText,需将 textPLain 转换为 textHTML - if (textPlain.endsWith(Constants.ZWSP) && !textHTML) { - textHTML = textPlain; - } /// #if !BROWSER // 不再支持 PC 浏览器 https://github.com/siyuan-note/siyuan/issues/7206 - if (!textHTML && !textPlain && ("clipboardData" in event)) { + if (!siyuanHTML && !textHTML && !textPlain && ("clipboardData" in event)) { if ("darwin" === window.siyuan.config.system.os) { const xmlString = clipboard.read("NSFilenamesPboardType"); const domParser = new DOMParser(); @@ -136,9 +135,12 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven `${textPlain}`) { textHTML = ""; } - + // 复制标题及其下方块使用 writeText,需将 textPlain 转换为 textHTML + if (textPlain.endsWith(Constants.ZWSP) && !textHTML && !siyuanHTML) { + siyuanHTML = textPlain.substr(0, textPlain.length - 1); + } // 剪切复制中首位包含空格或仅有空格 https://github.com/siyuan-note/siyuan/issues/5667 - if (!textHTML.endsWith(Constants.ZWSP) && !textHTML.startsWith(Constants.ZWSP)) { + if (!siyuanHTML) { // process word const doc = new DOMParser().parseFromString(textHTML, "text/html"); if (doc.body && doc.body.innerHTML) { @@ -148,10 +150,9 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven if (textHTML.startsWith("\n") && textHTML.endsWith("\n\n")) { textHTML = doc.body.innerHTML.trim().replace("", "").replace("", ""); } + textHTML = Lute.Sanitize(textHTML); } - textHTML = Lute.Sanitize(textHTML); - const nodeElement = hasClosestBlock(event.target); if (!nodeElement) { if (files && files.length > 0) { @@ -165,8 +166,29 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven }); const code = processPasteCode(textHTML, textPlain); const range = getEditorRange(protyle.wysiwyg.element); - // process code - if (nodeElement.getAttribute("data-type") === "NodeCodeBlock") { + if (siyuanHTML) { + // 编辑器内部粘贴 + const tempElement = document.createElement("div") + tempElement.innerHTML = siyuanHTML + let isBlock = false; + tempElement.querySelectorAll("[data-node-id]").forEach((e) => { + const newId = Lute.NewNodeID(); + e.setAttribute("data-node-id", newId); + e.classList.remove("protyle-wysiwyg--select", "protyle-wysiwyg--hl"); + e.setAttribute("updated", newId.split("-")[0]); + isBlock = true; + }); + if (nodeElement.classList.contains("table")) { + isBlock = false; + } + // 从历史中复制后粘贴 + tempElement.querySelectorAll('[contenteditable="false"][spellcheck]').forEach((e) => { + e.setAttribute("contenteditable", "true"); + }); + const tempInnerHTML = tempElement.innerHTML; + insertHTML(tempInnerHTML, protyle, isBlock); + filterClipboardHint(protyle, tempInnerHTML); + } else if (nodeElement.getAttribute("data-type") === "NodeCodeBlock") { // 粘贴在代码位置 insertHTML(textPlain, protyle); return; @@ -213,77 +235,34 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven } if (isHTML) { const tempElement = document.createElement("div"); - if (textHTML.startsWith(Constants.ZWSP)) { - // 剪切块内容后粘贴 - // mac 复制后会带有 https://github.com/siyuan-note/siyuan/issues/5751 - tempElement.innerHTML = textHTML.substr(1).replace('', ""); - let isBlock = false; - tempElement.querySelectorAll("[data-node-id]").forEach((e) => { - const newId = Lute.NewNodeID(); - e.setAttribute("data-node-id", newId); - e.classList.remove("protyle-wysiwyg--select", "protyle-wysiwyg--hl"); - e.setAttribute("updated", newId.split("-")[0]); - isBlock = true; - }); - if (nodeElement.classList.contains("table")) { - isBlock = false; + tempElement.innerHTML = textHTML; + tempElement.querySelectorAll("[style]").forEach((e) => { + e.removeAttribute("style"); + }); + // 移除空的 A 标签 + tempElement.querySelectorAll("a").forEach((e) => { + if (e.innerHTML.trim() === "") { + e.remove(); } - insertHTML(tempElement.innerHTML, protyle, isBlock); - // 转换为 md,避免再次粘贴 ID 重复 - const tempMd = protyle.lute.BlockDOM2StdMd(tempElement.innerHTML); - writeText(tempMd); - filterClipboardHint(protyle, tempMd); - } else if (textHTML.endsWith(Constants.ZWSP)) { - // 编辑器内部粘贴 - tempElement.innerHTML = textHTML.substr(0, textHTML.length - 1).replace('', ""); - let isBlock = false; - tempElement.querySelectorAll("[data-node-id]").forEach((e) => { - const newId = Lute.NewNodeID(); - e.setAttribute("data-node-id", newId); - e.classList.remove("protyle-wysiwyg--select", "protyle-wysiwyg--hl"); - e.setAttribute("updated", newId.split("-")[0]); - isBlock = true; - }); - if (nodeElement.classList.contains("table")) { - isBlock = false; - } - // 从历史中复制后粘贴 - tempElement.querySelectorAll('[contenteditable="false"][spellcheck]').forEach((e) => { - e.setAttribute("contenteditable", "true"); - }); - const tempInnerHTML = tempElement.innerHTML; - insertHTML(tempInnerHTML, protyle, isBlock); - filterClipboardHint(protyle, tempInnerHTML); - } else { - tempElement.innerHTML = textHTML; - tempElement.querySelectorAll("[style]").forEach((e) => { - e.removeAttribute("style"); - }); - // 移除空的 A 标签 - tempElement.querySelectorAll("a").forEach((e) => { - if (e.innerHTML.trim() === "") { - e.remove(); + }); + fetchPost("/api/lute/html2BlockDOM", { + dom: tempElement.innerHTML + }, (response) => { + insertHTML(response.data, protyle); + protyle.wysiwyg.element.querySelectorAll('[data-type~="block-ref"]').forEach(item => { + if (item.textContent === "") { + fetchPost("/api/block/getRefText", {id: item.getAttribute("data-id")}, (response) => { + item.innerHTML = response.data; + }); } }); - fetchPost("/api/lute/html2BlockDOM", { - dom: tempElement.innerHTML - }, (response) => { - insertHTML(response.data, protyle); - protyle.wysiwyg.element.querySelectorAll('[data-type~="block-ref"]').forEach(item => { - if (item.textContent === "") { - fetchPost("/api/block/getRefText", {id: item.getAttribute("data-id")}, (response) => { - item.innerHTML = response.data; - }); - } - }); - blockRender(protyle, protyle.wysiwyg.element); - processRender(protyle.wysiwyg.element); - highlightRender(protyle.wysiwyg.element); - filterClipboardHint(protyle, response.data); - scrollCenter(protyle); - }); - return; - } + blockRender(protyle, protyle.wysiwyg.element); + processRender(protyle.wysiwyg.element); + highlightRender(protyle.wysiwyg.element); + filterClipboardHint(protyle, response.data); + scrollCenter(protyle); + }); + return; } else if (files && files.length > 0) { uploadFiles(protyle, files); } else if (textPlain.trim() !== "" && files && files.length === 0) { diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 8644abded..93f5da5de 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -281,7 +281,8 @@ export class WYSIWYG { html = getEnableHTML(html); } event.clipboardData.setData("text/plain", textPlain || protyle.lute.BlockDOM2StdMd(html).trimEnd()); - event.clipboardData.setData("text/html", html + Constants.ZWSP); + event.clipboardData.setData("text/html", protyle.lute.BlockDOM2HTML(html)); + event.clipboardData.setData("text/siyuan", html); }); this.element.addEventListener("mousedown", (event: MouseEvent) => { if (event.button === 2 || window.siyuan.ctrlIsPressed) { @@ -1115,7 +1116,8 @@ export class WYSIWYG { } protyle.hint.render(protyle); event.clipboardData.setData("text/plain", protyle.lute.BlockDOM2StdMd(html).trimEnd()); // 需要 trimEnd,否则 \n 会导致 https://github.com/siyuan-note/siyuan/issues/6218 - event.clipboardData.setData("text/html", Constants.ZWSP + html); + event.clipboardData.setData("text/html", protyle.lute.BlockDOM2HTML(html)); + event.clipboardData.setData("text/siyuan", html); }); let beforeContextmenuRange: Range;