mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-27 20:08:49 +01:00
This commit is contained in:
parent
c737ecabb6
commit
901ea823cb
8 changed files with 174 additions and 42 deletions
|
|
@ -1,5 +1,8 @@
|
|||
document.body.insertAdjacentHTML('afterbegin', `<svg style="position: absolute; width: 0; height: 0; overflow: hidden;" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<symbol id="iconPaste" viewBox="0 0 32 32">
|
||||
<path d="M26.714 2.607h-3.616v-1.339c0-0.147-0.12-0.268-0.268-0.268h-1.875c-0.147 0-0.268 0.121-0.268 0.268v1.339h-5.089v-1.339c0-0.147-0.12-0.268-0.268-0.268h-1.875c-0.147 0-0.268 0.121-0.268 0.268v1.339h-3.616c-0.593 0-1.071 0.479-1.071 1.071v4.018h-3.214c-0.593 0-1.071 0.479-1.071 1.071v21.161c0 0.593 0.479 1.071 1.071 1.071h17.143c0.593 0 1.071-0.479 1.071-1.071v-3.214h3.214c0.593 0 1.071-0.479 1.071-1.071v-21.964c0-0.593-0.479-1.071-1.071-1.071zM21.089 28.589h-14.464v-18.482h7.299v5.826c0 0.74 0.599 1.339 1.339 1.339h5.826v11.317zM21.089 15.13h-5.022v-5.022h0.007l5.016 5.016v0.007zM25.375 24.304h-1.875v-10.179l-6.429-6.429h-6.161v-2.679h2.277v1.071c0 0.147 0.12 0.268 0.268 0.268h1.875c0.147 0 0.268-0.12 0.268-0.268v-1.071h5.089v1.071c0 0.147 0.12 0.268 0.268 0.268h1.875c0.147 0 0.268-0.12 0.268-0.268v-1.071h2.277v19.286z"></path>
|
||||
</symbol>
|
||||
<symbol id="iconEmail" viewBox="0 0 32 32">
|
||||
<path d="M29.675 4.429h-27.351c-0.582 0-1.052 0.47-1.052 1.052v21.039c0 0.582 0.47 1.052 1.052 1.052h27.351c0.582 0 1.052-0.47 1.052-1.052v-21.039c0-0.582-0.47-1.052-1.052-1.052zM28.36 8.071v17.134h-24.721v-17.134l-0.907-0.707 1.292-1.66 1.407 1.095h21.141l1.407-1.095 1.292 1.66-0.911 0.707zM26.572 6.795l-10.572 8.218-11.979-9.313-1.292 1.66 0.907 0.707 11.23 8.731c0.308 0.241 0.702 0.387 1.129 0.387s0.821-0.146 1.133-0.39l-0.004 0.003 12.143-9.435-1.292-1.66-1.404 1.091z"></path>
|
||||
</symbol>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@
|
|||
<body>
|
||||
<h2>SiYuan</h2>
|
||||
<div class="fn__clear">
|
||||
<div>
|
||||
<svg>
|
||||
<use xlink:href="#iconPaste"></use>
|
||||
</svg>
|
||||
iconPaste
|
||||
</div>
|
||||
<div>
|
||||
<svg>
|
||||
<use xlink:href="#iconPhone"></use>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
document.body.insertAdjacentHTML('afterbegin', `<svg style="position: absolute; width: 0; height: 0; overflow: hidden;" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<symbol id="iconPaste" viewBox="0 0 32 32">
|
||||
<path d="M25.545 3.727h-5.7c-0.573-1.582-2.073-2.727-3.845-2.727s-3.273 1.145-3.845 2.727h-5.7c-1.5 0-2.727 1.227-2.727 2.727v21.818c0 1.5 1.227 2.727 2.727 2.727h19.091c1.5 0 2.727-1.227 2.727-2.727v-21.818c0-1.5-1.227-2.727-2.727-2.727zM16 3.727c0.75 0 1.364 0.614 1.364 1.364s-0.614 1.364-1.364 1.364-1.364-0.614-1.364-1.364 0.614-1.364 1.364-1.364zM25.545 28.273h-19.091v-21.818h2.727v4.091h13.636v-4.091h2.727v21.818z"></path>
|
||||
</symbol>
|
||||
<symbol id="iconEmail" viewBox="0 0 32 32">
|
||||
<path d="M16 0.925c-8.28 0-15 6.72-15 15s6.72 15 15 15h7.5v-3h-7.5c-6.51 0-12-5.49-12-12s5.49-12 12-12 12 5.49 12 12v2.145c0 1.185-1.065 2.355-2.25 2.355s-2.25-1.17-2.25-2.355v-2.145c0-4.14-3.36-7.5-7.5-7.5s-7.5 3.36-7.5 7.5 3.36 7.5 7.5 7.5c2.070 0 3.96-0.84 5.31-2.205 0.975 1.335 2.655 2.205 4.44 2.205 2.955 0 5.25-2.4 5.25-5.355v-2.145c0-8.28-6.72-15-15-15zM16 20.425c-2.49 0-4.5-2.010-4.5-4.5s2.010-4.5 4.5-4.5 4.5 2.010 4.5 4.5-2.010 4.5-4.5 4.5z"></path>
|
||||
</symbol>
|
||||
|
|
|
|||
|
|
@ -93,11 +93,14 @@
|
|||
|
||||
&__title {
|
||||
border-bottom: .5px solid var(--b3-theme-background-light);
|
||||
line-height: 48px;
|
||||
padding: 0 8px;
|
||||
display: flex;
|
||||
background-color: var(--b3-theme-background);
|
||||
height: 48.5px;
|
||||
|
||||
& > .b3-menu__label {
|
||||
line-height: 32.5px;
|
||||
}
|
||||
}
|
||||
|
||||
&__separator {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@
|
|||
background-color: transparent;
|
||||
height: 29px;
|
||||
box-sizing: border-box;
|
||||
font-size: 0;
|
||||
font-size: 10px;
|
||||
white-space: nowrap;
|
||||
padding: 1px 6px;
|
||||
|
||||
&:focus {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import {copyPlainText, readText, setStorageVal, writeText} from "../protyle/util
|
|||
import {preventScroll} from "../protyle/scroll/preventScroll";
|
||||
import {onGet} from "../protyle/util/onGet";
|
||||
import {getAllModels} from "../layout/getAll";
|
||||
import {pasteAsPlainText, pasteText} from "../protyle/util/paste";
|
||||
import {pasteAsPlainText, pasteEscaped, pasteText} from "../protyle/util/paste";
|
||||
/// #if !MOBILE
|
||||
import {openFileById, updateBacklinkGraph} from "../editor/util";
|
||||
import {openGlobalSearch} from "../search/util";
|
||||
|
|
@ -411,6 +411,9 @@ export const refMenu = (protyle: IProtyle, element: HTMLElement) => {
|
|||
export const contentMenu = (protyle: IProtyle, nodeElement: Element) => {
|
||||
const range = getEditorRange(nodeElement);
|
||||
window.siyuan.menus.menu.remove();
|
||||
/// #if MOBILE
|
||||
protyle.toolbar.showContent(protyle, range, nodeElement);
|
||||
/// #else
|
||||
if (range.toString() !== "" || (range.cloneContents().childNodes[0] as HTMLElement)?.classList?.contains("emoji")) {
|
||||
window.siyuan.menus.menu.append(new MenuItem({
|
||||
icon: "iconCopy",
|
||||
|
|
@ -464,6 +467,7 @@ export const contentMenu = (protyle: IProtyle, nodeElement: Element) => {
|
|||
if (!protyle.disabled) {
|
||||
window.siyuan.menus.menu.append(new MenuItem({
|
||||
label: window.siyuan.languages.paste,
|
||||
icon: "iconPaste",
|
||||
accelerator: "⌘V",
|
||||
async click() {
|
||||
if (document.queryCommandSupported("paste")) {
|
||||
|
|
@ -488,46 +492,14 @@ export const contentMenu = (protyle: IProtyle, nodeElement: Element) => {
|
|||
}).element);
|
||||
window.siyuan.menus.menu.append(new MenuItem({
|
||||
label: window.siyuan.languages.pasteEscaped,
|
||||
async click() {
|
||||
try {
|
||||
// * _ [ ] ! \ ` < > & ~ { } ( ) = # $ ^ |
|
||||
let clipText = await readText();
|
||||
// https://github.com/siyuan-note/siyuan/issues/5446
|
||||
// A\B\C\D\
|
||||
// E
|
||||
// task-blog-2~default~baiduj 无法原义粘贴含有 `~foo~` 的文本 https://github.com/siyuan-note/siyuan/issues/5523
|
||||
|
||||
// 这里必须多加一个反斜杆,因为 Lute 在进行 Markdown 嵌套节点转换平铺标记节点时会剔除 Backslash 节点,
|
||||
// 多加入的一个反斜杆会作为文本节点保留下来,后续 Spin 时刚好用于转义标记符 https://github.com/siyuan-note/siyuan/issues/6341
|
||||
clipText = clipText.replace(/\\/g, "\\\\\\\\")
|
||||
.replace(/\*/g, "\\\\\\*")
|
||||
.replace(/\_/g, "\\\\\\_")
|
||||
.replace(/\[/g, "\\\\\\[")
|
||||
.replace(/\]/g, "\\\\\\]")
|
||||
.replace(/\!/g, "\\\\\\!")
|
||||
.replace(/\`/g, "\\\\\\`")
|
||||
.replace(/\</g, "\\\\\\<")
|
||||
.replace(/\>/g, "\\\\\\>")
|
||||
.replace(/\&/g, "\\\\\\&")
|
||||
.replace(/\~/g, "\\\\\\~")
|
||||
.replace(/\{/g, "\\\\\\{")
|
||||
.replace(/\}/g, "\\\\\\}")
|
||||
.replace(/\(/g, "\\\\\\(")
|
||||
.replace(/\)/g, "\\\\\\)")
|
||||
.replace(/\=/g, "\\\\\\=")
|
||||
.replace(/\#/g, "\\\\\\#")
|
||||
.replace(/\$/g, "\\\\\\$")
|
||||
.replace(/\^/g, "\\\\\\^")
|
||||
.replace(/\|/g, "\\\\\\|");
|
||||
pasteText(protyle, clipText, nodeElement);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
click() {
|
||||
pasteEscaped(protyle, nodeElement);
|
||||
}
|
||||
}).element);
|
||||
}
|
||||
window.siyuan.menus.menu.append(new MenuItem({
|
||||
label: window.siyuan.languages.selectAll,
|
||||
icon: "iconSelect",
|
||||
accelerator: "⌘A",
|
||||
click() {
|
||||
selectAll(protyle, nodeElement, range);
|
||||
|
|
@ -544,6 +516,7 @@ export const contentMenu = (protyle: IProtyle, nodeElement: Element) => {
|
|||
}).element);
|
||||
}
|
||||
}
|
||||
/// #endif
|
||||
if (protyle?.app?.plugins) {
|
||||
emitOpenMenu({
|
||||
plugins: protyle.app.plugins,
|
||||
|
|
@ -669,7 +642,7 @@ export const imgMenu = (protyle: IProtyle, range: Range, assetElement: HTMLEleme
|
|||
iconHTML: "",
|
||||
label: `<textarea style="margin: 4px 0" rows="1" class="b3-text-field fn__size200" placeholder="${window.siyuan.languages.imageURL}">${imgElement.getAttribute("src")}</textarea>`,
|
||||
bind(element) {
|
||||
element.querySelector("textarea").addEventListener("input", (event:InputEvent) => {
|
||||
element.querySelector("textarea").addEventListener("input", (event: InputEvent) => {
|
||||
if (event.isComposing) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {
|
|||
focusByRange,
|
||||
focusByWbr,
|
||||
getEditorRange,
|
||||
getSelectionPosition,
|
||||
getSelectionPosition, selectAll,
|
||||
setFirstNodeRange,
|
||||
setLastNodeRange
|
||||
} from "../util/selection";
|
||||
|
|
@ -15,7 +15,7 @@ import {Link} from "./Link";
|
|||
import {setPosition} from "../../util/setPosition";
|
||||
import {updateTransaction} from "../wysiwyg/transaction";
|
||||
import {Constants} from "../../constants";
|
||||
import {openByMobile, setStorageVal} from "../util/compatibility";
|
||||
import {copyPlainText, openByMobile, readText, setStorageVal} from "../util/compatibility";
|
||||
import {upDownHint} from "../../util/upDownHint";
|
||||
import {highlightRender} from "../render/highlightRender";
|
||||
import {getContenteditableElement, hasNextSibling, hasPreviousSibling} from "../wysiwyg/getBlock";
|
||||
|
|
@ -45,6 +45,7 @@ import {mathRender} from "../render/mathRender";
|
|||
import {linkMenu} from "../../menus/protyle";
|
||||
import {addScript} from "../util/addScript";
|
||||
import {confirmDialog} from "../../dialog/confirmDialog";
|
||||
import {pasteAsPlainText, pasteEscaped, pasteText} from "../util/paste";
|
||||
|
||||
export class Toolbar {
|
||||
public element: HTMLElement;
|
||||
|
|
@ -835,6 +836,7 @@ export class Toolbar {
|
|||
const autoHeight = () => {
|
||||
textElement.style.height = textElement.scrollHeight + "px";
|
||||
if (isMobile()) {
|
||||
setPosition(this.subElement, 0, 0);
|
||||
return;
|
||||
}
|
||||
if (this.subElement.firstElementChild.getAttribute("data-drag") === "true") {
|
||||
|
|
@ -1258,6 +1260,8 @@ export class Toolbar {
|
|||
/// #if !MOBILE
|
||||
const nodeRect = languageElement.getBoundingClientRect();
|
||||
setPosition(this.subElement, nodeRect.left, nodeRect.bottom, nodeRect.height);
|
||||
/// #else
|
||||
setPosition(this.subElement, 0, 0);
|
||||
/// #endif
|
||||
this.element.classList.add("fn__none");
|
||||
inputElement.select();
|
||||
|
|
@ -1434,6 +1438,8 @@ export class Toolbar {
|
|||
const rangePosition = getSelectionPosition(nodeElement, range);
|
||||
setPosition(this.subElement, rangePosition.left, rangePosition.top + 18, Constants.SIZE_TOOLBAR_HEIGHT);
|
||||
(this.subElement.firstElementChild as HTMLElement).style.maxHeight = Math.min(window.innerHeight * 0.8, window.innerHeight - this.subElement.getBoundingClientRect().top) - 16 + "px";
|
||||
/// #else
|
||||
setPosition(this.subElement, 0, 0);
|
||||
/// #endif
|
||||
});
|
||||
}
|
||||
|
|
@ -1499,6 +1505,8 @@ export class Toolbar {
|
|||
/// #if !MOBILE
|
||||
const rangePosition = getSelectionPosition(nodeElement, range);
|
||||
setPosition(this.subElement, rangePosition.left, rangePosition.top + 18, Constants.SIZE_TOOLBAR_HEIGHT);
|
||||
/// #else
|
||||
setPosition(this.subElement, 0, 0);
|
||||
/// #endif
|
||||
});
|
||||
}
|
||||
|
|
@ -1605,6 +1613,8 @@ export class Toolbar {
|
|||
/// #if !MOBILE
|
||||
const rangePosition = getSelectionPosition(nodeElement, range);
|
||||
setPosition(this.subElement, rangePosition.left, rangePosition.top + 18, Constants.SIZE_TOOLBAR_HEIGHT);
|
||||
/// #else
|
||||
setPosition(this.subElement, 0, 0);
|
||||
/// #endif
|
||||
this.element.classList.add("fn__none");
|
||||
inputElement.select();
|
||||
|
|
@ -1621,4 +1631,100 @@ export class Toolbar {
|
|||
this.subElement.querySelector(".b3-list--background").innerHTML = html;
|
||||
});
|
||||
}
|
||||
|
||||
public showContent(protyle: IProtyle, range: Range, nodeElement: Element) {
|
||||
this.range = range;
|
||||
hideElements(["hint"], protyle);
|
||||
|
||||
this.subElement.style.width = "auto";
|
||||
this.subElement.style.padding = "0 8px";
|
||||
let html = ""
|
||||
const hasCopy = range.toString() !== "" || (range.cloneContents().childNodes[0] as HTMLElement)?.classList?.contains("emoji");
|
||||
if (hasCopy) {
|
||||
html += `<button class="protyle-toolbar__item" data-action="copy"><svg><use xlink:href="#iconCopy"></use></svg></button>`
|
||||
if (!protyle.disabled) {
|
||||
html += `<button class="protyle-toolbar__item" data-action="cut"><svg><use xlink:href="#iconCut"></use></svg></button>
|
||||
<button class="protyle-toolbar__item" data-action="delete"><svg><use xlink:href="#iconTrashcan"></use></svg></button>`
|
||||
}
|
||||
}
|
||||
if (!protyle.disabled) {
|
||||
html += `<button class="protyle-toolbar__item" data-action="paste"><svg><use xlink:href="#iconPaste"></use></svg></button>
|
||||
<button class="protyle-toolbar__item" data-action="select"><svg><use xlink:href="#iconSelect"></use></svg></button>`
|
||||
}
|
||||
if (hasCopy || !protyle.disabled) {
|
||||
html += `<button class="protyle-toolbar__item" data-action="more"><svg><use xlink:href="#iconMore"></use></svg></button>`
|
||||
}
|
||||
this.subElement.innerHTML = `<div class="fn__flex">${html}</div>`;
|
||||
this.subElement.lastElementChild.addEventListener("click", async (event) => {
|
||||
const btnElemen = hasClosestByClassName(event.target as HTMLElement, "protyle-toolbar__item");
|
||||
if (!btnElemen) {
|
||||
return
|
||||
}
|
||||
const action = btnElemen.getAttribute("data-action");
|
||||
if (action === "copy") {
|
||||
focusByRange(getEditorRange(nodeElement));
|
||||
document.execCommand("copy");
|
||||
this.subElement.classList.add("fn__none");
|
||||
} else if (action === "cut") {
|
||||
focusByRange(getEditorRange(nodeElement));
|
||||
document.execCommand("cut");
|
||||
this.subElement.classList.add("fn__none");
|
||||
} else if (action === "delete") {
|
||||
const currentRange = getEditorRange(nodeElement);
|
||||
currentRange.insertNode(document.createElement("wbr"));
|
||||
const oldHTML = nodeElement.outerHTML;
|
||||
currentRange.extractContents();
|
||||
focusByWbr(nodeElement, currentRange);
|
||||
focusByRange(currentRange);
|
||||
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, oldHTML);
|
||||
this.subElement.classList.add("fn__none");
|
||||
} else if (action === "paste") {
|
||||
if (document.queryCommandSupported("paste")) {
|
||||
document.execCommand("paste");
|
||||
} else {
|
||||
try {
|
||||
const clipText = await readText();
|
||||
pasteText(protyle, clipText, nodeElement);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
this.subElement.classList.add("fn__none");
|
||||
} else if (action === "select") {
|
||||
selectAll(protyle, nodeElement, range);
|
||||
this.subElement.classList.add("fn__none");
|
||||
} else if (action === "copyPlainText") {
|
||||
focusByRange(getEditorRange(nodeElement));
|
||||
const cloneContents = getSelection().getRangeAt(0).cloneContents();
|
||||
cloneContents.querySelectorAll('[data-type="backslash"]').forEach(item => {
|
||||
item.firstElementChild.remove();
|
||||
});
|
||||
copyPlainText(cloneContents.textContent);
|
||||
this.subElement.classList.add("fn__none");
|
||||
} else if (action === "pasteAsPlainText") {
|
||||
focusByRange(getEditorRange(nodeElement));
|
||||
pasteAsPlainText(protyle);
|
||||
this.subElement.classList.add("fn__none");
|
||||
} else if (action === "pasteEscaped") {
|
||||
pasteEscaped(protyle, nodeElement);
|
||||
this.subElement.classList.add("fn__none");
|
||||
} else if (action === "back") {
|
||||
this.subElement.lastElementChild.innerHTML = html;
|
||||
} else if (action === "more") {
|
||||
this.subElement.lastElementChild.innerHTML = `<button class="protyle-toolbar__item${hasCopy ? "" : " fn__none"}" data-action="copyPlainText">${window.siyuan.languages.copyPlainText}</button>
|
||||
<div class="protyle-toolbar__divider${hasCopy ? "" : " fn__none"}"></div>
|
||||
<button class="protyle-toolbar__item${protyle.disabled ? " fn__none" : ""}" data-action="pasteAsPlainText">${window.siyuan.languages.pasteAsPlainText}</button>
|
||||
<div class="protyle-toolbar__divider${protyle.disabled ? " fn__none" : ""}"></div>
|
||||
<button class="protyle-toolbar__item${protyle.disabled ? " fn__none" : ""}" data-action="pasteEscaped">${window.siyuan.languages.pasteEscaped}</button>
|
||||
<div class="protyle-toolbar__divider${protyle.disabled ? " fn__none" : ""}"></div>
|
||||
<button class="protyle-toolbar__item" data-action="back"><svg><use xlink:href="#iconBack"></use></svg></button>`
|
||||
setPosition(this.subElement, rangePosition.left, rangePosition.top + 18, Constants.SIZE_TOOLBAR_HEIGHT);
|
||||
}
|
||||
});
|
||||
this.subElement.classList.remove("fn__none");
|
||||
this.subElementCloseCB = undefined;
|
||||
this.element.classList.add("fn__none");
|
||||
const rangePosition = getSelectionPosition(nodeElement, range);
|
||||
setPosition(this.subElement, rangePosition.left, rangePosition.top + 18, Constants.SIZE_TOOLBAR_HEIGHT);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import {Constants} from "../../constants";
|
||||
import {uploadFiles, uploadLocalFiles} from "../upload";
|
||||
import {processPasteCode, processRender} from "./processCode";
|
||||
import {writeText} from "./compatibility";
|
||||
import {readText, writeText} from "./compatibility";
|
||||
/// #if !BROWSER
|
||||
import {clipboard} from "electron";
|
||||
/// #endif
|
||||
|
|
@ -16,6 +16,43 @@ import {scrollCenter} from "../../util/highlightById";
|
|||
import {hideElements} from "../ui/hideElements";
|
||||
import {avRender} from "../render/av/render";
|
||||
|
||||
export const pasteEscaped = async (protyle:IProtyle, nodeElement:Element) => {
|
||||
try {
|
||||
// * _ [ ] ! \ ` < > & ~ { } ( ) = # $ ^ |
|
||||
let clipText = await readText();
|
||||
// https://github.com/siyuan-note/siyuan/issues/5446
|
||||
// A\B\C\D\
|
||||
// E
|
||||
// task-blog-2~default~baiduj 无法原义粘贴含有 `~foo~` 的文本 https://github.com/siyuan-note/siyuan/issues/5523
|
||||
|
||||
// 这里必须多加一个反斜杆,因为 Lute 在进行 Markdown 嵌套节点转换平铺标记节点时会剔除 Backslash 节点,
|
||||
// 多加入的一个反斜杆会作为文本节点保留下来,后续 Spin 时刚好用于转义标记符 https://github.com/siyuan-note/siyuan/issues/6341
|
||||
clipText = clipText.replace(/\\/g, "\\\\\\\\")
|
||||
.replace(/\*/g, "\\\\\\*")
|
||||
.replace(/\_/g, "\\\\\\_")
|
||||
.replace(/\[/g, "\\\\\\[")
|
||||
.replace(/\]/g, "\\\\\\]")
|
||||
.replace(/\!/g, "\\\\\\!")
|
||||
.replace(/\`/g, "\\\\\\`")
|
||||
.replace(/\</g, "\\\\\\<")
|
||||
.replace(/\>/g, "\\\\\\>")
|
||||
.replace(/\&/g, "\\\\\\&")
|
||||
.replace(/\~/g, "\\\\\\~")
|
||||
.replace(/\{/g, "\\\\\\{")
|
||||
.replace(/\}/g, "\\\\\\}")
|
||||
.replace(/\(/g, "\\\\\\(")
|
||||
.replace(/\)/g, "\\\\\\)")
|
||||
.replace(/\=/g, "\\\\\\=")
|
||||
.replace(/\#/g, "\\\\\\#")
|
||||
.replace(/\$/g, "\\\\\\$")
|
||||
.replace(/\^/g, "\\\\\\^")
|
||||
.replace(/\|/g, "\\\\\\|");
|
||||
pasteText(protyle, clipText, nodeElement);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
const filterClipboardHint = (protyle: IProtyle, textPlain: string) => {
|
||||
let needRender = true;
|
||||
protyle.options.hint.extend.find(item => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue