From cdb5085f356b0c52e634421a5c190b38429ff11a Mon Sep 17 00:00:00 2001 From: frostime Date: Sat, 16 Sep 2023 18:03:59 +0800 Subject: [PATCH 01/88] setting-utils --- src/index.ts | 81 +++++++++++++----- src/libs/index.d.ts | 20 +++++ src/libs/setting-utils.ts | 176 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 255 insertions(+), 22 deletions(-) create mode 100644 src/libs/index.d.ts create mode 100644 src/libs/setting-utils.ts diff --git a/src/index.ts b/src/index.ts index 02aa494..b98b48a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,6 +18,8 @@ import "@/index.scss"; import HelloExample from "@/hello.svelte"; import SettingPannel from "@/libs/setting-panel.svelte"; +import { SettingUtils } from "./libs/setting-utils"; + const STORAGE_NAME = "menu-config"; const TAB_TYPE = "custom_tab"; const DOCK_TYPE = "dock_tab"; @@ -27,6 +29,7 @@ export default class PluginSample extends Plugin { private customTab: () => IModel; private isMobile: boolean; private blockIconEventBindThis = this.blockIconEvent.bind(this); + private settingUtils: SettingUtils; async onload() { this.data[STORAGE_NAME] = { readonlyText: "Readonly" }; @@ -158,32 +161,66 @@ export default class PluginSample extends Plugin { } }); - const textareaElement = document.createElement("textarea"); - this.setting = new Setting({ - confirmCallback: () => { - this.saveData(STORAGE_NAME, { readonlyText: textareaElement.value }); + this.settingUtils = new SettingUtils(this, STORAGE_NAME); + this.settingUtils.addItem({ + key: "Input", + value: "", + type: "textinput", + title: "Readonly text", + description: "Input description", + }); + this.settingUtils.addItem({ + key: "InputArea", + value: "", + type: "textarea", + title: "Readonly text", + description: "Input description", + }); + this.settingUtils.addItem({ + key: "Select", + value: 1, + type: "select", + title: "Readonly text", + description: "Select description", + select: { + options: [ + { + val: 1, + text: "Option 1" + }, + { + val: 2, + text: "Option 2" + } + ] } }); - this.setting.addItem({ - title: "Readonly text", - createActionElement: () => { - textareaElement.className = "b3-text-field fn__block"; - textareaElement.placeholder = "Readonly text in the menu"; - textareaElement.value = this.data[STORAGE_NAME].readonlyText; - return textareaElement; - }, + this.settingUtils.addItem({ + key: "Slider", + value: 50, + type: "slider", + title: "Slider text", + description: "Slider description", + slider: { + min: 0, + max: 100, + step: 1, + } }); - const btnaElement = document.createElement("button"); - btnaElement.className = "b3-button b3-button--outline fn__flex-center fn__size200"; - btnaElement.textContent = "Open"; - btnaElement.addEventListener("click", () => { - window.open("https://github.com/siyuan-note/plugin-sample-vite-svelte"); - }); - this.setting.addItem({ - title: "Open plugin url", - description: "Open plugin url in browser", - actionElement: btnaElement, + this.settingUtils.addItem({ + key: "Btn", + value: "", + type: "button", + title: "Button", + description: "Button description", + button: { + label: "Button", + callback: () => { + showMessage("Button clicked"); + } + } }); + this.settingUtils.load(); this.protyleSlash = [{ filter: ["insert emoji 😊", "插入表情 😊", "crbqwx"], diff --git a/src/libs/index.d.ts b/src/libs/index.d.ts new file mode 100644 index 0000000..b46f655 --- /dev/null +++ b/src/libs/index.d.ts @@ -0,0 +1,20 @@ +type TSettingItemType = "checkbox" | "select" | "textinput" | "textarea" | "slider" | "button"; +interface ISettingItem { + key: string; + value: any; + type: TSettingItemType; + title: string; + description?: string; + slider?: { + min: number; + max: number; + step: number; + }; + select?: { + options: {val: any; text: string}[]; + }; + button?: { + label: string; + callback: () => void; + } +} diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts new file mode 100644 index 0000000..5c5638b --- /dev/null +++ b/src/libs/setting-utils.ts @@ -0,0 +1,176 @@ +import { Plugin, Setting } from 'siyuan'; + +export class SettingUtils { + plugin: Plugin; + name: string; + file: string; + + settings: Map = new Map(); + elements: Map = new Map(); + + constructor(plugin: Plugin, name?: string, width?: string, height?: string) { + this.name = name ?? 'settings'; + this.plugin = plugin; + this.file = this.name.endsWith('.json') ? this.name : `${this.name}.json`; + this.plugin.setting = new Setting({ + width: width, + height: height, + confirmCallback: () => { + for (let key of this.settings.keys()) { + this.updateValue(key); + } + let data = this.dump(); + this.plugin.data[this.name] = data; + this.save(); + } + }); + } + + async load() { + let data = await this.plugin.loadData(this.file); + if (data) { + for (let [key, item] of this.settings) { + item.value = data?.[key] ?? item.value; + } + } + } + + async save() { + let data = this.dump(); + await this.plugin.saveData(this.file, this.dump()); + return data; + } + + /** + * Get setting item value + * @param key key name + * @returns setting item value + */ + get(key: string) { + return this.settings.get(key)?.value; + } + + /** + * 将设置项目导出为 JSON 对象 + * @returns object + */ + dump(): Object { + let data: any = {}; + for (let [key, item] of this.settings) { + if (item.type === 'button') continue; + data[key] = item.value; + } + return data; + } + + addItem(item: ISettingItem) { + this.settings.set(item.key, item); + let itemElement: HTMLElement; + switch (item.type) { + case 'checkbox': + let element: HTMLInputElement = document.createElement('input'); + element.type = 'checkbox'; + element.checked = item.value; + element.className = "b3-switch fn__flex-center"; + itemElement = element; + break; + case 'select': + let selectElement: HTMLSelectElement = document.createElement('select'); + selectElement.className = "b3-select fn__flex-center fn__size200"; + for (let option of item.select?.options ?? []) { + let optionElement = document.createElement('option'); + optionElement.value = option.val; + optionElement.text = option.text; + selectElement.appendChild(optionElement); + } + selectElement.value = item.value; + itemElement = selectElement; + break; + case 'slider': + let sliderElement: HTMLInputElement = document.createElement('input'); + sliderElement.type = 'range'; + sliderElement.className = 'b3-slider fn__size200'; + sliderElement.ariaLabel = item.value; + sliderElement.min = item.slider?.min.toString() ?? '0'; + sliderElement.max = item.slider?.max.toString() ?? '100'; + sliderElement.step = item.slider?.step.toString() ?? '1'; + sliderElement.value = item.value; + itemElement = sliderElement; + break; + case 'textinput': + let textInputElement: HTMLInputElement = document.createElement('input'); + textInputElement.className = 'b3-text-field fn__flex-center fn__size200'; + textInputElement.value = item.value; + itemElement = textInputElement; + break; + case 'textarea': + let textareaElement: HTMLTextAreaElement = document.createElement('textarea'); + textareaElement.className = "b3-text-field fn__block"; + textareaElement.value = item.value; + itemElement = textareaElement; + break; + case 'button': + let buttonElement: HTMLButtonElement = document.createElement('button'); + buttonElement.className = "b3-button b3-button--outline fn__flex-center fn__size200"; + buttonElement.innerText = item.button?.label ?? 'Button'; + buttonElement.onclick = item.button?.callback ?? (() => {}); + itemElement = buttonElement; + break; + } + this.elements.set(item.key, itemElement); + this.plugin.setting.addItem({ + title: item.title, + description: item?.description, + createActionElement: () => { + let element = this.getElement(item.key); + return element; + } + }) + } + + private getElement(key: string) { + let item = this.settings.get(key); + let element = this.elements.get(key) as any; + switch (item.type) { + case 'checkbox': + element.checked = item.value; + break; + case 'select': + element.value = item.value; + break; + case 'slider': + element.value = item.value; + break; + case 'textinput': + element.value = item.value; + break; + case 'textarea': + element.value = item.value; + break; + } + return element; + } + + private updateValue(key: string) { + let item = this.settings.get(key); + let element = this.elements.get(key) as any; + switch (item.type) { + case 'checkbox': + item.value = element.checked; + break; + case 'select': + item.value = element.value; + break; + case 'slider': + item.value = element.value; + break; + case 'textinput': + item.value = element.value; + break; + case 'textarea': + item.value = element.value; + break; + } + } + +} \ No newline at end of file From 1a0b1018c55cd600916131846011de75b5d862c1 Mon Sep 17 00:00:00 2001 From: frostime Date: Sat, 16 Sep 2023 18:17:41 +0800 Subject: [PATCH 02/88] =?UTF-8?q?=E4=BC=98=E5=8C=96=20setting-utils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 14 +++++++++++--- src/libs/setting-utils.ts | 20 ++++++++++++++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index b98b48a..f65b4e1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -176,6 +176,13 @@ export default class PluginSample extends Plugin { title: "Readonly text", description: "Input description", }); + this.settingUtils.addItem({ + key: "Check", + value: true, + type: "checkbox", + title: "Checkbox text", + description: "Check description", + }); this.settingUtils.addItem({ key: "Select", value: 1, @@ -220,7 +227,6 @@ export default class PluginSample extends Plugin { } } }); - this.settingUtils.load(); this.protyleSlash = [{ filter: ["insert emoji 😊", "插入表情 😊", "crbqwx"], @@ -235,12 +241,14 @@ export default class PluginSample extends Plugin { } onLayoutReady() { - this.loadData(STORAGE_NAME); + // this.loadData(STORAGE_NAME); + this.settingUtils.load(); console.log(`frontend: ${getFrontend()}; backend: ${getBackend()}`); } - onunload() { + async onunload() { console.log(this.i18n.byePlugin); + await this.settingUtils.save(); showMessage("Goodbye SiYuan Plugin"); console.log("onunload"); } diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index 5c5638b..ff78af8 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -1,3 +1,12 @@ +/* + * Copyright (c) 2023 by frostime. All Rights Reserved. + * @Author : frostime + * @Date : 2023-09-16 18:05:00 + * @FilePath : /src/libs/setting-utils.ts + * @LastEditTime : 2023-09-16 18:17:03 + * @Description : A utility for siyuan plugin settings + */ + import { Plugin, Setting } from 'siyuan'; export class SettingUtils { @@ -33,6 +42,9 @@ export class SettingUtils { item.value = data?.[key] ?? item.value; } } + this.plugin.data[this.name] = this.dump(); + console.log(data); + return data; } async save() { @@ -89,12 +101,15 @@ export class SettingUtils { case 'slider': let sliderElement: HTMLInputElement = document.createElement('input'); sliderElement.type = 'range'; - sliderElement.className = 'b3-slider fn__size200'; + sliderElement.className = 'b3-slider fn__size200 b3-tooltips b3-tooltips__n'; sliderElement.ariaLabel = item.value; sliderElement.min = item.slider?.min.toString() ?? '0'; sliderElement.max = item.slider?.max.toString() ?? '100'; sliderElement.step = item.slider?.step.toString() ?? '1'; sliderElement.value = item.value; + sliderElement.onchange = () => { + sliderElement.ariaLabel = sliderElement.value; + } itemElement = sliderElement; break; case 'textinput': @@ -154,6 +169,7 @@ export class SettingUtils { private updateValue(key: string) { let item = this.settings.get(key); let element = this.elements.get(key) as any; + console.log(element, element?.value); switch (item.type) { case 'checkbox': item.value = element.checked; @@ -162,7 +178,7 @@ export class SettingUtils { item.value = element.value; break; case 'slider': - item.value = element.value; + item.value = parseInt(element.value); break; case 'textinput': item.value = element.value; From 05c9f269e27341cc1d376f149ea12e65fa05888f Mon Sep 17 00:00:00 2001 From: frostime Date: Sat, 16 Sep 2023 18:37:00 +0800 Subject: [PATCH 03/88] update doc --- README.md | 2 ++ README_zh_CN.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/README.md b/README.md index d4ddddb..279abc8 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,8 @@ The github action is included in this sample, you can use it to publish your new ## How to remove svelte dependencies +> Pure vite without svelte: https://github.com/frostime/plugin-sample-vite + This plugin is packaged in vite and provides a dependency on the svelte framework. However, in practice some developers may not want to use svelte and only want to use the vite package. In fact you can use this template without using svelte without any modifications at all. The compilation-related parts of the svelte compilation are loaded into the vite workflow as plugins, so even if you don't have svelte in your project, it won't matter much. diff --git a/README_zh_CN.md b/README_zh_CN.md index c8ad1fd..198be1d 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -195,6 +195,8 @@ PR 社区集市仓库。 ## 如何去掉 svelte 依赖 +> 无 Svelte 依赖版: https://github.com/frostime/plugin-sample-vite + 本插件使用 vite 打包,并提供了 svelte 框架依赖。不过实际情况下可能有些开发者并不想要 svelte,只希望使用 vite 打包。 实际上你可以完全不做任何修改,就可以在不使用 svelte 的前提下使用这个模板。与 svelte 编译的编译相关的部分是以插件的形式载入到 vite 的工作流中,所以即使你的项目里面没有 svelte,也不会有太大的影响。 From c2d3812e191d71d26178b729b5039a008e8c2585 Mon Sep 17 00:00:00 2001 From: frostime Date: Fri, 27 Oct 2023 20:41:40 +0800 Subject: [PATCH 04/88] misc --- CHANGELOG.md | 16 ++++++++++++++++ README.md | 2 +- README_zh_CN.md | 2 +- package.json | 8 ++++---- plugin.json | 15 +++++++++++---- src/i18n/en_US.json | 1 + src/i18n/zh_CN.json | 1 + 7 files changed, 35 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7310325..aadd6ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,23 @@ # Changelog +## 0.2.7 2023-10 + +## 0.2.6 2023-10-24 + +* [Deprecated `loaded-protyle` use `loaded-protyle-static` instead](https://github.com/siyuan-note/siyuan/issues/9468) + +## 0.2.5 2023-10-10 + +* [Add plugin event bus `open-menu-doctree`](https://github.com/siyuan-note/siyuan/issues/9351) + +## 0.2.4 2023-09-19 + +* Supports use in windows +* [Add plugin function `transaction`](https://github.com/siyuan-note/siyuan/issues/9172) + ## 0.2.3 2023-09-05 +* [Add plugin function `transaction`](https://github.com/siyuan-note/siyuan/issues/9172) * [Plugin API add openWindow and command.globalCallback](https://github.com/siyuan-note/siyuan/issues/9032) ## 0.2.2 2023-08-29 diff --git a/README.md b/README.md index 279abc8..4a2b21b 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [中文版](./README_zh_CN.md) -> Consistent with [siyuan/plugin-sample](https://github.com/siyuan-note/plugin-sample) [v0.2.3](https://github.com/siyuan-note/plugin-sample/tree/v0.2.3) +> Consistent with [siyuan/plugin-sample](https://github.com/siyuan-note/plugin-sample) [v0.2.6](https://github.com/siyuan-note/plugin-sample/tree/v0.2.6) diff --git a/README_zh_CN.md b/README_zh_CN.md index 198be1d..bf72da3 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -4,7 +4,7 @@ [English](./README.md) -> 本例和 [siyuan/plugin-sample](https://github.com/siyuan-note/plugin-sample) [v0.2.3](https://github.com/siyuan-note/plugin-sample/tree/v0.2.3) +> 本例和 [siyuan/plugin-sample](https://github.com/siyuan-note/plugin-sample) [v0.2.6](https://github.com/siyuan-note/plugin-sample/tree/v0.2.6) 1. 使用 vite 打包 2. 使用符号链接、而不是把项目放到插件目录下的模式进行开发 diff --git a/package.json b/package.json index 528917a..bfe4eb0 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "plugin-sample-vite-svelte", - "version": "0.2.3", + "version": "0.2.6", "type": "module", - "description": "", + "description": "This is a sample plugin based on vite and svelte for Siyuan (https://b3log.org/siyuan)", "repository": "", "homepage": "", "author": "", - "license": "GPL-3.0", + "license": "MIT", "scripts": { "make-link": "node --no-warnings ./scripts/make_dev_link.js", "dev": "vite build --watch", @@ -22,7 +22,7 @@ "minimist": "^1.2.8", "rollup-plugin-livereload": "^2.0.5", "sass": "^1.62.1", - "siyuan": "0.8.3", + "siyuan": "0.8.7", "svelte": "^3.57.0", "ts-node": "^10.9.1", "typescript": "^5.0.4", diff --git a/plugin.json b/plugin.json index 41c9250..04236da 100644 --- a/plugin.json +++ b/plugin.json @@ -2,10 +2,17 @@ "name": "plugin-sample-vite-svelte", "author": "frostime", "url": "https://github.com/siyuan-note/plugin-sample-vite-svelte", - "version": "0.2.3", - "minAppVersion": "2.10.3", - "backends": ["all"], - "frontends": ["all"], + "version": "0.2.6", + "minAppVersion": "2.10.12", + "backends": [ + "windows", + "linux", + "darwin" + ], + "frontends": [ + "desktop", + "desktop-window" + ], "displayName": { "en_US": "Plugin sample with vite and svelte", "zh_CN": "插件样例 vite + svelte 版" diff --git a/src/i18n/en_US.json b/src/i18n/en_US.json index 4f21f86..c7ed102 100644 --- a/src/i18n/en_US.json +++ b/src/i18n/en_US.json @@ -9,6 +9,7 @@ "removedData": "Data deleted", "confirmRemove": "Confirm to delete the data in ${name}?", "insertEmoji": "Insert Emoji", + "removeSpace": "Remove Space", "getTab": "Print out all opened custom tabs in the debugger", "name": "SiYuan", "hello": { diff --git a/src/i18n/zh_CN.json b/src/i18n/zh_CN.json index 5a586e1..49a7af8 100644 --- a/src/i18n/zh_CN.json +++ b/src/i18n/zh_CN.json @@ -9,6 +9,7 @@ "removedData": "数据已删除", "confirmRemove": "确认删除 ${name} 中的数据?", "insertEmoji": "插入表情", + "removeSpace": "移除空格", "getTab": "在日志中打印出已打开的所有自定义页签", "name": "思源", "hello": { From 8be20e023ce21b890c172f59fc5c8e560abd0f15 Mon Sep 17 00:00:00 2001 From: frostime Date: Fri, 27 Oct 2023 20:52:25 +0800 Subject: [PATCH 05/88] update typescript --- src/index.ts | 69 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/src/index.ts b/src/index.ts index f65b4e1..353d472 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,7 +11,7 @@ import { IModel, Setting, fetchPost, - Protyle, openWindow + Protyle, openWindow, IOperation } from "siyuan"; import "@/index.scss"; @@ -68,7 +68,7 @@ export default class PluginSample extends Plugin { }); const statusIconTemp = document.createElement("template"); - statusIconTemp.innerHTML = `
+ statusIconTemp.innerHTML = `
@@ -272,19 +272,38 @@ export default class PluginSample extends Plugin { }); } + private eventBusPaste(event: any) { + // 如果需异步处理请调用 preventDefault, 否则会进行默认处理 + event.preventDefault(); + // 如果使用了 preventDefault,必须调用 resolve,否则程序会卡死 + event.detail.resolve({ + textPlain: event.detail.textPlain.trim(), + }); + } + private eventBusLog({ detail }: any) { console.log(detail); } private blockIconEvent({ detail }: any) { - const ids: string[] = []; - detail.blockElements.forEach((item: HTMLElement) => { - ids.push(item.getAttribute("data-node-id")); - }); detail.menu.addItem({ iconHTML: "", - type: "readonly", - label: "IDs
" + ids.join("
"), + label: this.i18n.removeSpace, + click: () => { + const doOperations: IOperation[] = []; + detail.blockElements.forEach((item: HTMLElement) => { + const editElement = item.querySelector('[contenteditable="true"]'); + if (editElement) { + editElement.textContent = editElement.textContent.replace(/ /g, ""); + doOperations.push({ + id: item.dataset.nodeId, + data: item.outerHTML, + action: "update" + }); + } + }); + detail.protyle.getInstance().transaction(doOperations); + } }); } @@ -488,9 +507,15 @@ export default class PluginSample extends Plugin { } }, { icon: "iconSelect", - label: "On loaded-protyle", + label: "On loaded-protyle-static", click: () => { - this.eventBus.on("loaded-protyle", this.eventBusLog); + this.eventBus.on("loaded-protyle-static", this.eventBusLog); + } + }, { + icon: "iconClose", + label: "Off loaded-protyle-static", + click: () => { + this.eventBus.off("loaded-protyle-static", this.eventBusLog); } }, { icon: "iconSelect", @@ -517,10 +542,16 @@ export default class PluginSample extends Plugin { this.eventBus.off("destroy-protyle", this.eventBusLog); } }, { - icon: "iconClose", - label: "Off loaded-protyle", + icon: "iconSelect", + label: "On open-menu-doctree", click: () => { - this.eventBus.off("loaded-protyle", this.eventBusLog); + this.eventBus.on("open-menu-doctree", this.eventBusLog); + } + }, { + icon: "iconClose", + label: "Off open-menu-doctree", + click: () => { + this.eventBus.off("open-menu-doctree", this.eventBusLog); } }, { icon: "iconSelect", @@ -630,6 +661,18 @@ export default class PluginSample extends Plugin { click: () => { this.eventBus.off("input-search", this.eventBusLog); } + }, { + icon: "iconSelect", + label: "On paste", + click: () => { + this.eventBus.on("paste", this.eventBusPaste); + } + }, { + icon: "iconClose", + label: "Off paste", + click: () => { + this.eventBus.off("paste", this.eventBusPaste); + } }, { icon: "iconSelect", label: "On open-siyuan-url-plugin", From bc635356dc37fb74e7a34a6ba2912931f27872f7 Mon Sep 17 00:00:00 2001 From: frostime Date: Fri, 27 Oct 2023 21:04:12 +0800 Subject: [PATCH 06/88] fix protyle bug --- src/hello.svelte | 2 +- src/index.ts | 41 ++++++++++++++++++++--------------------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/hello.svelte b/src/hello.svelte index 6d10108..63a54a2 100644 --- a/src/hello.svelte +++ b/src/hello.svelte @@ -6,7 +6,7 @@ export let app; let time: string = ""; - let ver: string; + let ver: string = ""; let divProtyle: HTMLDivElement; let protyle: any; diff --git a/src/index.ts b/src/index.ts index 353d472..aa7bd75 100644 --- a/src/index.ts +++ b/src/index.ts @@ -85,27 +85,6 @@ export default class PluginSample extends Plugin { element: statusIconTemp.content.firstElementChild as HTMLElement, }); - let tabDiv = document.createElement("div"); - new HelloExample({ - target: tabDiv, - props: { - app: this.app, - } - }); - this.customTab = this.addTab({ - type: TAB_TYPE, - init() { - this.element.appendChild(tabDiv); - console.log(this.element); - }, - beforeDestroy() { - console.log("before destroy tab:", TAB_TYPE); - }, - destroy() { - console.log("destroy tab:", TAB_TYPE); - } - }); - this.addCommand({ langKey: "showDialog", hotkey: "⇧⌘O", @@ -244,6 +223,26 @@ export default class PluginSample extends Plugin { // this.loadData(STORAGE_NAME); this.settingUtils.load(); console.log(`frontend: ${getFrontend()}; backend: ${getBackend()}`); + let tabDiv = document.createElement("div"); + new HelloExample({ + target: tabDiv, + props: { + app: this.app, + } + }); + this.customTab = this.addTab({ + type: TAB_TYPE, + init() { + this.element.appendChild(tabDiv); + console.log(this.element); + }, + beforeDestroy() { + console.log("before destroy tab:", TAB_TYPE); + }, + destroy() { + console.log("destroy tab:", TAB_TYPE); + } + }); } async onunload() { From c580fb7a0040ecc6987bd00205927af76d790404 Mon Sep 17 00:00:00 2001 From: frostime Date: Fri, 27 Oct 2023 22:11:43 +0800 Subject: [PATCH 07/88] update setting utils --- src/libs/setting-utils.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index ff78af8..17cc555 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -17,7 +17,7 @@ export class SettingUtils { settings: Map = new Map(); elements: Map = new Map(); - constructor(plugin: Plugin, name?: string, width?: string, height?: string) { + constructor(plugin: Plugin, name?: string, width?: string, height?: string, callback?: (data: any) => void) { this.name = name ?? 'settings'; this.plugin = plugin; this.file = this.name.endsWith('.json') ? this.name : `${this.name}.json`; @@ -29,8 +29,12 @@ export class SettingUtils { this.updateValue(key); } let data = this.dump(); - this.plugin.data[this.name] = data; - this.save(); + if (callback !== undefined) { + callback(data); + } else { + this.plugin.data[this.name] = data; + this.save(); + } } }); } From 3343eb7e5c57c9bed51aa199bca6299e74f70585 Mon Sep 17 00:00:00 2001 From: frostime Date: Fri, 27 Oct 2023 22:12:43 +0800 Subject: [PATCH 08/88] update --- src/libs/setting-utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index 17cc555..79f35f4 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -3,7 +3,7 @@ * @Author : frostime * @Date : 2023-09-16 18:05:00 * @FilePath : /src/libs/setting-utils.ts - * @LastEditTime : 2023-09-16 18:17:03 + * @LastEditTime : 2023-10-27 22:12:37 * @Description : A utility for siyuan plugin settings */ @@ -17,7 +17,7 @@ export class SettingUtils { settings: Map = new Map(); elements: Map = new Map(); - constructor(plugin: Plugin, name?: string, width?: string, height?: string, callback?: (data: any) => void) { + constructor(plugin: Plugin, name?: string, callback?: (data: any) => void, width?: string, height?: string) { this.name = name ?? 'settings'; this.plugin = plugin; this.file = this.name.endsWith('.json') ? this.name : `${this.name}.json`; From 7d95423d24ba8154b0ab27e75619419680af6842 Mon Sep 17 00:00:00 2001 From: frostime Date: Sat, 28 Oct 2023 16:52:03 +0800 Subject: [PATCH 09/88] update --- src/libs/setting-utils.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index 79f35f4..b092a27 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -3,7 +3,7 @@ * @Author : frostime * @Date : 2023-09-16 18:05:00 * @FilePath : /src/libs/setting-utils.ts - * @LastEditTime : 2023-10-27 22:12:37 + * @LastEditTime : 2023-10-28 16:52:01 * @Description : A utility for siyuan plugin settings */ @@ -41,13 +41,13 @@ export class SettingUtils { async load() { let data = await this.plugin.loadData(this.file); + console.debug('Load config:', data); if (data) { for (let [key, item] of this.settings) { item.value = data?.[key] ?? item.value; } } this.plugin.data[this.name] = this.dump(); - console.log(data); return data; } @@ -159,6 +159,7 @@ export class SettingUtils { break; case 'slider': element.value = item.value; + element.ariaLabel = item.value; break; case 'textinput': element.value = item.value; @@ -173,7 +174,7 @@ export class SettingUtils { private updateValue(key: string) { let item = this.settings.get(key); let element = this.elements.get(key) as any; - console.log(element, element?.value); + // console.debug(element, element?.value); switch (item.type) { case 'checkbox': item.value = element.checked; @@ -182,7 +183,7 @@ export class SettingUtils { item.value = element.value; break; case 'slider': - item.value = parseInt(element.value); + item.value = element.value; break; case 'textinput': item.value = element.value; From 5f59ffefe42923a655b8381a9cf12c0bc6907fb6 Mon Sep 17 00:00:00 2001 From: frostime Date: Sat, 28 Oct 2023 18:22:56 +0800 Subject: [PATCH 10/88] update keywords --- plugin.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugin.json b/plugin.json index 04236da..f3e2682 100644 --- a/plugin.json +++ b/plugin.json @@ -29,5 +29,8 @@ "custom": [ "https://afdian.net/a/frostime" ] - } + }, + "keywords": [ + "plugin", "sample", "插件样例" + ] } From 3de8bc61344ec06257d10c5b2c435ca2df831b52 Mon Sep 17 00:00:00 2001 From: frostime Date: Sun, 19 Nov 2023 11:49:25 +0800 Subject: [PATCH 11/88] =?UTF-8?q?=F0=9F=90=B3=20chore(update):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=A8=A1=E6=9D=BF=E7=9A=84=E4=BE=9D=E8=B5=96=E3=80=81?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E7=AD=89=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++++-- README_zh_CN.md | 8 ++++++-- package.json | 2 +- plugin.json | 4 ++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 4a2b21b..4f79c10 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [中文版](./README_zh_CN.md) -> Consistent with [siyuan/plugin-sample](https://github.com/siyuan-note/plugin-sample) [v0.2.6](https://github.com/siyuan-note/plugin-sample/tree/v0.2.6) +> Consistent with [siyuan/plugin-sample](https://github.com/siyuan-note/plugin-sample) [v0.2.8](https://github.com/siyuan-note/plugin-sample/tree/v0.2.8) @@ -98,7 +98,10 @@ conveniently. "custom": [ "https://ld246.com/sponsor" ] - } + }, + "keywords": [ + "sample", "示例" + ] } ``` @@ -137,6 +140,7 @@ conveniently. * `patreon`: Patreon name * `github`: GitHub login name * `custom`: Custom sponsorship link list +* `keywords`: Search keyword list, used for marketplace search function ## Package diff --git a/README_zh_CN.md b/README_zh_CN.md index bf72da3..5b3e6e8 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -4,7 +4,7 @@ [English](./README.md) -> 本例和 [siyuan/plugin-sample](https://github.com/siyuan-note/plugin-sample) [v0.2.6](https://github.com/siyuan-note/plugin-sample/tree/v0.2.6) +> 本例同 [siyuan/plugin-sample](https://github.com/siyuan-note/plugin-sample) [v0.2.8](https://github.com/siyuan-note/plugin-sample/tree/v0.2.8) 1. 使用 vite 打包 2. 使用符号链接、而不是把项目放到插件目录下的模式进行开发 @@ -95,7 +95,10 @@ "custom": [ "https://ld246.com/sponsor" ] - } + }, + "keywords": [ + "sample", "示例" + ] } ``` @@ -133,6 +136,7 @@ * `patreon`:Patreon 名称 * `github`:GitHub 登录名 * `custom`:自定义赞助链接列表 +* `keywords`:搜索关键字列表,用于集市搜索功能 ## 打包 diff --git a/package.json b/package.json index bfe4eb0..e4c06a2 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "minimist": "^1.2.8", "rollup-plugin-livereload": "^2.0.5", "sass": "^1.62.1", - "siyuan": "0.8.7", + "siyuan": "0.8.8", "svelte": "^3.57.0", "ts-node": "^10.9.1", "typescript": "^5.0.4", diff --git a/plugin.json b/plugin.json index f3e2682..7bb3bea 100644 --- a/plugin.json +++ b/plugin.json @@ -2,8 +2,8 @@ "name": "plugin-sample-vite-svelte", "author": "frostime", "url": "https://github.com/siyuan-note/plugin-sample-vite-svelte", - "version": "0.2.6", - "minAppVersion": "2.10.12", + "version": "0.2.8", + "minAppVersion": "2.10.14", "backends": [ "windows", "linux", From 8e841a4a905f16c9accf2150e1e89b905fab0e5d Mon Sep 17 00:00:00 2001 From: frostime Date: Sun, 19 Nov 2023 12:17:42 +0800 Subject: [PATCH 12/88] =?UTF-8?q?=E2=9C=A8=20feat(update):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=8F=92=E4=BB=B6=E6=A8=A1=E6=9D=BF=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 10 +++++++++- src/api.ts | 1 - src/hello.svelte | 5 +++++ src/index.ts | 24 ++++++++++++++++++++---- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aadd6ee..4411dd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Changelog -## 0.2.7 2023-10 +## 0.2.8 2023-11-15 + +* [`resize` cannot be triggered after dragging to unpin the dock](https://github.com/siyuan-note/siyuan/issues/9640) + +## 0.2.7 2023-10-31 + +* [Export `Constants` to plugin](https://github.com/siyuan-note/siyuan/issues/9555) +* [Add plugin `app.appId`](https://github.com/siyuan-note/siyuan/issues/9538) +* [Add plugin event bus `switch-protyle`](https://github.com/siyuan-note/siyuan/issues/9454) ## 0.2.6 2023-10-24 diff --git a/src/api.ts b/src/api.ts index 4b12999..7202000 100644 --- a/src/api.ts +++ b/src/api.ts @@ -6,7 +6,6 @@ * API 文档见 [API_zh_CN.md](https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md) */ -import { time } from "console"; import { fetchSyncPost, IWebSocketData } from "siyuan"; diff --git a/src/hello.svelte b/src/hello.svelte index 63a54a2..cc9f0dd 100644 --- a/src/hello.svelte +++ b/src/hello.svelte @@ -36,6 +36,11 @@
+
appId:
+
+
${app?.appId}
+
+
API demo:
diff --git a/src/index.ts b/src/index.ts index aa7bd75..6fb4f0a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,9 +9,10 @@ import { getFrontend, getBackend, IModel, - Setting, - fetchPost, - Protyle, openWindow, IOperation + Protyle, + openWindow, + IOperation, + Constants } from "siyuan"; import "@/index.scss"; @@ -120,6 +121,9 @@ export default class PluginSample extends Plugin { text: "This is my custom dock" }, type: DOCK_TYPE, + resize() { + console.log(DOCK_TYPE + " resize"); + }, init() { this.element.innerHTML = `
@@ -308,7 +312,7 @@ export default class PluginSample extends Plugin { private showDialog() { let dialog = new Dialog({ - title: "Hello World", + title: `SiYuan ${Constants.SIYUAN_VERSION}`, content: `
`, width: this.isMobile ? "92vw" : "720px", destroyCallback(options) { @@ -528,6 +532,18 @@ export default class PluginSample extends Plugin { click: () => { this.eventBus.off("loaded-protyle-dynamic", this.eventBusLog); } + }, { + icon: "iconSelect", + label: "On switch-protyle", + click: () => { + this.eventBus.on("switch-protyle", this.eventBusLog); + } + }, { + icon: "iconClose", + label: "Off switch-protyle", + click: () => { + this.eventBus.off("switch-protyle", this.eventBusLog); + } }, { icon: "iconSelect", label: "On destroy-protyle", From 962f879fa25d0e682f6da3d78f91467109846b49 Mon Sep 17 00:00:00 2001 From: frostime Date: Sun, 19 Nov 2023 12:30:11 +0800 Subject: [PATCH 13/88] =?UTF-8?q?=E2=9C=A8=20feat(api):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=90=8E=E7=AB=AFAPI=20`getIDsByHPath`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/api.ts b/src/api.ts index 7202000..9a4ff3f 100644 --- a/src/api.ts +++ b/src/api.ts @@ -131,6 +131,16 @@ export async function getHPathByID(id: BlockId): Promise { return request(url, data); } + +export async function getIDsByHPath(notebook: NotebookId, path: string): Promise { + let data = { + notebook: notebook, + path: path + }; + let url = '/api/filetree/getIDsByHPath'; + return request(url, data); +} + // **************************************** Asset Files **************************************** export async function upload(assetsDirPath: string, files: any[]): Promise { From 7f57c40db532464a53e9699de38ef24da5fd9a4d Mon Sep 17 00:00:00 2001 From: Frostime Date: Tue, 21 Nov 2023 19:55:28 +0800 Subject: [PATCH 14/88] =?UTF-8?q?doc:=20=E5=AE=A3=E4=BC=A0=E4=B8=80?= =?UTF-8?q?=E4=B8=8B=E6=97=A0=20svelte=20=E7=89=88=E6=9C=AC=E7=9A=84?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +++ README_zh_CN.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index 4f79c10..b7da17d 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,9 @@ 1. Using vite for packaging 2. Use symbolic linking instead of putting the project into the plugins directory program development 3. Built-in support for the svelte framework + + > If don't want svelte, turn to this template: [frostime/plugin-sample-vite](https://github.com/frostime/plugin-sample-vite) + 4. Provides a github action template to automatically generate package.zip and upload to new release diff --git a/README_zh_CN.md b/README_zh_CN.md index 5b3e6e8..950f11c 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -9,6 +9,9 @@ 1. 使用 vite 打包 2. 使用符号链接、而不是把项目放到插件目录下的模式进行开发 3. 内置对 svelte 框架的支持 + + > 如果不想要 svelte,请移步 [frostime/plugin-sample-vite](https://github.com/frostime/plugin-sample-vite) + 4. 提供一个github action 模板,能自动生成package.zip并上传到新版本中 ## 开始 From ec8d768d2d9deb448f6a7932472e6f7ce308a89c Mon Sep 17 00:00:00 2001 From: frostime Date: Mon, 27 Nov 2023 09:28:36 +0800 Subject: [PATCH 15/88] =?UTF-8?q?:construction=5Fworker:=20ci:=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20vite=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/vite.config.ts b/vite.config.ts index 2af9f2f..f83f26c 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -57,6 +57,7 @@ export default defineConfig({ // 在这里自定义变量 define: { "process.env.DEV_MODE": `"${isWatch}"`, + "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV) }, build: { From b0d28e2513d6edc2e221ce1ccdfdea101ba450fa Mon Sep 17 00:00:00 2001 From: frostime Date: Tue, 28 Nov 2023 21:24:19 +0800 Subject: [PATCH 16/88] =?UTF-8?q?:hammer:=20refactor(setting):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E4=BA=86Svelte=E8=AE=BE=E7=BD=AE=E7=9A=84=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 SettingPanel 作为基本模板 - 更改了 settingitem 的类型定义 --- src/index.ts | 18 ++--- src/libs/index.d.ts | 5 +- src/libs/setting-item.svelte | 14 +++- src/libs/setting-panel.svelte | 139 +++++++++++----------------------- src/libs/setting-utils.ts | 10 ++- src/setting-example.svelte | 99 ++++++++++++++++++++++++ 6 files changed, 169 insertions(+), 116 deletions(-) create mode 100644 src/setting-example.svelte diff --git a/src/index.ts b/src/index.ts index 6fb4f0a..349aca6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,7 +17,7 @@ import { import "@/index.scss"; import HelloExample from "@/hello.svelte"; -import SettingPannel from "@/libs/setting-panel.svelte"; +import SettingExample from "@/setting-example.svelte"; import { SettingUtils } from "./libs/setting-utils"; @@ -173,16 +173,10 @@ export default class PluginSample extends Plugin { title: "Readonly text", description: "Select description", select: { - options: [ - { - val: 1, - text: "Option 1" - }, - { - val: 2, - text: "Option 2" - } - ] + options: { + 1: "Option 1", + 2: "Option 2" + } } }); this.settingUtils.addItem({ @@ -270,7 +264,7 @@ export default class PluginSample extends Plugin { pannel.$destroy(); } }); - let pannel = new SettingPannel({ + let pannel = new SettingExample({ target: dialog.element.querySelector("#SettingPanel"), }); } diff --git a/src/libs/index.d.ts b/src/libs/index.d.ts index b46f655..379d841 100644 --- a/src/libs/index.d.ts +++ b/src/libs/index.d.ts @@ -5,13 +5,16 @@ interface ISettingItem { type: TSettingItemType; title: string; description?: string; + text?: { + placeholder?: string; + }; slider?: { min: number; max: number; step: number; }; select?: { - options: {val: any; text: string}[]; + options: { [key: string | number]: string }; }; button?: { label: string; diff --git a/src/libs/setting-item.svelte b/src/libs/setting-item.svelte index b728cf4..6f17890 100644 --- a/src/libs/setting-item.svelte +++ b/src/libs/setting-item.svelte @@ -2,13 +2,13 @@ import { createEventDispatcher } from "svelte"; export let type: string; // Setting Type export let title: string; // Displayint Setting Title - export let text: string; // Displaying Setting Text + export let description: string; // Displaying Setting Text export let settingKey: string; export let settingValue: any; //Optional export let placeholder: string = ""; // Use it if type is input - export let options: { [key: string]: string } = {}; // Use it if type is select + export let options: { [key: string | number]: string } = {}; // Use it if type is select export let slider: { min: number; max: number; @@ -30,7 +30,7 @@
{title}
- {text} + {@html description}
@@ -53,6 +53,14 @@ bind:value={settingValue} on:change={changed} /> + {:else if type === "number"} + {:else if type === "button"} {:else if type === "select"} diff --git a/src/libs/setting-panel.svelte b/src/libs/setting-panel.svelte index fc5e508..038d890 100644 --- a/src/libs/setting-panel.svelte +++ b/src/libs/setting-panel.svelte @@ -3,7 +3,7 @@ Author : frostime Date : 2023-07-01 19:23:50 FilePath : /src/libs/setting-panel.svelte - LastEditTime : 2023-11-28 21:45:10 + LastEditTime : 2024-04-27 16:46:49 Description : --> @@ -83,6 +99,7 @@ settingItems={SettingItems} display={focusGroup === groups[0]} on:changed={onChanged} + on:click={({ detail }) => { console.debug("Click:", detail.key); }} >
💡 This is our default settings. From 56be185458ea2c96ca276305e3c6b687c4d4f1e6 Mon Sep 17 00:00:00 2001 From: frostime Date: Sun, 28 Apr 2024 17:48:49 +0800 Subject: [PATCH 54/88] =?UTF-8?q?=E2=9C=A8=20misc(setting-utils)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 14 ++--- src/libs/setting-utils.ts | 114 ++++++++++++++++++++++---------------- 2 files changed, 74 insertions(+), 54 deletions(-) diff --git a/src/index.ts b/src/index.ts index 9a47d54..49cc9c4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -164,13 +164,6 @@ export default class PluginSample extends Plugin { }); this.settingUtils = new SettingUtils(this, STORAGE_NAME); - - try { - this.settingUtils.load(); - } catch (error) { - console.error("Error loading settings storage, probably empty config json:", error); - } - this.settingUtils.addItem({ key: "Input", value: "", @@ -274,6 +267,13 @@ export default class PluginSample extends Plugin { description: this.i18n.hintDesc, }); + try { + this.settingUtils.load(); + } catch (error) { + console.error("Error loading settings storage, probably empty config json:", error); + } + + this.protyleSlash = [{ filter: ["insert emoji 😊", "插入表情 😊", "crbqwx"], html: `
${this.i18n.insertEmoji}😊
`, diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index ddb576c..c5bff05 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -3,12 +3,44 @@ * @Author : frostime * @Date : 2023-12-17 18:28:19 * @FilePath : /src/libs/setting-utils.ts - * @LastEditTime : 2024-04-27 16:38:09 + * @LastEditTime : 2024-04-28 17:43:43 * @Description : */ import { Plugin, Setting } from 'siyuan'; +const valueOf = (ele: HTMLElement) => { + if (ele instanceof HTMLInputElement) { + if (ele.type === 'checkbox') { + return ele.checked; + } else { + return ele.value; + } + } else if (ele instanceof HTMLSelectElement) { + return ele.value; + } else if (ele instanceof HTMLTextAreaElement) { + return ele.value; + } else { + return ele.textContent; + } +} + +const setValue = (ele: HTMLElement, value: any) => { + if (ele instanceof HTMLInputElement) { + if (ele.type === 'checkbox') { + ele.checked = value; + } else { + ele.value = value; + } + } else if (ele instanceof HTMLSelectElement) { + ele.value = value; + } else if (ele instanceof HTMLTextAreaElement) { + ele.value = value; + } else { + ele.textContent = value; + } +} + export class SettingUtils { plugin: Plugin; name: string; @@ -31,10 +63,9 @@ export class SettingUtils { let data = this.dump(); if (callback !== undefined) { callback(data); - } else { - this.plugin.data[this.name] = data; - this.save(); } + this.plugin.data[this.name] = data; + this.save(); }, destroyCallback: () => { //从值恢复元素 @@ -73,21 +104,6 @@ export class SettingUtils { return this.settings.get(key)?.value; } - /** - * Read in real time, - * do not read from the configuration file - * @param key key name - * @returns value in html - */ - take(key: string) { - let element = this.elements.get(key) as any; - if (!element){ - return - } - this.settings.set(key, element.value) - return element.value - } - /** * Set data to this.settings, * but do not save it to the configuration file @@ -113,20 +129,38 @@ export class SettingUtils { if (item) { item.value = value; this.updateElementFromValue(key); - await this.save() + await this.save(); } } + /** + * Read in the value of element instead of setting obj in real time + * @param key key name + * @param apply whether to apply the value to the setting object + * if true, the value will be applied to the setting object + * @returns value in html + */ + take(key: string, apply: boolean = false) { + let element = this.elements.get(key) as any; + if (!element){ + return + } + if (apply) { + this.updateValueFromElement(key); + } + return valueOf(element) + } + /** * Read data from html and save it * @param key key name * @param value value - * @return value in html + * @return value in html */ async takeAndSave(key: string) { - let value = this.take(key) - await this.save() - return value + let value = this.take(key, true); + await this.save(); + return value; } /** @@ -248,6 +282,7 @@ export class SettingUtils { title: item.title, description: item?.description, createActionElement: () => { + this.updateElementFromValue(item.key); let element = this.getElement(item.key); return element; } @@ -255,40 +290,19 @@ export class SettingUtils { } /** - * Set the value in the setting to the value of the element - * and return the element information + * return the setting element * @param key key name * @returns element */ getElement(key: string) { - let item = this.settings.get(key); + // let item = this.settings.get(key); let element = this.elements.get(key) as any; - switch (item.type) { - case 'checkbox': - element.value = element.checked ? true : false; - element.checked = item.value; - break; - case 'select': - element.value = item.value; - break; - case 'slider': - element.value = item.value; - element.ariaLabel = item.value; - break; - case 'textinput': - element.value = item.value; - break; - case 'textarea': - element.value = item.value; - break; - } return element; } private updateValueFromElement(key: string) { let item = this.settings.get(key); let element = this.elements.get(key) as any; - // console.debug(element, element?.value); switch (item.type) { case 'checkbox': item.value = element.checked; @@ -305,6 +319,9 @@ export class SettingUtils { case 'textarea': item.value = element.value; break; + case 'number': + item.value = parseInt(element.value); + break; } } @@ -327,6 +344,9 @@ export class SettingUtils { case 'textarea': element.value = item.value; break; + case 'number': + element.value = item.value; + break; } } } \ No newline at end of file From 57cc62f7b516a9331ad1cfaeb7f5fce3f163ead5 Mon Sep 17 00:00:00 2001 From: frostime Date: Sun, 28 Apr 2024 17:50:52 +0800 Subject: [PATCH 55/88] =?UTF-8?q?=F0=9F=8E=A8=20refactor:=20setting-utils?= =?UTF-8?q?=20args?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 4 +++- src/libs/setting-utils.ts | 22 ++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/index.ts b/src/index.ts index 49cc9c4..704ad00 100644 --- a/src/index.ts +++ b/src/index.ts @@ -163,7 +163,9 @@ export default class PluginSample extends Plugin { } }); - this.settingUtils = new SettingUtils(this, STORAGE_NAME); + this.settingUtils = new SettingUtils({ + plugin: this, name: STORAGE_NAME + }); this.settingUtils.addItem({ key: "Input", value: "", diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index c5bff05..c839d1a 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -3,7 +3,7 @@ * @Author : frostime * @Date : 2023-12-17 18:28:19 * @FilePath : /src/libs/setting-utils.ts - * @LastEditTime : 2024-04-28 17:43:43 + * @LastEditTime : 2024-04-28 17:49:31 * @Description : */ @@ -49,20 +49,26 @@ export class SettingUtils { settings: Map = new Map(); elements: Map = new Map(); - constructor(plugin: Plugin, name?: string, callback?: (data: any) => void, width?: string, height?: string) { - this.name = name ?? 'settings'; - this.plugin = plugin; + constructor(args: { + plugin: Plugin, + name?: string, + callback?: (data: any) => void, + width?: string, + height?: string + }) { + this.name = args.name ?? 'settings'; + this.plugin = args.plugin; this.file = this.name.endsWith('.json') ? this.name : `${this.name}.json`; this.plugin.setting = new Setting({ - width: width, - height: height, + width: args.width, + height: args.height, confirmCallback: () => { for (let key of this.settings.keys()) { this.updateValueFromElement(key); } let data = this.dump(); - if (callback !== undefined) { - callback(data); + if (args.callback !== undefined) { + args.callback(data); } this.plugin.data[this.name] = data; this.save(); From 0df9ec29ea61f34655028b1f6ddaa331e1f8c3d0 Mon Sep 17 00:00:00 2001 From: frostime Date: Mon, 29 Apr 2024 17:43:02 +0800 Subject: [PATCH 56/88] =?UTF-8?q?=E2=9C=A8=20feat(setting-utils):=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=AE=9A=E4=B9=89=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/index.d.ts | 1 + src/libs/setting-utils.ts | 148 ++++++++++++++++++++++---------------- 2 files changed, 89 insertions(+), 60 deletions(-) diff --git a/src/libs/index.d.ts b/src/libs/index.d.ts index cdb1ea3..9e0b889 100644 --- a/src/libs/index.d.ts +++ b/src/libs/index.d.ts @@ -19,4 +19,5 @@ interface ISettingItem { label: string; callback: () => void; } + createElement?: (currentVal: any) => HTMLElement; } diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index c839d1a..f43ab36 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -3,35 +3,45 @@ * @Author : frostime * @Date : 2023-12-17 18:28:19 * @FilePath : /src/libs/setting-utils.ts - * @LastEditTime : 2024-04-28 17:49:31 + * @LastEditTime : 2024-04-29 17:17:19 * @Description : */ import { Plugin, Setting } from 'siyuan'; -const valueOf = (ele: HTMLElement) => { +const valueOf = (ele: HTMLElement, parseNumber: Function=parseInt) => { + let val: any = null; if (ele instanceof HTMLInputElement) { if (ele.type === 'checkbox') { - return ele.checked; + val = ele.checked; } else { - return ele.value; + if (ele.type === 'number') { + val = parseNumber(ele.value); + } else { + val = ele.value; + } } } else if (ele instanceof HTMLSelectElement) { - return ele.value; + val = ele.value; } else if (ele instanceof HTMLTextAreaElement) { - return ele.value; + val = ele.value; } else { - return ele.textContent; + val = ele?.textContent; } + return val; } const setValue = (ele: HTMLElement, value: any) => { + if (ele === null || ele === undefined) return; if (ele instanceof HTMLInputElement) { if (ele.type === 'checkbox') { ele.checked = value; } else { ele.value = value; } + if (ele.type === 'range') { + ele.ariaLabel = value; + } } else if (ele instanceof HTMLSelectElement) { ele.value = value; } else if (ele instanceof HTMLTextAreaElement) { @@ -74,7 +84,7 @@ export class SettingUtils { this.save(); }, destroyCallback: () => { - //从值恢复元素 + //Restore the original value for (let key of this.settings.keys()) { this.updateElementFromValue(key); } @@ -197,8 +207,6 @@ export class SettingUtils { */ dump(): Object { let data: any = {}; - - for (let [key, item] of this.settings) { if (item.type === 'button') continue; data[key] = item.value; @@ -208,6 +216,33 @@ export class SettingUtils { addItem(item: ISettingItem) { this.settings.set(item.key, item); + if (item.createElement === undefined) { + let itemElement = this.createDefaultElement(item); + this.elements.set(item.key, itemElement); + this.plugin.setting.addItem({ + title: item.title, + description: item?.description, + createActionElement: () => { + this.updateElementFromValue(item.key); + let element = this.getElement(item.key); + return element; + } + }); + } else { + this.plugin.setting.addItem({ + title: item.title, + description: item?.description, + createActionElement: () => { + let val = this.get(item.key); + let element = item.createElement(val); + this.elements.set(item.key, element); + return element; + } + }); + } + } + + createDefaultElement(item: ISettingItem) { let itemElement: HTMLElement; switch (item.type) { case 'checkbox': @@ -283,16 +318,7 @@ export class SettingUtils { itemElement = hintElement; break; } - this.elements.set(item.key, itemElement); - this.plugin.setting.addItem({ - title: item.title, - description: item?.description, - createActionElement: () => { - this.updateElementFromValue(item.key); - let element = this.getElement(item.key); - return element; - } - }) + return itemElement; } /** @@ -309,50 +335,52 @@ export class SettingUtils { private updateValueFromElement(key: string) { let item = this.settings.get(key); let element = this.elements.get(key) as any; - switch (item.type) { - case 'checkbox': - item.value = element.checked; - break; - case 'select': - item.value = element.value; - break; - case 'slider': - item.value = element.value; - break; - case 'textinput': - item.value = element.value; - break; - case 'textarea': - item.value = element.value; - break; - case 'number': - item.value = parseInt(element.value); - break; - } + item.value = valueOf(element); + // switch (item.type) { + // case 'checkbox': + // item.value = element.checked; + // break; + // case 'select': + // item.value = element.value; + // break; + // case 'slider': + // item.value = element.value; + // break; + // case 'textinput': + // item.value = element.value; + // break; + // case 'textarea': + // item.value = element.value; + // break; + // case 'number': + // item.value = parseInt(element.value); + // break; + // } } private updateElementFromValue(key: string) { let item = this.settings.get(key); let element = this.elements.get(key) as any; - switch (item.type) { - case 'checkbox': - element.checked = item.value; - break; - case 'select': - element.value = item.value; - break; - case 'slider': - element.value = item.value; - break; - case 'textinput': - element.value = item.value; - break; - case 'textarea': - element.value = item.value; - break; - case 'number': - element.value = item.value; - break; - } + setValue(element, item.value); + // switch (item.type) { + // case 'checkbox': + // element.checked = item.value; + // break; + // case 'select': + // element.value = item.value; + // break; + // case 'slider': + // element.value = item.value; + // break; + // case 'textinput': + // element.value = item.value; + // break; + // case 'textarea': + // element.value = item.value; + // break; + // case 'number': + // element.value = item.value; + // break; + // } } } \ No newline at end of file From 4a9d0f39531157c69af1c212c2ab8e251bb08d3a Mon Sep 17 00:00:00 2001 From: frostime Date: Tue, 30 Apr 2024 15:57:43 +0800 Subject: [PATCH 57/88] =?UTF-8?q?=F0=9F=94=A5=20remove=20eslint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .eslintignore | 2 -- .eslintrc.cjs | 38 -------------------------------------- package.json | 1 - 3 files changed, 41 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.cjs diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index f06235c..0000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -dist diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 0781605..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,38 +0,0 @@ -module.exports = { - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:svelte/recommended", - "turbo", - "prettier", - ], - - parser: "@typescript-eslint/parser", - - overrides: [ - { - files: ["*.svelte"], - parser: "svelte-eslint-parser", - // Parse the script in `.svelte` as TypeScript by adding the following configuration. - parserOptions: { - parser: "@typescript-eslint/parser", - }, - }, - ], - - plugins: ["@typescript-eslint", "prettier"], - - rules: { - // Note: you must disable the base rule as it can report incorrect errors - semi: "off", - quotes: "off", - "no-undef": "off", - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/no-this-alias": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-unused-vars": "off", - "@typescript-eslint/no-explicit-any": "off", - "turbo/no-undeclared-env-vars": "off", - "prettier/prettier": "error", - }, -} diff --git a/package.json b/package.json index df94e90..4bccd57 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,6 @@ "@sveltejs/vite-plugin-svelte": "^3.0.0", "@tsconfig/svelte": "^4.0.1", "@types/node": "^20.3.0", - "eslint": "^8.42.0", "fast-glob": "^3.2.12", "glob": "^7.2.3", "js-yaml": "^4.1.0", From 7159755c7074be1c7054141cc74bb50b0ece02f6 Mon Sep 17 00:00:00 2001 From: frostime Date: Tue, 30 Apr 2024 16:00:03 +0800 Subject: [PATCH 58/88] =?UTF-8?q?=F0=9F=94=A8=20=E8=B0=83=E6=95=B4=20setti?= =?UTF-8?q?ng=20=E7=9A=84=20interface=20=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/index.d.ts | 32 +++++++++++++++++++++++++------- src/libs/setting-utils.ts | 8 ++++---- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/libs/index.d.ts b/src/libs/index.d.ts index 9e0b889..7ca733f 100644 --- a/src/libs/index.d.ts +++ b/src/libs/index.d.ts @@ -1,10 +1,17 @@ +/* + * Copyright (c) 2024 by frostime. All Rights Reserved. + * @Author : frostime + * @Date : 2024-04-19 18:30:12 + * @FilePath : /src/libs/index.d.ts + * @LastEditTime : 2024-04-30 15:53:15 + * @Description : + */ type TSettingItemType = "checkbox" | "select" | "textinput" | "textarea" | "number" | "slider" | "button" | "hint"; -interface ISettingItem { + +interface ISettingItemCore { + type: TSettingItemType; key: string; value: any; - type: TSettingItemType; - title: string; - description?: string; placeholder?: string; slider?: { min: number; @@ -12,12 +19,23 @@ interface ISettingItem { step: number; }; options?: { [key: string | number]: string }; - action?: { - callback: () => void; - } button?: { label: string; callback: () => void; } +} + +interface ISettingItem extends ISettingItemCore { + title: string; + description: string; +} + + +//Interface for setting-utils +interface ISettingUtilsItem extends ISettingItem { + direction?: "row" | "column"; + action?: { + callback: () => void; + } createElement?: (currentVal: any) => HTMLElement; } diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index f43ab36..2a3926b 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -3,7 +3,7 @@ * @Author : frostime * @Date : 2023-12-17 18:28:19 * @FilePath : /src/libs/setting-utils.ts - * @LastEditTime : 2024-04-29 17:17:19 + * @LastEditTime : 2024-04-30 15:50:07 * @Description : */ @@ -56,7 +56,7 @@ export class SettingUtils { name: string; file: string; - settings: Map = new Map(); + settings: Map = new Map(); elements: Map = new Map(); constructor(args: { @@ -214,7 +214,7 @@ export class SettingUtils { return data; } - addItem(item: ISettingItem) { + addItem(item: ISettingUtilsItem) { this.settings.set(item.key, item); if (item.createElement === undefined) { let itemElement = this.createDefaultElement(item); @@ -242,7 +242,7 @@ export class SettingUtils { } } - createDefaultElement(item: ISettingItem) { + createDefaultElement(item: ISettingUtilsItem) { let itemElement: HTMLElement; switch (item.type) { case 'checkbox': From 59daefa941e3fb2b2c590a58a8872c9ea8cfb519 Mon Sep 17 00:00:00 2001 From: frostime Date: Tue, 30 Apr 2024 16:15:58 +0800 Subject: [PATCH 59/88] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20update=20siyuan:=20a?= =?UTF-8?q?dd=20`direction`=20parameter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- README_zh_CN.md | 2 +- package.json | 6 +++--- plugin.json | 4 ++-- src/index.ts | 1 + src/libs/setting-utils.ts | 6 +++++- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3c233a7..09c8cdd 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [中文版](./README_zh_CN.md) -> Consistent with [siyuan/plugin-sample](https://github.com/siyuan-note/plugin-sample) [v0.3.4](https://github.com/siyuan-note/plugin-sample/tree/v0.3.4) +> Consistent with [siyuan/plugin-sample](https://github.com/siyuan-note/plugin-sample) [v0.3.5](https://github.com/siyuan-note/plugin-sample/tree/v0.3.5) diff --git a/README_zh_CN.md b/README_zh_CN.md index 1510f9b..ca35f7c 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -4,7 +4,7 @@ [English](./README.md) -> 本例同 [siyuan/plugin-sample](https://github.com/siyuan-note/plugin-sample) [v0.3.4](https://github.com/siyuan-note/plugin-sample/tree/v0.3.4) +> 本例同 [siyuan/plugin-sample](https://github.com/siyuan-note/plugin-sample) [v0.3.5](https://github.com/siyuan-note/plugin-sample/tree/v0.3.5) 1. 使用 vite 打包 2. 使用符号链接、而不是把项目放到插件目录下的模式进行开发 diff --git a/package.json b/package.json index 4bccd57..44cdd78 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "plugin-sample-vite-svelte", - "version": "0.3.2", + "version": "0.3.5", "type": "module", "description": "This is a sample plugin based on vite and svelte for Siyuan (https://b3log.org/siyuan)", "repository": "", "homepage": "", - "author": "", + "author": "frostime", "license": "MIT", "scripts": { "make-link": "node --no-warnings ./scripts/make_dev_link.js", @@ -23,7 +23,7 @@ "minimist": "^1.2.8", "rollup-plugin-livereload": "^2.0.5", "sass": "^1.63.3", - "siyuan": "0.9.7", + "siyuan": "0.9.8", "svelte": "^4.2.0", "ts-node": "^10.9.1", "typescript": "^5.1.3", diff --git a/plugin.json b/plugin.json index b810268..071b2a3 100644 --- a/plugin.json +++ b/plugin.json @@ -2,8 +2,8 @@ "name": "plugin-sample-vite-svelte", "author": "frostime", "url": "https://github.com/siyuan-note/plugin-sample-vite-svelte", - "version": "0.3.4", - "minAppVersion": "3.0.0", + "version": "0.3.5", + "minAppVersion": "3.0.12", "backends": [ "windows", "linux", diff --git a/src/index.ts b/src/index.ts index 704ad00..4af2041 100644 --- a/src/index.ts +++ b/src/index.ts @@ -235,6 +235,7 @@ export default class PluginSample extends Plugin { type: "slider", title: "Slider text", description: "Slider description", + direction: "column", slider: { min: 0, max: 100, diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index 2a3926b..e611ce8 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -3,7 +3,7 @@ * @Author : frostime * @Date : 2023-12-17 18:28:19 * @FilePath : /src/libs/setting-utils.ts - * @LastEditTime : 2024-04-30 15:50:07 + * @LastEditTime : 2024-04-30 16:09:54 * @Description : */ @@ -222,6 +222,7 @@ export class SettingUtils { this.plugin.setting.addItem({ title: item.title, description: item?.description, + direction: item?.direction, createActionElement: () => { this.updateElementFromValue(item.key); let element = this.getElement(item.key); @@ -232,6 +233,7 @@ export class SettingUtils { this.plugin.setting.addItem({ title: item.title, description: item?.description, + direction: item?.direction, createActionElement: () => { let val = this.get(item.key); let element = item.createElement(val); @@ -334,6 +336,7 @@ export class SettingUtils { private updateValueFromElement(key: string) { let item = this.settings.get(key); + if (item.type === 'button') return; let element = this.elements.get(key) as any; item.value = valueOf(element); // switch (item.type) { @@ -360,6 +363,7 @@ export class SettingUtils { private updateElementFromValue(key: string) { let item = this.settings.get(key); + if (item.type === 'button') return; let element = this.elements.get(key) as any; setValue(element, item.value); // switch (item.type) { From 29c494a3f4aa977341f103f0b794b692f0b73f5e Mon Sep 17 00:00:00 2001 From: frostime Date: Tue, 30 Apr 2024 16:32:26 +0800 Subject: [PATCH 60/88] =?UTF-8?q?=E2=9C=A8=20feat(setting-utils):=20getter?= =?UTF-8?q?=20and=20setting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 12 +-- src/libs/index.d.ts | 4 +- src/libs/setting-utils.ts | 153 ++++++++++++++++++-------------------- 3 files changed, 81 insertions(+), 88 deletions(-) diff --git a/src/index.ts b/src/index.ts index 4af2041..6a59d4c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -176,7 +176,7 @@ export default class PluginSample extends Plugin { // Called when focus is lost and content changes callback: () => { // Return data and save it in real time - let value = this.settingUtils.takeAndSave("Input") + let value = this.settingUtils.takeAndSave("Input"); console.log(value); } } @@ -191,7 +191,7 @@ export default class PluginSample extends Plugin { action: { callback: () => { // Read data in real time - let value = this.settingUtils.take("InputArea") + let value = this.settingUtils.take("InputArea"); console.log(value); } } @@ -205,8 +205,8 @@ export default class PluginSample extends Plugin { action: { callback: () => { // Return data and save it in real time - let value = !this.settingUtils.get("Check") - this.settingUtils.set("Check", value) + let value = !this.settingUtils.get("Check"); + this.settingUtils.set("Check", value); console.log(value); } } @@ -224,7 +224,7 @@ export default class PluginSample extends Plugin { action: { callback: () => { // Read data in real time - let value = this.settingUtils.take("Select") + let value = this.settingUtils.take("Select"); console.log(value); } } @@ -244,7 +244,7 @@ export default class PluginSample extends Plugin { action:{ callback: () => { // Read data in real time - let value = this.settingUtils.take("Slider") + let value = this.settingUtils.take("Slider"); console.log(value); } } diff --git a/src/libs/index.d.ts b/src/libs/index.d.ts index 7ca733f..539076a 100644 --- a/src/libs/index.d.ts +++ b/src/libs/index.d.ts @@ -3,7 +3,7 @@ * @Author : frostime * @Date : 2024-04-19 18:30:12 * @FilePath : /src/libs/index.d.ts - * @LastEditTime : 2024-04-30 15:53:15 + * @LastEditTime : 2024-04-30 16:26:23 * @Description : */ type TSettingItemType = "checkbox" | "select" | "textinput" | "textarea" | "number" | "slider" | "button" | "hint"; @@ -38,4 +38,6 @@ interface ISettingUtilsItem extends ISettingItem { callback: () => void; } createElement?: (currentVal: any) => HTMLElement; + getEleVal?: (ele: HTMLElement) => any; + setEleVal?: (ele: HTMLElement, val: any) => void; } diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index e611ce8..19952c4 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -3,60 +3,83 @@ * @Author : frostime * @Date : 2023-12-17 18:28:19 * @FilePath : /src/libs/setting-utils.ts - * @LastEditTime : 2024-04-30 16:09:54 + * @LastEditTime : 2024-04-30 16:28:00 * @Description : */ import { Plugin, Setting } from 'siyuan'; -const valueOf = (ele: HTMLElement, parseNumber: Function=parseInt) => { - let val: any = null; - if (ele instanceof HTMLInputElement) { - if (ele.type === 'checkbox') { - val = ele.checked; - } else { - if (ele.type === 'number') { - val = parseNumber(ele.value); - } else { - val = ele.value; + +/** + * The default function to get the value of the element + * @param type + * @returns + */ +const createDefaultGetter = (type: TSettingItemType) => { + let getter: (ele: HTMLElement) => any; + switch (type) { + case 'checkbox': + getter = (ele: HTMLInputElement) => { + return ele.checked; } - } - } else if (ele instanceof HTMLSelectElement) { - val = ele.value; - } else if (ele instanceof HTMLTextAreaElement) { - val = ele.value; - } else { - val = ele?.textContent; + break; + case 'select': + case 'slider': + case 'textinput': + case 'textarea': + getter = (ele: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement) => { + return ele.value; + } + break; + case 'number': + getter = (ele: HTMLInputElement) => { + return parseInt(ele.value); + } + break; + default: + getter = (ele: HTMLElement) => { + return ele?.textContent; + } + break; } - return val; + return getter; } -const setValue = (ele: HTMLElement, value: any) => { - if (ele === null || ele === undefined) return; - if (ele instanceof HTMLInputElement) { - if (ele.type === 'checkbox') { - ele.checked = value; - } else { - ele.value = value; - } - if (ele.type === 'range') { - ele.ariaLabel = value; - } - } else if (ele instanceof HTMLSelectElement) { - ele.value = value; - } else if (ele instanceof HTMLTextAreaElement) { - ele.value = value; - } else { - ele.textContent = value; + +/** + * The default function to set the value of the element + * @param type + * @returns + */ +const createDefaultSetter = (type: TSettingItemType) => { + let setter: (ele: HTMLElement, value: any) => void; + switch (type) { + case 'checkbox': + setter = (ele: HTMLInputElement, value: any) => { + ele.checked = value; + } + break; + case 'select': + case 'slider': + case 'textinput': + case 'textarea': + case 'number': + setter = (ele: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement, value: any) => { + ele.value = value; + } + break; } + return setter; + } + export class SettingUtils { plugin: Plugin; name: string; file: string; - settings: Map = new Map(); + settings: Map = new Map(); elements: Map = new Map(); constructor(args: { @@ -157,14 +180,15 @@ export class SettingUtils { * @returns value in html */ take(key: string, apply: boolean = false) { + let item = this.settings.get(key); let element = this.elements.get(key) as any; - if (!element){ + if (!element) { return } if (apply) { this.updateValueFromElement(key); } - return valueOf(element) + return item.getEleVal(element); } /** @@ -216,6 +240,13 @@ export class SettingUtils { addItem(item: ISettingUtilsItem) { this.settings.set(item.key, item); + if (item.getEleVal === undefined) { + item.getEleVal = createDefaultGetter(item.type); + } + if (item.setEleVal === undefined) { + item.setEleVal = createDefaultSetter(item.type); + } + if (item.createElement === undefined) { let itemElement = this.createDefaultElement(item); this.elements.set(item.key, itemElement); @@ -338,53 +369,13 @@ export class SettingUtils { let item = this.settings.get(key); if (item.type === 'button') return; let element = this.elements.get(key) as any; - item.value = valueOf(element); - // switch (item.type) { - // case 'checkbox': - // item.value = element.checked; - // break; - // case 'select': - // item.value = element.value; - // break; - // case 'slider': - // item.value = element.value; - // break; - // case 'textinput': - // item.value = element.value; - // break; - // case 'textarea': - // item.value = element.value; - // break; - // case 'number': - // item.value = parseInt(element.value); - // break; - // } + item.value = item.getEleVal(element); } private updateElementFromValue(key: string) { let item = this.settings.get(key); if (item.type === 'button') return; let element = this.elements.get(key) as any; - setValue(element, item.value); - // switch (item.type) { - // case 'checkbox': - // element.checked = item.value; - // break; - // case 'select': - // element.value = item.value; - // break; - // case 'slider': - // element.value = item.value; - // break; - // case 'textinput': - // element.value = item.value; - // break; - // case 'textarea': - // element.value = item.value; - // break; - // case 'number': - // element.value = item.value; - // break; - // } + item.setEleVal(element, item.value); } } \ No newline at end of file From 3d565424aec01410a512c066f1d0ce3d94944439 Mon Sep 17 00:00:00 2001 From: frostime Date: Tue, 30 Apr 2024 16:48:10 +0800 Subject: [PATCH 61/88] =?UTF-8?q?=F0=9F=8E=A8=20feat:=20Add=20"custom=20se?= =?UTF-8?q?tting-items"=20example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.ts | 26 ++++++++++++++++++++++++-- src/libs/index.d.ts | 4 ++-- src/libs/setting-utils.ts | 24 ++++++++++++++++-------- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/index.ts b/src/index.ts index 6a59d4c..62a09a7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -31,7 +31,7 @@ const DOCK_TYPE = "dock_tab"; export default class PluginSample extends Plugin { - private customTab: () => IModel; + customTab: () => IModel; private isMobile: boolean; private blockIconEventBindThis = this.blockIconEvent.bind(this); private settingUtils: SettingUtils; @@ -262,6 +262,28 @@ export default class PluginSample extends Plugin { } } }); + this.settingUtils.addItem({ + key: "Custom Element", + value: "", + type: "custom", + direction: "row", + title: "Custom Element", + description: "Custom Element description", + //Any custom element must offer the following methods + createElement: (currentVal: any) => { + let div = document.createElement('div'); + div.style.border = "1px solid var(--b3-theme-primary)"; + div.contentEditable = "true"; + div.textContent = currentVal; + return div; + }, + getEleVal: (ele: HTMLElement) => { + return ele.textContent; + }, + setEleVal: (ele: HTMLElement, val: any) => { + ele.textContent = val; + } + }); this.settingUtils.addItem({ key: "Hint", value: "", @@ -437,7 +459,7 @@ export default class PluginSample extends Plugin { title: `SiYuan ${Constants.SIYUAN_VERSION}`, content: `
`, width: this.isMobile ? "92vw" : "720px", - destroyCallback(options) { + destroyCallback() { // hello.$destroy(); }, }); diff --git a/src/libs/index.d.ts b/src/libs/index.d.ts index 539076a..ab2f6c3 100644 --- a/src/libs/index.d.ts +++ b/src/libs/index.d.ts @@ -3,10 +3,10 @@ * @Author : frostime * @Date : 2024-04-19 18:30:12 * @FilePath : /src/libs/index.d.ts - * @LastEditTime : 2024-04-30 16:26:23 + * @LastEditTime : 2024-04-30 16:39:54 * @Description : */ -type TSettingItemType = "checkbox" | "select" | "textinput" | "textarea" | "number" | "slider" | "button" | "hint"; +type TSettingItemType = "checkbox" | "select" | "textinput" | "textarea" | "number" | "slider" | "button" | "hint" | "custom"; interface ISettingItemCore { type: TSettingItemType; diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index 19952c4..948dc2f 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -3,7 +3,7 @@ * @Author : frostime * @Date : 2023-12-17 18:28:19 * @FilePath : /src/libs/setting-utils.ts - * @LastEditTime : 2024-04-30 16:28:00 + * @LastEditTime : 2024-04-30 16:42:23 * @Description : */ @@ -21,7 +21,7 @@ const createDefaultGetter = (type: TSettingItemType) => { case 'checkbox': getter = (ele: HTMLInputElement) => { return ele.checked; - } + }; break; case 'select': case 'slider': @@ -29,7 +29,7 @@ const createDefaultGetter = (type: TSettingItemType) => { case 'textarea': getter = (ele: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement) => { return ele.value; - } + }; break; case 'number': getter = (ele: HTMLInputElement) => { @@ -37,9 +37,7 @@ const createDefaultGetter = (type: TSettingItemType) => { } break; default: - getter = (ele: HTMLElement) => { - return ele?.textContent; - } + getter = () => null; break; } return getter; @@ -57,7 +55,7 @@ const createDefaultSetter = (type: TSettingItemType) => { case 'checkbox': setter = (ele: HTMLInputElement, value: any) => { ele.checked = value; - } + }; break; case 'select': case 'slider': @@ -66,7 +64,10 @@ const createDefaultSetter = (type: TSettingItemType) => { case 'number': setter = (ele: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement, value: any) => { ele.value = value; - } + }; + break; + default: + setter = () => {}; break; } return setter; @@ -240,6 +241,13 @@ export class SettingUtils { addItem(item: ISettingUtilsItem) { this.settings.set(item.key, item); + const IsCustom = item.type === 'custom'; + let error = IsCustom && (item.createElement === undefined || item.getEleVal === undefined || item.setEleVal === undefined); + if (error) { + console.error('The custom setting item must have createElement, getEleVal and setEleVal methods'); + return; + } + if (item.getEleVal === undefined) { item.getEleVal = createDefaultGetter(item.type); } From 9f54e7046cf6070ac2ae5547240ea8d45e0425ae Mon Sep 17 00:00:00 2001 From: frostime Date: Tue, 30 Apr 2024 22:15:50 +0800 Subject: [PATCH 62/88] =?UTF-8?q?=E2=9C=A8=20misc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/setting-utils.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index 948dc2f..33c5cac 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -3,7 +3,7 @@ * @Author : frostime * @Date : 2023-12-17 18:28:19 * @FilePath : /src/libs/setting-utils.ts - * @LastEditTime : 2024-04-30 16:42:23 + * @LastEditTime : 2024-04-30 22:15:25 * @Description : */ @@ -105,7 +105,7 @@ export class SettingUtils { args.callback(data); } this.plugin.data[this.name] = data; - this.save(); + this.save(data); }, destroyCallback: () => { //Restore the original value @@ -128,8 +128,8 @@ export class SettingUtils { return data; } - async save() { - let data = this.dump(); + async save(data?: any) { + data = data ?? this.dump(); await this.plugin.saveData(this.file, this.dump()); console.debug('Save config:', data); return data; From 03ab34f5523274b3c416801359d8df32f8617141 Mon Sep 17 00:00:00 2001 From: frostime Date: Wed, 1 May 2024 17:45:05 +0800 Subject: [PATCH 63/88] =?UTF-8?q?=E2=9A=A1=20=E7=A6=81=E7=94=A8=E6=80=9D?= =?UTF-8?q?=E6=BA=90=E5=86=85=E9=83=A8=E7=9A=84=20enter=20confirm=20?= =?UTF-8?q?=E7=89=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/setting-utils.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts index 33c5cac..ae316e2 100644 --- a/src/libs/setting-utils.ts +++ b/src/libs/setting-utils.ts @@ -3,7 +3,7 @@ * @Author : frostime * @Date : 2023-12-17 18:28:19 * @FilePath : /src/libs/setting-utils.ts - * @LastEditTime : 2024-04-30 22:15:25 + * @LastEditTime : 2024-05-01 17:44:16 * @Description : */ @@ -285,6 +285,13 @@ export class SettingUtils { createDefaultElement(item: ISettingUtilsItem) { let itemElement: HTMLElement; + //阻止思源内置的回车键确认 + const preventEnterConfirm = (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + e.stopImmediatePropagation(); + } + } switch (item.type) { case 'checkbox': let element: HTMLInputElement = document.createElement('input'); @@ -330,7 +337,7 @@ export class SettingUtils { textInputElement.value = item.value; textInputElement.onchange = item.action?.callback ?? (() => { }); itemElement = textInputElement; - + textInputElement.addEventListener('keydown', preventEnterConfirm); break; case 'textarea': let textareaElement: HTMLTextAreaElement = document.createElement('textarea'); @@ -345,6 +352,7 @@ export class SettingUtils { numberElement.className = 'b3-text-field fn__flex-center fn__size200'; numberElement.value = item.value; itemElement = numberElement; + numberElement.addEventListener('keydown', preventEnterConfirm); break; case 'button': let buttonElement: HTMLButtonElement = document.createElement('button'); From 67d6024a04dce60765347c35c6d2422c33971321 Mon Sep 17 00:00:00 2001 From: frostime Date: Sat, 1 Jun 2024 16:29:07 +0800 Subject: [PATCH 64/88] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20kits=20about=20?= =?UTF-8?q?dialogs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/dialog.ts | 121 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/libs/dialog.ts diff --git a/src/libs/dialog.ts b/src/libs/dialog.ts new file mode 100644 index 0000000..ea2b187 --- /dev/null +++ b/src/libs/dialog.ts @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2024 by frostime. All Rights Reserved. + * @Author : frostime + * @Date : 2024-03-23 21:37:33 + * @FilePath : /src/libs/dialog.ts + * @LastEditTime : 2024-06-01 16:28:30 + * @Description : Kits about dialogs + */ +import { Dialog } from "siyuan"; + +export const inputDialog = (args: { + title: string, placeholder?: string, defaultText?: string, + confirm?: (text: string) => void, cancel?: () => void, + width?: string, height?: string +}) => { + const dialog = new Dialog({ + title: args.title, + content: `
+
+
+
+
+ +
`, + width: args.width ?? "520px", + height: args.height + }); + const target: HTMLTextAreaElement = dialog.element.querySelector(".b3-dialog__content>div.ft__breakword>textarea"); + const btnsElement = dialog.element.querySelectorAll(".b3-button"); + btnsElement[0].addEventListener("click", () => { + if (args?.cancel) { + args.cancel(); + } + dialog.destroy(); + }); + btnsElement[1].addEventListener("click", () => { + if (args?.confirm) { + args.confirm(target.value); + } + dialog.destroy(); + }); +}; + +export const inputDialogSync = async (args: { + title: string, placeholder?: string, defaultText?: string, + width?: string, height?: string +}) => { + return new Promise((resolve) => { + let newargs = { + ...args, confirm: (text) => { + resolve(text); + }, cancel: () => { + resolve(null); + } + }; + inputDialog(newargs); + }); +} + + +interface IConfirmDialogArgs { + title: string; + content: string | HTMLElement; + confirm?: (ele?: HTMLElement) => void; + cancel?: (ele?: HTMLElement) => void; + width?: string; + height?: string; +} + +export const confirmDialog = (args: IConfirmDialogArgs) => { + const { title, content, confirm, cancel, width, height } = args; + + const dialog = new Dialog({ + title, + content: `
+
+
+
+
+
+ +
`, + width: width, + height: height + }); + + const target: HTMLElement = dialog.element.querySelector(".b3-dialog__content>div.ft__breakword"); + if (typeof content === "string") { + target.innerHTML = content; + } else { + target.appendChild(content); + } + + const btnsElement = dialog.element.querySelectorAll(".b3-button"); + btnsElement[0].addEventListener("click", () => { + if (cancel) { + cancel(target); + } + dialog.destroy(); + }); + btnsElement[1].addEventListener("click", () => { + if (confirm) { + confirm(target); + } + dialog.destroy(); + }); +}; + + +export const confirmDialogSync = async (args: IConfirmDialogArgs) => { + return new Promise((resolve) => { + let newargs = { + ...args, confirm: (ele: HTMLElement) => { + resolve(ele); + }, cancel: (ele: HTMLElement) => { + resolve(ele); + } + }; + confirmDialog(newargs); + }); +}; From 81d5bee160e9b8b505a09b523c27fea2f89d18a3 Mon Sep 17 00:00:00 2001 From: frostime Date: Sat, 1 Jun 2024 16:35:02 +0800 Subject: [PATCH 65/88] =?UTF-8?q?=F0=9F=93=9Ddocs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 5 ++++- README.md | 2 +- README_zh_CN.md | 2 +- package.json | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce36ec8..af04807 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog -## 0.3.5 2024-03 +## v0.3.5 2024-04-30 + +* [Add `direction` to plugin method `Setting.addItem`](https://github.com/siyuan-note/siyuan/issues/11183) + ## 0.3.4 2024-02-20 diff --git a/README.md b/README.md index 09c8cdd..5f3c813 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ 2. Use symbolic linking instead of putting the project into the plugins directory program development 3. Built-in support for the svelte framework - > If don't want svelte, turn to this template: [frostime/plugin-sample-vite](https://github.com/frostime/plugin-sample-vite) + > **If don't want svelte, turn to this template**: [frostime/plugin-sample-vite](https://github.com/frostime/plugin-sample-vite) 4. Provides a github action template to automatically generate package.zip and upload to new release diff --git a/README_zh_CN.md b/README_zh_CN.md index ca35f7c..9f447fa 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -10,7 +10,7 @@ 2. 使用符号链接、而不是把项目放到插件目录下的模式进行开发 3. 内置对 svelte 框架的支持 - > 如果不想要 svelte,请移步 [frostime/plugin-sample-vite](https://github.com/frostime/plugin-sample-vite) + > **如果不想要 svelte,请移步这个模板:** [frostime/plugin-sample-vite](https://github.com/frostime/plugin-sample-vite) 4. 提供一个github action 模板,能自动生成package.zip并上传到新版本中 diff --git a/package.json b/package.json index 44cdd78..fd49b9c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "minimist": "^1.2.8", "rollup-plugin-livereload": "^2.0.5", "sass": "^1.63.3", - "siyuan": "0.9.8", + "siyuan": "0.9.9", "svelte": "^4.2.0", "ts-node": "^10.9.1", "typescript": "^5.1.3", From 9c7572b820189d61320b84f25132a1d44782f71b Mon Sep 17 00:00:00 2001 From: frostime Date: Tue, 4 Jun 2024 15:04:07 +0800 Subject: [PATCH 66/88] =?UTF-8?q?=F0=9F=90=9B=20getFile=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/api.ts b/src/api.ts index c227518..0a421ce 100644 --- a/src/api.ts +++ b/src/api.ts @@ -6,7 +6,7 @@ * API 文档见 [API_zh_CN.md](https://github.com/siyuan-note/siyuan/blob/master/API_zh_CN.md) */ -import { fetchSyncPost, IWebSocketData } from "siyuan"; +import { fetchPost, fetchSyncPost, IWebSocketData } from "siyuan"; export async function request(url: string, data: any) { @@ -328,12 +328,11 @@ export async function getFile(path: string): Promise { path: path } let url = '/api/file/getFile'; - try { - let file = await fetchSyncPost(url, data); - return file; - } catch (error_msg) { - return null; - } + return new Promise((resolve, _) => { + fetchPost(url, data, (content: any) => { + resolve(content) + }); + }); } export async function putFile(path: string, isDir: boolean, file: any) { From 49eb06330da596e276afd399f993a340957f691f Mon Sep 17 00:00:00 2001 From: Frostime Date: Thu, 6 Jun 2024 22:31:20 +0800 Subject: [PATCH 67/88] =?UTF-8?q?=F0=9F=94=A8=20Remove=20the=20default=20f?= =?UTF-8?q?und=20in=20plugin.json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin.json b/plugin.json index 071b2a3..865a240 100644 --- a/plugin.json +++ b/plugin.json @@ -32,7 +32,7 @@ }, "funding": { "custom": [ - "https://afdian.net/a/frostime" + "" ] }, "keywords": [ From 6d75a46a56c0aad62a74b0ee7943fc4e1601fc56 Mon Sep 17 00:00:00 2001 From: frostime Date: Sat, 8 Jun 2024 18:30:53 +0800 Subject: [PATCH 68/88] =?UTF-8?q?=F0=9F=94=A8=20refactor:=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E5=9F=BA=E4=BA=8E=20svelte=20=E7=9A=84=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E9=9D=A2=E6=9D=BF=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/index.d.ts | 2 +- src/libs/item-input.svelte | 108 ++++++++++++++++++++++++++++++++++ src/libs/item-wrap.svelte | 51 ++++++++++++++++ src/libs/setting-item.svelte | 105 --------------------------------- src/libs/setting-panel.svelte | 31 ++++++---- src/setting-example.svelte | 9 +++ 6 files changed, 187 insertions(+), 119 deletions(-) create mode 100644 src/libs/item-input.svelte create mode 100644 src/libs/item-wrap.svelte delete mode 100644 src/libs/setting-item.svelte diff --git a/src/libs/index.d.ts b/src/libs/index.d.ts index ab2f6c3..27a27ed 100644 --- a/src/libs/index.d.ts +++ b/src/libs/index.d.ts @@ -28,12 +28,12 @@ interface ISettingItemCore { interface ISettingItem extends ISettingItemCore { title: string; description: string; + direction?: "row" | "column"; } //Interface for setting-utils interface ISettingUtilsItem extends ISettingItem { - direction?: "row" | "column"; action?: { callback: () => void; } diff --git a/src/libs/item-input.svelte b/src/libs/item-input.svelte new file mode 100644 index 0000000..3a42b45 --- /dev/null +++ b/src/libs/item-input.svelte @@ -0,0 +1,108 @@ + + + +{#if type === "checkbox"} + + +{:else if type === "textinput"} + + +{:else if type === "textarea"} +