Skip to content

Commit cebdba4

Browse files
committed
feat: support configuration of label display
1 parent 60df7d2 commit cebdba4

File tree

10 files changed

+177
-62
lines changed

10 files changed

+177
-62
lines changed

README.md

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,10 @@ Click the menu button in the top-right corner of the image. If the block is reco
6363
+ Method 1: Simply export your diagram as an SVG from any draw.io platform with the "Include a copy of my diagram" option enabled, then drag the resulting SVG file into SiYuan.
6464
+ Method 2: Copy all content from any draw.io platform, type `/drawio` in the editor, and paste the copied content into the pop-up draw.io window.
6565

66-
**Disable draw.io label:**
67-
68-
Add CSS Snippet:
69-
70-
```css
71-
.protyle-attr .label--embed-drawio {
72-
display: none !important;
73-
}
74-
```
75-
7666
## Changelog
7767

68+
+ v0.2.2
69+
+ Optimize: add tag configuration, now you can set the display mode of tags in the configuration
7870
+ v0.2.1
7971
+ Feature: lightbox
8072
+ v0.2.0

README_zh_CN.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,10 @@
5757
+ 方案1:只需要在任意draw.io平台导出SVG图像时勾选 `包含绘图副本` 选项,再把SVG图像拖入思源笔记中即可,不用担心以后没法再迁移,这个SVG图像也是可以导入到任意draw.io再次编辑的。
5858
+ 方案2:在任意draw.io平台内复制全部内容,在思源笔记中输入 `/drawio` 命令创建新draw.io图像,然后将复制的内容粘贴进弹出的draw.io窗口中即可。
5959

60-
**移除draw.io标签:** 添加下列代码片段:
61-
62-
```css
63-
.protyle-attr .label--embed-drawio {
64-
display: none !important;
65-
}
66-
```
67-
6860
## 更新日志
6961

62+
+ v0.2.2
63+
+ 优化:增加标签的配置,现在可以在配置里设置标签的显示模式
7064
+ v0.2.1
7165
+ 新增功能:灯箱
7266
+ v0.2.0

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "siyuan-embed-drawio",
3-
"version": "0.2.1",
3+
"version": "0.2.2",
44
"type": "module",
55
"description": "This is a plugin for siyuan",
66
"author": "",

plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "siyuan-embed-drawio",
33
"author": "Yuxin Zhao",
44
"url": "https://github.com/YuxinZhaozyx/siyuan-embed-drawio",
5-
"version": "0.2.1",
5+
"version": "0.2.2",
66
"minAppVersion": "3.3.0",
77
"disabledInPublish": true,
88
"backends": [

src/i18n/en_US.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
{
22
"editDrawio": "Edit draw.io",
3-
"drawioLightbox": "draw.io Lightbox"
3+
"drawioLightbox": "draw.io Lightbox",
4+
"labelDisplay": "Label Display",
5+
"labelDisplayDescription": "Label display in image block top right corner (Changes require refresh of document)",
6+
"noLabel": "No Label",
7+
"showLabelAlways": "Show Label Always",
8+
"showLabelOnHover": "Show Label On Hover"
49
}

src/i18n/zh_CN.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
{
22
"editDrawio": "编辑 draw.io",
3-
"drawioLightbox": "draw.io 灯箱"
3+
"drawioLightbox": "draw.io 灯箱",
4+
"labelDisplay": "标签显示",
5+
"labelDisplayDescription": "图像块右上角的标签显示(修改后需刷新文档生效)",
6+
"noLabel": "不显示标签",
7+
"showLabelAlways": "始终显示标签",
8+
"showLabelOnHover": "悬停时显示标签"
49
}

src/index.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,8 @@
3838

3939
html[data-theme-mode="dark"] img[data-src^="assets/drawio-"][data-src$=".svg"] {
4040
filter: invert(0.8) brightness(1.2);
41+
}
42+
43+
div[data-type='NodeParagraph']:not(:hover) .protyle-attr .label--embed-drawio:not(.label--embed-drawio--always) {
44+
display: none !important;
4145
}

src/index.ts

Lines changed: 131 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from "siyuan";
88
import "@/index.scss";
99
import PluginInfoString from '@/../plugin.json';
10-
import { unescapeHTML, escapeHTML, base64ToUnicode } from "./utils";
10+
import { base64ToUnicode, HTMLToElement } from "./utils";
1111
import defaultImageContent from "@/../default.svg?raw";
1212

1313
let PluginInfo = {
@@ -22,6 +22,8 @@ const {
2222
version,
2323
} = PluginInfo
2424

25+
const STORAGE_NAME = "config.json";
26+
2527
export default class DrawioPlugin extends Plugin {
2628
// Run as mobile
2729
public isMobile: boolean
@@ -40,14 +42,19 @@ export default class DrawioPlugin extends Plugin {
4042
private _openMenuImageHandler;
4143
private _globalKeyDownHandler;
4244

45+
private settingItems: SettingItem[];
46+
4347
async onload() {
4448
this.initMetaInfo();
49+
this.initSetting();
4550

4651
this._mutationObserver = this.setAddImageBlockMuatationObserver(document.body, (blockElement: HTMLElement) => {
52+
if (this.data[STORAGE_NAME].labelDisplay === "noLabel") return;
53+
4754
const imageElement = blockElement.querySelector("img") as HTMLImageElement;
4855
if (imageElement) {
4956
const imageURL = imageElement.getAttribute("data-src");
50-
this.getDrawioImageInfo(imageURL).then((imageInfo) => {
57+
this.getDrawioImageInfo(imageURL, false).then((imageInfo) => {
5158
this.updateAttrLabel(imageInfo, blockElement);
5259
});
5360
}
@@ -77,8 +84,105 @@ export default class DrawioPlugin extends Plugin {
7784
if (this._globalKeyDownHandler) document.documentElement.removeEventListener("keydown", this._globalKeyDownHandler);
7885
}
7986

80-
// openSetting() {
81-
// }
87+
openSetting() {
88+
const dialogHTML = `
89+
<div class="b3-dialog__content"></div>
90+
<div class="b3-dialog__action">
91+
<button class="b3-button b3-button--cancel" data-type="cancel">${window.siyuan.languages.cancel}</button>
92+
<div class="fn__space"></div>
93+
<button class="b3-button b3-button--text" data-type="confirm">${window.siyuan.languages.save}</button>
94+
</div>
95+
`;
96+
97+
const dialog = new Dialog({
98+
title: this.displayName,
99+
content: dialogHTML,
100+
width: this.isMobile ? "92vw" : "768px",
101+
height: "80vh",
102+
hideCloseIcon: this.isMobile,
103+
});
104+
105+
// 配置的处理拷贝自思源源码
106+
const contentElement = dialog.element.querySelector(".b3-dialog__content");
107+
this.settingItems.forEach((item) => {
108+
let html = "";
109+
let actionElement = item.actionElement;
110+
if (!item.actionElement && item.createActionElement) {
111+
actionElement = item.createActionElement();
112+
}
113+
const tagName = actionElement?.classList.contains("b3-switch") ? "label" : "div";
114+
if (typeof item.direction === "undefined") {
115+
item.direction = (!actionElement || "TEXTAREA" === actionElement.tagName) ? "row" : "column";
116+
}
117+
if (item.direction === "row") {
118+
html = `<${tagName} class="b3-label">
119+
<div class="fn__block">
120+
${item.title}
121+
${item.description ? `<div class="b3-label__text">${item.description}</div>` : ""}
122+
<div class="fn__hr"></div>
123+
</div>
124+
</${tagName}>`;
125+
} else {
126+
html = `<${tagName} class="fn__flex b3-label config__item">
127+
<div class="fn__flex-1">
128+
${item.title}
129+
${item.description ? `<div class="b3-label__text">${item.description}</div>` : ""}
130+
</div>
131+
<span class="fn__space${actionElement ? "" : " fn__none"}"></span>
132+
</${tagName}>`;
133+
}
134+
contentElement.insertAdjacentHTML("beforeend", html);
135+
if (actionElement) {
136+
if (["INPUT", "TEXTAREA"].includes(actionElement.tagName)) {
137+
dialog.bindInput(actionElement as HTMLInputElement, () => {
138+
(dialog.element.querySelector(".b3-dialog__action [data-type='confirm']") as HTMLElement).dispatchEvent(new CustomEvent("click"));
139+
});
140+
}
141+
if (item.direction === "row") {
142+
contentElement.lastElementChild.lastElementChild.insertAdjacentElement("beforeend", actionElement);
143+
actionElement.classList.add("fn__block");
144+
} else {
145+
actionElement.classList.remove("fn__block");
146+
actionElement.classList.add("fn__flex-center", "fn__size200");
147+
contentElement.lastElementChild.insertAdjacentElement("beforeend", actionElement);
148+
}
149+
}
150+
});
151+
152+
(dialog.element.querySelector(".b3-dialog__action [data-type='cancel']") as HTMLElement).addEventListener("click", () => {
153+
dialog.destroy();
154+
});
155+
(dialog.element.querySelector(".b3-dialog__action [data-type='confirm']") as HTMLElement).addEventListener("click", () => {
156+
this.data[STORAGE_NAME].labelDisplay = (dialog.element.querySelector("[data-type='labelDisplay']") as HTMLSelectElement).value;
157+
this.saveData(STORAGE_NAME, this.data[STORAGE_NAME]);
158+
dialog.destroy();
159+
});
160+
}
161+
162+
private async initSetting() {
163+
await this.loadData(STORAGE_NAME);
164+
if (!this.data[STORAGE_NAME]) {
165+
this.data[STORAGE_NAME] = {
166+
labelDisplay: "showLabelOnHover",
167+
};
168+
}
169+
170+
this.settingItems = [
171+
{
172+
title: "标签显示",
173+
direction: "column",
174+
description: "图像块右上角的标签显示(修改后需刷新文档生效)",
175+
createActionElement: () => {
176+
const options = ["noLabel", "showLabelAlways", "showLabelOnHover"];
177+
const optionsHTML = options.map(option => {
178+
const isSelected = String(option) === String(this.data[STORAGE_NAME].labelDisplay);
179+
return `<option value="${option}"${isSelected ? " selected" : ""}>${this.i18n[option]}</option>`;
180+
}).join("");
181+
return HTMLToElement(`<select class="b3-select fn__flex-center" data-type="labelDisplay">${optionsHTML}</select>`);
182+
},
183+
},
184+
];
185+
}
82186

83187
private initMetaInfo() {
84188
const frontEnd = getFrontend();
@@ -129,11 +233,11 @@ export default class DrawioPlugin extends Plugin {
129233
return mutationObserver;
130234
}
131235

132-
public async getDrawioImageInfo(imageURL: string): Promise<DrawioImageInfo | null> {
236+
public async getDrawioImageInfo(imageURL: string, reload: boolean): Promise<DrawioImageInfo | null> {
133237
const imageURLRegex = /^assets\/.+\.svg$/;
134238
if (!imageURLRegex.test(imageURL)) return null;
135239

136-
const svgContent = await this.getDrawioImage(imageURL);
240+
const svgContent = await this.getDrawioImage(imageURL, reload);
137241
if (!svgContent) return null;
138242

139243
if (!svgContent.includes("mxfile")) return null;
@@ -175,8 +279,8 @@ export default class DrawioPlugin extends Plugin {
175279
});
176280
}
177281

178-
public async getDrawioImage(imageURL: string): Promise<string> {
179-
const response = await fetch(imageURL, { cache: 'reload' });
282+
public async getDrawioImage(imageURL: string, reload: boolean): Promise<string> {
283+
const response = await fetch(imageURL, { cache: reload ? 'reload' : 'default' });
180284
if (!response.ok) return "";
181285
const svgContent = await response.text();
182286
return svgContent;
@@ -198,6 +302,8 @@ export default class DrawioPlugin extends Plugin {
198302
public updateAttrLabel(imageInfo: DrawioImageInfo, blockElement: HTMLElement) {
199303
if (!imageInfo) return;
200304

305+
if (this.data[STORAGE_NAME].labelDisplay === "noLabel") return;
306+
201307
const attrElement = blockElement.querySelector(".protyle-attr") as HTMLDivElement;
202308
if (attrElement) {
203309
const pageCount = (imageInfo.data.match(/name=&quot;/g) || []).length;
@@ -208,6 +314,9 @@ export default class DrawioPlugin extends Plugin {
208314
} else {
209315
labelElement = document.createElement("div");
210316
labelElement.classList.add("label--embed-drawio");
317+
if (this.data[STORAGE_NAME].labelDisplay === "showLabelAlways") {
318+
labelElement.classList.add("label--embed-drawio--always");
319+
}
211320
labelElement.innerHTML = labelHTML;
212321
attrElement.prepend(labelElement);
213322
}
@@ -218,7 +327,7 @@ export default class DrawioPlugin extends Plugin {
218327
const selectedElement = detail.element;
219328
const imageElement = selectedElement.querySelector("img") as HTMLImageElement;
220329
const imageURL = imageElement.dataset.src;
221-
this.getDrawioImageInfo(imageURL).then((imageInfo: DrawioImageInfo) => {
330+
this.getDrawioImageInfo(imageURL, true).then((imageInfo: DrawioImageInfo) => {
222331
if (imageInfo) {
223332
window.siyuan.menus.menu.addItem({
224333
id: "edit-drawio",
@@ -255,7 +364,7 @@ export default class DrawioPlugin extends Plugin {
255364
<div class="edit-dialog-header resize__move"></div>
256365
<div class="edit-dialog-container">
257366
<div class="edit-dialog-editor">
258-
<iframe src="/plugins/siyuan-embed-drawio/draw/index.html?proto=json&embed=1${this.isMobile?"&ui=min":""}&lang=${window.siyuan.config.lang.split('_')[0]}"></iframe>
367+
<iframe src="/plugins/siyuan-embed-drawio/draw/index.html?proto=json&embed=1${this.isMobile ? "&ui=min" : ""}&lang=${window.siyuan.config.lang.split('_')[0]}"></iframe>
259368
</div>
260369
<div class="fn__hr--b"></div>
261370
</div>
@@ -294,8 +403,8 @@ export default class DrawioPlugin extends Plugin {
294403

295404
const onSave = (message: any) => {
296405
postMessage({
297-
action: 'export',
298-
format:'xmlsvg'
406+
action: 'export',
407+
format: 'xmlsvg'
299408
});
300409
}
301410

@@ -310,7 +419,7 @@ export default class DrawioPlugin extends Plugin {
310419

311420
this.updateDrawioImage(imageInfo, () => {
312421
postMessage({
313-
action: 'status',
422+
action: 'status',
314423
messageKey: 'allChangesSaved',
315424
modified: false
316425
});
@@ -332,13 +441,10 @@ export default class DrawioPlugin extends Plugin {
332441
}
333442

334443
const messageEventHandler = (event) => {
335-
if (event.data && event.data.length > 0)
336-
{
337-
try
338-
{
444+
if (event.data && event.data.length > 0) {
445+
try {
339446
var message = JSON.parse(event.data);
340-
if (message != null)
341-
{
447+
if (message != null) {
342448
// console.log(message.event);
343449
if (message.event == "init") {
344450
onInit(message);
@@ -354,8 +460,7 @@ export default class DrawioPlugin extends Plugin {
354460
}
355461
}
356462
}
357-
catch (err)
358-
{
463+
catch (err) {
359464
console.error(err);
360465
}
361466
}
@@ -373,7 +478,7 @@ export default class DrawioPlugin extends Plugin {
373478
<div class="edit-dialog-header resize__move"></div>
374479
<div class="edit-dialog-container">
375480
<div class="edit-dialog-editor">
376-
<iframe src="/plugins/siyuan-embed-drawio/draw/index.html?proto=json&embed=1${this.isMobile?"&ui=min":""}&lang=${window.siyuan.config.lang.split('_')[0]}&lightbox=1"></iframe>
481+
<iframe src="/plugins/siyuan-embed-drawio/draw/index.html?proto=json&embed=1${this.isMobile ? "&ui=min" : ""}&lang=${window.siyuan.config.lang.split('_')[0]}&lightbox=1"></iframe>
377482
</div>
378483
<div class="fn__hr--b"></div>
379484
</div>
@@ -411,21 +516,17 @@ export default class DrawioPlugin extends Plugin {
411516
}
412517

413518
const messageEventHandler = (event) => {
414-
if (event.data && event.data.length > 0)
415-
{
416-
try
417-
{
519+
if (event.data && event.data.length > 0) {
520+
try {
418521
var message = JSON.parse(event.data);
419-
if (message != null)
420-
{
522+
if (message != null) {
421523
// console.log(message.event);
422524
if (message.event == "init") {
423525
onInit(message);
424526
}
425527
}
426528
}
427-
catch (err)
428-
{
529+
catch (err) {
429530
console.error(err);
430531
}
431532
}

src/types/index.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,11 @@ interface DrawioImageInfo {
152152
imageURL: string;
153153
data: string;
154154
}
155+
156+
interface SettingItem {
157+
title?: string;
158+
description?: string;
159+
direction?: "row" | "column";
160+
actionElement?: HTMLElement;
161+
createActionElement?: () => HTMLElement;
162+
}

0 commit comments

Comments
 (0)