diff --git a/app/src/assets/scss/component/_typography.scss b/app/src/assets/scss/component/_typography.scss
index e8ab2561b..592731d87 100644
--- a/app/src/assets/scss/component/_typography.scss
+++ b/app/src/assets/scss/component/_typography.scss
@@ -259,7 +259,7 @@
display: inline-block !important;
position: absolute !important;
width: 1px !important;
- right: 0 !important;
+ right: 6px !important;
outline: 0 !important;
background: 0 0 !important;
text-decoration: initial !important;
@@ -487,6 +487,10 @@
right: 4px;
top: 4px;
display: flex;
+
+ &--show {
+ opacity: .86;
+ }
}
&-icon {
diff --git a/app/src/assets/scss/protyle/_wysiwyg.scss b/app/src/assets/scss/protyle/_wysiwyg.scss
index 8855ef668..66c5f3fb7 100644
--- a/app/src/assets/scss/protyle/_wysiwyg.scss
+++ b/app/src/assets/scss/protyle/_wysiwyg.scss
@@ -243,6 +243,10 @@
&.render-node {
min-height: 32px;
+ &:hover > .protyle-icons {
+ opacity: .86;
+ }
+
&[data-type="NodeBlockQueryEmbed"] {
background-color: var(--b3-theme-surface);
border-left: 1px dashed var(--b3-theme-surface-lighter);
@@ -616,23 +620,19 @@
}
}
- .img:hover .protyle-icons,
- .render-node:hover > .protyle-icons,
- .protyle-icons--show {
+ .img:hover .protyle-icons {
opacity: .86;
}
.render-node .img:hover .protyle-icons,
.render-node .render-node:hover > .protyle-icons {
- opacity: 0;
- }
-}
-
-// https://ld246.com/article/1708826665603
-.protyle-wysiwyg[contenteditable="false"] {
- .img:hover .protyle-icons,
- .render-node:hover > .protyle-icons,
- .protyle-icons--show {
+ display: none;
+ }
+}
+
+.protyle-wysiwyg:not([custom-sy-readonly]),
+.protyle-wysiwyg[custom-sy-readonly="true"] {
+ .img:hover .protyle-icons {
display: none;
}
}
diff --git a/app/src/boot/globalEvent/event.ts b/app/src/boot/globalEvent/event.ts
index 098a91f6b..a613b975d 100644
--- a/app/src/boot/globalEvent/event.ts
+++ b/app/src/boot/globalEvent/event.ts
@@ -8,7 +8,7 @@ import {Constants} from "../../constants";
import {isIPad} from "../../protyle/util/compatibility";
import {globalTouchEnd, globalTouchStart} from "./touch";
import {initDockMenu} from "../../menus/dock";
-import {hasClosestByAttribute, hasClosestByClassName} from "../../protyle/util/hasClosest";
+import {hasClosestByAttribute, hasClosestByClassName, hasTopClosestByAttribute} from "../../protyle/util/hasClosest";
import {initTabMenu} from "../../menus/tab";
import {getInstanceById} from "../../layout/util";
import {Tab} from "../../layout/Tab";
@@ -85,7 +85,7 @@ export const initWindowEvent = (app: App) => {
}
return;
}
- const embedBlockElement = hasClosestByAttribute(target, "data-type", "NodeBlockQueryEmbed");
+ const embedBlockElement = hasTopClosestByAttribute(target, "data-type", "NodeBlockQueryEmbed");
if (embedBlockElement) {
embedBlockElement.firstElementChild.classList.toggle("protyle-icons--show");
return;
diff --git a/app/src/protyle/render/abcRender.ts b/app/src/protyle/render/abcRender.ts
index c5540bbd1..b8abbe46a 100644
--- a/app/src/protyle/render/abcRender.ts
+++ b/app/src/protyle/render/abcRender.ts
@@ -1,6 +1,7 @@
import {addScript} from "../util/addScript";
import {Constants} from "../../constants";
import {genIconHTML} from "./util";
+import {hasClosestByClassName} from "../util/hasClosest";
export const abcRender = (element: Element, cdn = Constants.PROTYLE_CDN) => {
let abcElements: Element[] = [];
@@ -15,12 +16,13 @@ export const abcRender = (element: Element, cdn = Constants.PROTYLE_CDN) => {
}
if (abcElements.length > 0) {
addScript(`${cdn}/js/abcjs/abcjs-basic-min.js?v=6.2.2`, "protyleAbcjsScript").then(() => {
+ const wysiswgElement = hasClosestByClassName(element, "protyle-wysiwyg", true)
abcElements.forEach((e: HTMLDivElement) => {
if (e.getAttribute("data-render") === "true") {
return;
}
- if(!e.firstElementChild.classList.contains("protyle-icons")) {
- e.insertAdjacentHTML("afterbegin", genIconHTML());
+ if (!e.firstElementChild.classList.contains("protyle-icons")) {
+ e.insertAdjacentHTML("afterbegin", genIconHTML(wysiswgElement));
}
const renderElement = e.firstElementChild.nextElementSibling as HTMLElement;
renderElement.innerHTML = `${Constants.ZWSP}
`;
diff --git a/app/src/protyle/render/av/rollup.ts b/app/src/protyle/render/av/rollup.ts
index 404ec0fbf..61fbb62c6 100644
--- a/app/src/protyle/render/av/rollup.ts
+++ b/app/src/protyle/render/av/rollup.ts
@@ -72,7 +72,6 @@ const genSearchList = (element: Element, keyword: string, avId: string, isRelati
response.data.keys.forEach((item: IAVColumn, index: number) => {
html += `
${item.icon ? unicode2Emoji(item.icon, "b3-list-item__graphic", true) : ``}
- ${genIconHTML()}
${escapeHtml(item.name || window.siyuan.languages.title)}
`;
});
diff --git a/app/src/protyle/render/chartRender.ts b/app/src/protyle/render/chartRender.ts
index 2685e6fa2..413e62cb1 100644
--- a/app/src/protyle/render/chartRender.ts
+++ b/app/src/protyle/render/chartRender.ts
@@ -30,12 +30,13 @@ export const chartRender = (element: Element, cdn = Constants.PROTYLE_CDN) => {
});
}
}
+ const wysiswgElement = hasClosestByClassName(element, "protyle-wysiwyg", true)
echartsElements.forEach(async (e: HTMLDivElement) => {
if (e.getAttribute("data-render") === "true") {
return;
}
if (!e.firstElementChild.classList.contains("protyle-icons")) {
- e.insertAdjacentHTML("afterbegin", genIconHTML());
+ e.insertAdjacentHTML("afterbegin", genIconHTML(wysiswgElement));
}
const renderElement = e.firstElementChild.nextElementSibling as HTMLElement;
try {
diff --git a/app/src/protyle/render/flowchartRender.ts b/app/src/protyle/render/flowchartRender.ts
index 6de68fdb2..cd4060d5d 100644
--- a/app/src/protyle/render/flowchartRender.ts
+++ b/app/src/protyle/render/flowchartRender.ts
@@ -1,6 +1,6 @@
import {addScript} from "../util/addScript";
import {Constants} from "../../constants";
-import {hasClosestByAttribute} from "../util/hasClosest";
+import {hasClosestByAttribute, hasClosestByClassName} from "../util/hasClosest";
import {genIconHTML} from "./util";
declare const flowchart: {
@@ -36,12 +36,13 @@ export const flowchartRender = (element: Element, cdn = Constants.PROTYLE_CDN) =
};
const initFlowchart = (flowchartElements: Element[]) => {
+ const wysiswgElement = hasClosestByClassName(flowchartElements[0], "protyle-wysiwyg", true)
flowchartElements.forEach((item: HTMLElement) => {
if (item.getAttribute("data-render") === "true") {
return;
}
if (!item.firstElementChild.classList.contains("protyle-icons")) {
- item.insertAdjacentHTML("afterbegin", genIconHTML());
+ item.insertAdjacentHTML("afterbegin", genIconHTML(wysiswgElement));
}
const renderElement = item.firstElementChild.nextElementSibling;
renderElement.innerHTML = `${Constants.ZWSP}`;
diff --git a/app/src/protyle/render/graphvizRender.ts b/app/src/protyle/render/graphvizRender.ts
index 145d6fd66..eaf3cb72e 100644
--- a/app/src/protyle/render/graphvizRender.ts
+++ b/app/src/protyle/render/graphvizRender.ts
@@ -1,6 +1,7 @@
import {addScript} from "../util/addScript";
import {Constants} from "../../constants";
import {genIconHTML} from "./util";
+import {hasClosestByClassName} from "../util/hasClosest";
export const graphvizRender = (element: Element, cdn = Constants.PROTYLE_CDN) => {
let graphvizElements: Element[] = [];
@@ -14,12 +15,13 @@ export const graphvizRender = (element: Element, cdn = Constants.PROTYLE_CDN) =>
return;
}
addScript(`${cdn}/js/graphviz/viz.js?v=0.0.0`, "protyleGraphVizScript").then(() => {
+ const wysiswgElement = hasClosestByClassName(element, "protyle-wysiwyg", true)
graphvizElements.forEach((e: HTMLDivElement) => {
if (e.getAttribute("data-render") === "true") {
return;
}
if (!e.firstElementChild.classList.contains("protyle-icons")) {
- e.insertAdjacentHTML("afterbegin", genIconHTML());
+ e.insertAdjacentHTML("afterbegin", genIconHTML(wysiswgElement));
}
const renderElement = e.firstElementChild.nextElementSibling as HTMLElement;
try {
diff --git a/app/src/protyle/render/mermaidRender.ts b/app/src/protyle/render/mermaidRender.ts
index 5ad177e77..625952232 100644
--- a/app/src/protyle/render/mermaidRender.ts
+++ b/app/src/protyle/render/mermaidRender.ts
@@ -1,6 +1,7 @@
import {addScript} from "../util/addScript";
import {Constants} from "../../constants";
-import {hasClosestByAttribute} from "../util/hasClosest";
+import {hasClosestByAttribute, hasClosestByClassName} from "../util/hasClosest";
+import {genIconHTML} from "./util";
export const mermaidRender = (element: Element, cdn = Constants.PROTYLE_CDN) => {
let mermaidElements: Element[] = [];
@@ -56,15 +57,13 @@ export const mermaidRender = (element: Element, cdn = Constants.PROTYLE_CDN) =>
};
const initMermaid = (mermaidElements: Element[]) => {
+ const wysiswgElement = hasClosestByClassName(mermaidElements[0], "protyle-wysiwyg", true)
mermaidElements.forEach(async (item: HTMLElement) => {
if (item.getAttribute("data-render") === "true") {
return;
}
if (!item.firstElementChild.classList.contains("protyle-icons")) {
- item.insertAdjacentHTML("afterbegin", `
-
-
-
`);
+ item.insertAdjacentHTML("afterbegin", genIconHTML(wysiswgElement));
}
const renderElement = item.firstElementChild.nextElementSibling as HTMLElement;
const id = "mermaid" + Lute.NewNodeID();
diff --git a/app/src/protyle/render/mindmapRender.ts b/app/src/protyle/render/mindmapRender.ts
index b16a10cce..2acb3348c 100644
--- a/app/src/protyle/render/mindmapRender.ts
+++ b/app/src/protyle/render/mindmapRender.ts
@@ -27,12 +27,13 @@ export const mindmapRender = (element: Element, cdn = Constants.PROTYLE_CDN) =>
});
}
}
+ const wysiswgElement = hasClosestByClassName(element, "protyle-wysiwyg", true)
mindmapElements.forEach((e: HTMLDivElement) => {
if (e.getAttribute("data-render") === "true") {
return;
}
if (!e.firstElementChild.classList.contains("protyle-icons")) {
- e.insertAdjacentHTML("afterbegin", genIconHTML());
+ e.insertAdjacentHTML("afterbegin", genIconHTML(wysiswgElement));
}
const renderElement = e.firstElementChild.nextElementSibling as HTMLElement;
try {
diff --git a/app/src/protyle/render/plantumlRender.ts b/app/src/protyle/render/plantumlRender.ts
index 218c72a68..1d3a5cf67 100644
--- a/app/src/protyle/render/plantumlRender.ts
+++ b/app/src/protyle/render/plantumlRender.ts
@@ -1,6 +1,7 @@
import {addScript} from "../util/addScript";
import {Constants} from "../../constants";
import {genIconHTML} from "./util";
+import {hasClosestByClassName} from "../util/hasClosest";
export const plantumlRender = (element: Element, cdn = Constants.PROTYLE_CDN) => {
let plantumlElements: Element[] = [];
@@ -14,12 +15,13 @@ export const plantumlRender = (element: Element, cdn = Constants.PROTYLE_CDN) =>
return;
}
addScript(`${cdn}/js/plantuml/plantuml-encoder.min.js?v=0.0.0`, "protylePlantumlScript").then(() => {
+ const wysiswgElement = hasClosestByClassName(element, "protyle-wysiwyg", true)
plantumlElements.forEach((e: HTMLDivElement) => {
if (e.getAttribute("data-render") === "true") {
return;
}
if (!e.firstElementChild.classList.contains("protyle-icons")) {
- e.insertAdjacentHTML("afterbegin", genIconHTML());
+ e.insertAdjacentHTML("afterbegin", genIconHTML(wysiswgElement));
}
const renderElement = e.firstElementChild.nextElementSibling as HTMLElement;
try {
diff --git a/app/src/protyle/render/util.ts b/app/src/protyle/render/util.ts
index d1168ddf7..778d468d7 100644
--- a/app/src/protyle/render/util.ts
+++ b/app/src/protyle/render/util.ts
@@ -1,6 +1,15 @@
-export const genIconHTML = () => {
+export const genIconHTML = (element?: false|HTMLElement) => {
+ let enable = true;
+ if (element) {
+ const readonly = element.getAttribute("custom-sy-readonly");
+ if (typeof readonly === "string") {
+ enable = element.getAttribute("custom-sy-readonly") === "false";
+ } else {
+ return '';
+ }
+ }
return `
-
-
+
+
`;
};
diff --git a/app/src/protyle/util/onGet.ts b/app/src/protyle/util/onGet.ts
index ecd66e159..45c96adb5 100644
--- a/app/src/protyle/util/onGet.ts
+++ b/app/src/protyle/util/onGet.ts
@@ -296,6 +296,12 @@ export const disabledProtyle = (protyle: IProtyle) => {
protyle.wysiwyg.element.querySelectorAll(".protyle-icons--show").forEach(item => {
item.classList.remove("protyle-icons--show");
});
+ protyle.wysiwyg.element.querySelectorAll(".render-node .protyle-action__edit").forEach(item => {
+ item.classList.add("fn__none");
+ if (item.classList.contains("protyle-icon--first")) {
+ item.nextElementSibling?.classList.add("protyle-icon--first")
+ }
+ });
protyle.wysiwyg.element.style.userSelect = "text";
protyle.wysiwyg.element.setAttribute("contenteditable", "false");
protyle.wysiwyg.element.querySelectorAll('[contenteditable="true"][spellcheck]').forEach(item => {
@@ -347,6 +353,13 @@ export const enableProtyle = (protyle: IProtyle) => {
if (protyle.background) {
protyle.background.element.classList.add("protyle-background--enable");
}
+
+ protyle.wysiwyg.element.querySelectorAll(".render-node .protyle-action__edit").forEach(item => {
+ item.classList.remove("fn__none");
+ if (item.classList.contains("protyle-icon--first")) {
+ item.nextElementSibling?.classList.remove("protyle-icon--first")
+ }
+ });
protyle.wysiwyg.element.querySelectorAll('[contenteditable="false"][spellcheck]').forEach(item => {
if (!hasClosestByClassName(item, "protyle-wysiwyg__embed")) {
item.setAttribute("contenteditable", "true");