diff --git a/app/src/boot/globalEvent/click.ts b/app/src/boot/globalEvent/click.ts
index 60dd899fa..86ae3edef 100644
--- a/app/src/boot/globalEvent/click.ts
+++ b/app/src/boot/globalEvent/click.ts
@@ -7,7 +7,7 @@ import {isWindow} from "../../util/functions";
import {writeText} from "../../protyle/util/compatibility";
import {showMessage} from "../../dialog/message";
import {cancelDrag} from "./dragover";
-import {nbsp2space} from "../../protyle/util/nbsp2space";
+import {nbsp2space, removeZWJ} from "../../protyle/util/normalizeText";
export const globalClickHideMenu = (element: HTMLElement) => {
if (!window.siyuan.menus.menu.element.contains(element) && !hasClosestByAttribute(element, "data-menu", "true")) {
@@ -42,11 +42,7 @@ export const globalClick = (event: MouseEvent & { target: HTMLElement }) => {
const copyElement = hasTopClosestByClassName(event.target, "protyle-action__copy");
if (copyElement) {
- let text = copyElement.parentElement.nextElementSibling.textContent.replace(/\n$/, "");
- text = nbsp2space(text) // Replace non-breaking spaces with normal spaces when copying https://github.com/siyuan-note/siyuan/issues/9382
- // https://github.com/siyuan-note/siyuan/issues/14800
- text = text.replace(/\u200D```/g, "```");
- writeText(text);
+ writeText(removeZWJ(nbsp2space(copyElement.parentElement.nextElementSibling.textContent.replace(/\n$/, ""))));
showMessage(window.siyuan.languages.copied, 2000);
event.preventDefault();
return;
diff --git a/app/src/mobile/index.ts b/app/src/mobile/index.ts
index 639ef5d64..d0c91ea77 100644
--- a/app/src/mobile/index.ts
+++ b/app/src/mobile/index.ts
@@ -30,7 +30,7 @@ import {mobileKeydown} from "./util/keydown";
import {correctHotkey} from "../boot/globalEvent/commonHotkey";
import {processIOSPurchaseResponse} from "../util/iOSPurchase";
import {updateControlAlt} from "../protyle/util/hotKey";
-import {nbsp2space} from "../protyle/util/nbsp2space";
+import {nbsp2space} from "../protyle/util/normalizeText";
class App {
public plugins: import("../plugin").Plugin[] = [];
diff --git a/app/src/protyle/export/index.ts b/app/src/protyle/export/index.ts
index f43fa96fd..d4522c65b 100644
--- a/app/src/protyle/export/index.ts
+++ b/app/src/protyle/export/index.ts
@@ -530,10 +530,7 @@ ${getIconScript(servePath)}
return;
}
} else if (target.classList.contains("protyle-action__copy")) {
- let text = target.parentElement.nextElementSibling.textContent.trimEnd();
- text = text.replace(/\u00A0/g, " "); // Replace non-breaking spaces with normal spaces when copying https://github.com/siyuan-note/siyuan/issues/9382
- text = text.replace(/\u200D\`\`\`/g, "\`\`\`");
- navigator.clipboard.writeText(text);
+ navigator.clipboard.writeText(target.parentElement.nextElementSibling.textContent.trimEnd().replace(/\u00A0/g, " ").replace(/\u200D\`\`\`/g, "\`\`\`"));
event.preventDefault();
event.stopPropagation();
break;
@@ -824,10 +821,7 @@ ${getIconScript(servePath)}
Protyle.plantumlRender(previewElement, "stage/protyle");
document.querySelectorAll(".protyle-action__copy").forEach((item) => {
item.addEventListener("click", (event) => {
- let text = item.parentElement.nextElementSibling.textContent.trimEnd();
- text = text.replace(/\u00A0/g, " "); // Replace non-breaking spaces with normal spaces when copying
- text = text.replace(/\u200D\`\`\`/g, "\`\`\`");
- navigator.clipboard.writeText(text);
+ navigator.clipboard.writeText(item.parentElement.nextElementSibling.textContent.trimEnd().replace(/\u00A0/g, " ").replace(/\u200D\`\`\`/g, "\`\`\`"));
event.preventDefault();
event.stopPropagation();
})
diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts
index 8916eb4f8..0b2ff89c2 100644
--- a/app/src/protyle/gutter/index.ts
+++ b/app/src/protyle/gutter/index.ts
@@ -69,7 +69,7 @@ import {replaceLocalPath} from "../../editor/rename";
import {showMessage} from "../../dialog/message";
import {checkFold} from "../../util/noRelyPCFunction";
import {clearSelect} from "../util/clear";
-import {nbsp2space} from "../util/nbsp2space";
+import {nbsp2space} from "../util/normalizeText";
export class Gutter {
public element: HTMLElement;
@@ -779,10 +779,7 @@ export class Gutter {
selectsElement.forEach((item: HTMLElement) => {
html += getPlainText(item) + "\n";
});
- let plainText = html.trimEnd();
- // https://github.com/siyuan-note/siyuan/issues/14800
- plainText = plainText.replace(/\u200D```/g, "```");
- copyPlainText(plainText);
+ copyPlainText(html.trimEnd());
focusBlock(selectsElement[0]);
}
}, {
@@ -1353,12 +1350,7 @@ export class Gutter {
label: window.siyuan.languages.copyPlainText,
accelerator: window.siyuan.config.keymap.editor.general.copyPlainText.custom,
click() {
- let plainText = getPlainText(nodeElement as HTMLElement).trimEnd();
- if (type === "NodeCodeBlock") {
- // https://github.com/siyuan-note/siyuan/issues/14800
- plainText = plainText.replace(/\u200D```/g, "```");
- }
- copyPlainText(plainText);
+ copyPlainText(getPlainText(nodeElement as HTMLElement).trimEnd());
focusBlock(nodeElement);
}
}, {
diff --git a/app/src/protyle/header/Title.ts b/app/src/protyle/header/Title.ts
index 7283125b6..3da8e6d9c 100644
--- a/app/src/protyle/header/Title.ts
+++ b/app/src/protyle/header/Title.ts
@@ -20,7 +20,7 @@ import {openFileById} from "../../editor/util";
import {setTitle} from "../../dialog/processSystem";
import {getContenteditableElement, getNoContainerElement} from "../wysiwyg/getBlock";
import {commonHotkey} from "../wysiwyg/commonHotkey";
-import {nbsp2space} from "../util/nbsp2space";
+import {nbsp2space} from "../util/normalizeText";
import {genEmptyElement} from "../../block/util";
import {transaction} from "../wysiwyg/transaction";
import {hideTooltip} from "../../dialog/tooltip";
diff --git a/app/src/protyle/util/nbsp2space.ts b/app/src/protyle/util/nbsp2space.ts
deleted file mode 100644
index 704606471..000000000
--- a/app/src/protyle/util/nbsp2space.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export const nbsp2space = (text: string) => {
- // 非打断空格转换为空格
- return text.replace(/\u00A0/g, " ");
-};
diff --git a/app/src/protyle/util/normalizeText.ts b/app/src/protyle/util/normalizeText.ts
new file mode 100644
index 000000000..7d4c86688
--- /dev/null
+++ b/app/src/protyle/util/normalizeText.ts
@@ -0,0 +1,10 @@
+// https://github.com/siyuan-note/siyuan/issues/9382
+export const nbsp2space = (text: string) => {
+ // 非打断空格转换为空格
+ return text.replace(/\u00A0/g, " ");
+};
+
+// https://github.com/siyuan-note/siyuan/issues/14800
+export const removeZWJ = (text: string) => {
+ return text.replace(/\u200D```/g, "```");
+};
diff --git a/app/src/protyle/util/paste.ts b/app/src/protyle/util/paste.ts
index 4f8ef59ae..cb59b8a33 100644
--- a/app/src/protyle/util/paste.ts
+++ b/app/src/protyle/util/paste.ts
@@ -15,6 +15,7 @@ import {avRender} from "../render/av/render";
import {cellScrollIntoView, getCellText} from "../render/av/cell";
import {getCalloutInfo, getContenteditableElement} from "../wysiwyg/getBlock";
import {clearBlockElement} from "./clear";
+import {removeZWJ} from "./normalizeText";
export const getTextStar = (blockElement: HTMLElement, contentOnly = false) => {
const dataType = blockElement.dataset.type;
@@ -81,8 +82,10 @@ export const getPlainText = (blockElement: HTMLElement, isNested = false) => {
} else if (blockElement.classList.contains("render-node")) {
// 需在嵌入块后,代码块前
text += Lute.UnEscapeHTMLStr(blockElement.getAttribute("data-content"));
- } else if (["NodeHeading", "NodeParagraph", "NodeCodeBlock"].includes(dataType)) {
+ } else if (["NodeHeading", "NodeParagraph"].includes(dataType)) {
text += blockElement.querySelector("[spellcheck]").textContent;
+ } else if ("NodeCodeBlock" === dataType) {
+ text += removeZWJ(blockElement.querySelector("[spellcheck]").textContent);
} else if (dataType === "NodeTable") {
blockElement.querySelectorAll("th, td").forEach((item) => {
text += item.textContent.trim() + "\t";
@@ -159,7 +162,7 @@ export const pasteAsPlainText = async (protyle: IProtyle) => {
if (getSelection().rangeCount > 0) {
const range = getSelection().getRangeAt(0);
if (hasClosestByAttribute(range.startContainer, "data-type", "code") || hasClosestByClassName(range.startContainer, "hljs")) {
- insertHTML(textPlain.replace(/```/g, "\u200D```"), protyle);
+ insertHTML(removeZWJ(textPlain).replace(/```/g, "\u200D```"), protyle);
return;
}
}
@@ -361,7 +364,7 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
if (nodeElement.getAttribute("data-type") === "NodeCodeBlock" ||
protyle.toolbar.getCurrentType(range).includes("code")) {
// https://github.com/siyuan-note/siyuan/issues/13552
- insertHTML(textPlain.replace(/```/g, "\u200D```"), protyle);
+ insertHTML(removeZWJ(textPlain).replace(/```/g, "\u200D```"), protyle);
return;
} else if (siyuanHTML) {
// 编辑器内部粘贴
diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts
index 21dac5ef2..75fae5ef6 100644
--- a/app/src/protyle/wysiwyg/index.ts
+++ b/app/src/protyle/wysiwyg/index.ts
@@ -102,7 +102,7 @@ import {openGalleryItemMenu} from "../render/av/gallery/util";
import {clearSelect} from "../util/clear";
import {chartRender} from "../render/chartRender";
import {updateCalloutType} from "./callout";
-import {nbsp2space} from "../util/nbsp2space";
+import {nbsp2space, removeZWJ} from "../util/normalizeText";
export class WYSIWYG {
public lastHTMLs: { [key: string]: string } = {};
@@ -470,8 +470,7 @@ export class WYSIWYG {
if (isEndOfBlock(range)) {
textPlain = textPlain.replace(/\n$/, "");
}
- // https://github.com/siyuan-note/siyuan/issues/14800
- textPlain = textPlain.replace(/\u200D```/g, "```");
+ textPlain = removeZWJ(textPlain);
isInCodeBlock = true;
} else if (hasClosestByTag(range.startContainer, "TD") || hasClosestByTag(range.startContainer, "TH")) {
tempElement.innerHTML = tempElement.innerHTML.replace(/
/g, "\n").replace(/
/g, "\n");
@@ -2043,9 +2042,7 @@ export class WYSIWYG {
// https://github.com/siyuan-note/siyuan/issues/10722
if (hasClosestByAttribute(range.startContainer, "data-type", "NodeCodeBlock") ||
hasClosestByTag(range.startContainer, "CODE")) {
- textPlain = tempElement.textContent.replace(Constants.ZWSP, "");
- // https://github.com/siyuan-note/siyuan/issues/14800
- textPlain = textPlain.replace(/\u200D```/g, "```");
+ textPlain = removeZWJ(tempElement.textContent.replace(Constants.ZWSP, ""));
isInCodeBlock = true;
}
// https://github.com/siyuan-note/siyuan/issues/4321