-
appId:
-
-
${app?.appId}
-
-
API demo:
diff --git a/public/i18n/en_US.json b/src/i18n/en_US.json
similarity index 80%
rename from public/i18n/en_US.json
rename to src/i18n/en_US.json
index 7a11256..c7ed102 100644
--- a/public/i18n/en_US.json
+++ b/src/i18n/en_US.json
@@ -14,7 +14,5 @@
"name": "SiYuan",
"hello": {
"makesure": "Before using this template, please read the
offical sample, make sure that you've known about the pipeline for plugin developing."
- },
- "hintTitle":"About",
- "hintDesc":"
plugin-sample-vite-svelte@frostime
@88250
@zxkmm"
+ }
}
\ No newline at end of file
diff --git a/public/i18n/zh_CN.json b/src/i18n/zh_CN.json
similarity index 78%
rename from public/i18n/zh_CN.json
rename to src/i18n/zh_CN.json
index 6600f6a..49a7af8 100644
--- a/public/i18n/zh_CN.json
+++ b/src/i18n/zh_CN.json
@@ -14,7 +14,5 @@
"name": "思源",
"hello": {
"makesure": "使用这个模板之前,请阅读
官方教程, 确保自己已经理解了插件的基本开发流程。"
- },
- "hintTitle": "关于",
- "hintDesc": "
🔗 plugin-sample-vite-svelte💻 @frostime
💻 @88250
💻 @zxkmm"
+ }
}
\ No newline at end of file
diff --git a/src/index.scss b/src/index.scss
index e69de29..c8efd4f 100644
--- a/src/index.scss
+++ b/src/index.scss
@@ -0,0 +1,26 @@
+#helloPanel {
+ border: 1px rgb(189, 119, 119) dashed;
+}
+
+.plugin-sample {
+ &__custom-tab {
+ background-color: var(--b3-theme-background);
+ height: 100%;
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+
+ &__custom-dock {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+
+ &__time {
+ background: var(--b3-card-info-background);
+ border-radius: 4px;
+ padding: 2px 8px;
+ }
+}
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index 5b50c49..aa7bd75 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -9,22 +9,16 @@ import {
getFrontend,
getBackend,
IModel,
- Protyle,
- openWindow,
- IOperation,
- Constants,
- openMobileFileById,
- lockScreen,
- ICard,
- ICardData
+ Setting,
+ fetchPost,
+ Protyle, openWindow, IOperation
} from "siyuan";
import "@/index.scss";
import HelloExample from "@/hello.svelte";
-import SettingExample from "@/setting-example.svelte";
+import SettingPannel from "@/libs/setting-panel.svelte";
import { SettingUtils } from "./libs/setting-utils";
-import { svelteDialog } from "./libs/dialog";
const STORAGE_NAME = "menu-config";
const TAB_TYPE = "custom_tab";
@@ -32,7 +26,7 @@ const DOCK_TYPE = "dock_tab";
export default class PluginSample extends Plugin {
- customTab: () => IModel;
+ private customTab: () => IModel;
private isMobile: boolean;
private blockIconEventBindThis = this.blockIconEvent.bind(this);
private settingUtils: SettingUtils;
@@ -121,66 +115,38 @@ export default class PluginSample extends Plugin {
size: { width: 200, height: 0 },
icon: "iconSaving",
title: "Custom Dock",
- hotkey: "⌥⌘W",
},
data: {
text: "This is my custom dock"
},
type: DOCK_TYPE,
- resize() {
- console.log(DOCK_TYPE + " resize");
- },
- update() {
- console.log(DOCK_TYPE + " update");
- },
- init: (dock) => {
- if (this.isMobile) {
- dock.element.innerHTML = `
-
- ${dock.data.text}
-
-
`;
- } else {
- dock.element.innerHTML = `
-
-
-
- Custom Dock
-
-
-
-
-
- ${dock.data.text}
-
-
`;
- }
+ init() {
+ this.element.innerHTML = `
+
+
+
+ Custom Dock
+
+
+
+
+
+ ${this.data.text}
+
+
`;
},
destroy() {
console.log("destroy dock:", DOCK_TYPE);
}
});
- this.settingUtils = new SettingUtils({
- plugin: this, name: STORAGE_NAME
- });
+ this.settingUtils = new SettingUtils(this, STORAGE_NAME);
this.settingUtils.addItem({
key: "Input",
value: "",
type: "textinput",
title: "Readonly text",
description: "Input description",
- action: {
- // Called when focus is lost and content changes
- callback: () => {
- // Return data and save it in real time
- let value = this.settingUtils.takeAndSave("Input");
- console.log(value);
- }
- }
});
this.settingUtils.addItem({
key: "InputArea",
@@ -188,14 +154,6 @@ export default class PluginSample extends Plugin {
type: "textarea",
title: "Readonly text",
description: "Input description",
- // Called when focus is lost and content changes
- action: {
- callback: () => {
- // Read data in real time
- let value = this.settingUtils.take("InputArea");
- console.log(value);
- }
- }
});
this.settingUtils.addItem({
key: "Check",
@@ -203,31 +161,24 @@ export default class PluginSample extends Plugin {
type: "checkbox",
title: "Checkbox text",
description: "Check description",
- action: {
- callback: () => {
- // Return data and save it in real time
- let value = !this.settingUtils.get("Check");
- this.settingUtils.set("Check", value);
- console.log(value);
- }
- }
});
this.settingUtils.addItem({
key: "Select",
value: 1,
type: "select",
- title: "Select",
+ title: "Readonly text",
description: "Select description",
- options: {
- 1: "Option 1",
- 2: "Option 2"
- },
- action: {
- callback: () => {
- // Read data in real time
- let value = this.settingUtils.take("Select");
- console.log(value);
- }
+ select: {
+ options: [
+ {
+ val: 1,
+ text: "Option 1"
+ },
+ {
+ val: 2,
+ text: "Option 2"
+ }
+ ]
}
});
this.settingUtils.addItem({
@@ -236,18 +187,10 @@ export default class PluginSample extends Plugin {
type: "slider",
title: "Slider text",
description: "Slider description",
- direction: "column",
slider: {
min: 0,
max: 100,
step: 1,
- },
- action:{
- callback: () => {
- // Read data in real time
- let value = this.settingUtils.take("Slider");
- console.log(value);
- }
}
});
this.settingUtils.addItem({
@@ -263,42 +206,6 @@ 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: "",
- type: "hint",
- title: this.i18n.hintTitle,
- 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"],
@@ -309,38 +216,6 @@ export default class PluginSample extends Plugin {
}
}];
- this.protyleOptions = {
- toolbar: ["block-ref",
- "a",
- "|",
- "text",
- "strong",
- "em",
- "u",
- "s",
- "mark",
- "sup",
- "sub",
- "clear",
- "|",
- "code",
- "kbd",
- "tag",
- "inline-math",
- "inline-memo",
- "|",
- {
- name: "insert-smail-emoji",
- icon: "iconEmoji",
- hotkey: "⇧⌘I",
- tipPosition: "n",
- tip: this.i18n.insertEmoji,
- click(protyle: Protyle) {
- protyle.insert("😊");
- }
- }],
- };
-
console.log(this.i18n.helloPlugin);
}
@@ -348,14 +223,6 @@ export default class PluginSample extends Plugin {
// this.loadData(STORAGE_NAME);
this.settingUtils.load();
console.log(`frontend: ${getFrontend()}; backend: ${getBackend()}`);
-
- console.log(
- "Official settings value calling example:\n" +
- this.settingUtils.get("InputArea") + "\n" +
- this.settingUtils.get("Slider") + "\n" +
- this.settingUtils.get("Select") + "\n"
- );
-
let tabDiv = document.createElement("div");
new HelloExample({
target: tabDiv,
@@ -380,42 +247,26 @@ export default class PluginSample extends Plugin {
async onunload() {
console.log(this.i18n.byePlugin);
+ await this.settingUtils.save();
showMessage("Goodbye SiYuan Plugin");
console.log("onunload");
}
- uninstall() {
- console.log("uninstall");
- }
-
- async updateCards(options: ICardData) {
- options.cards.sort((a: ICard, b: ICard) => {
- if (a.blockID < b.blockID) {
- return -1;
- }
- if (a.blockID > b.blockID) {
- return 1;
- }
- return 0;
- });
- return options;
- }
-
/**
* A custom setting pannel provided by svelte
*/
openDIYSetting(): void {
let dialog = new Dialog({
title: "SettingPannel",
- content: `
`,
- width: "800px",
+ content: `
`,
+ width: "600px",
destroyCallback: (options) => {
console.log("destroyCallback", options);
//You'd better destroy the component when the dialog is closed
pannel.$destroy();
}
});
- let pannel = new SettingExample({
+ let pannel = new SettingPannel({
target: dialog.element.querySelector("#SettingPanel"),
});
}
@@ -456,30 +307,18 @@ export default class PluginSample extends Plugin {
}
private showDialog() {
- // let dialog = new Dialog({
- // title: `SiYuan ${Constants.SIYUAN_VERSION}`,
- // content: `
`,
- // width: this.isMobile ? "92vw" : "720px",
- // destroyCallback() {
- // // hello.$destroy();
- // },
- // });
- // new HelloExample({
- // target: dialog.element.querySelector("#helloPanel"),
- // props: {
- // app: this.app,
- // }
- // });
- svelteDialog({
- title: `SiYuan ${Constants.SIYUAN_VERSION}`,
+ let dialog = new Dialog({
+ title: "Hello World",
+ content: `
`,
width: this.isMobile ? "92vw" : "720px",
- constructor: (container: HTMLElement) => {
- return new HelloExample({
- target: container,
- props: {
- app: this.app,
- }
- });
+ destroyCallback(options) {
+ // hello.$destroy();
+ },
+ });
+ new HelloExample({
+ target: dialog.element.querySelector("#helloPanel"),
+ props: {
+ app: this.app,
}
});
}
@@ -588,22 +427,7 @@ export default class PluginSample extends Plugin {
});
}
});
- } else {
- menu.addItem({
- icon: "iconFile",
- label: "Open Doc(open help first)",
- click: () => {
- openMobileFileById(this.app, "20200812220555-lj3enxa");
- }
- });
}
- menu.addItem({
- icon: "iconLock",
- label: "Lockscreen",
- click: () => {
- lockScreen(this.app);
- }
- });
menu.addItem({
icon: "iconScrollHoriz",
label: "Event Bus",
@@ -668,18 +492,6 @@ export default class PluginSample extends Plugin {
click: () => {
this.eventBus.off("click-editortitleicon", this.eventBusLog);
}
- }, {
- icon: "iconSelect",
- label: "On click-flashcard-action",
- click: () => {
- this.eventBus.on("click-flashcard-action", this.eventBusLog);
- }
- }, {
- icon: "iconClose",
- label: "Off click-flashcard-action",
- click: () => {
- this.eventBus.off("click-flashcard-action", this.eventBusLog);
- }
}, {
icon: "iconSelect",
label: "On open-noneditableblock",
@@ -716,18 +528,6 @@ 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",
@@ -848,18 +648,6 @@ export default class PluginSample extends Plugin {
click: () => {
this.eventBus.off("open-menu-breadcrumbmore", this.eventBusLog);
}
- }, {
- icon: "iconSelect",
- label: "On open-menu-inbox",
- click: () => {
- this.eventBus.on("open-menu-inbox", this.eventBusLog);
- }
- }, {
- icon: "iconClose",
- label: "Off open-menu-inbox",
- click: () => {
- this.eventBus.off("open-menu-inbox", this.eventBusLog);
- }
}, {
icon: "iconSelect",
label: "On input-search",
diff --git a/src/libs/components/b3-typography.svelte b/src/libs/b3-typography.svelte
similarity index 100%
rename from src/libs/components/b3-typography.svelte
rename to src/libs/b3-typography.svelte
diff --git a/src/libs/components/Form/form-input.svelte b/src/libs/components/Form/form-input.svelte
deleted file mode 100644
index cbf5a7e..0000000
--- a/src/libs/components/Form/form-input.svelte
+++ /dev/null
@@ -1,118 +0,0 @@
-
-
-{#if type === "checkbox"}
-
-
-{:else if type === "textinput"}
-
-
-{:else if type === "textarea"}
-
-{:else if type === "number"}
-
-{:else if type === "button"}
-
-
-{:else if type === "select"}
-
-
-{:else if type == "slider"}
-
-
-
-
-{/if}
diff --git a/src/libs/components/Form/form-wrap.svelte b/src/libs/components/Form/form-wrap.svelte
deleted file mode 100644
index 4d8092e..0000000
--- a/src/libs/components/Form/form-wrap.svelte
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-{#if direction === "row"}
-
-
-
{title}
-
{@html description}
-
-
-
-
-
-
-{:else}
-
-
-
{title}
-
- {@html description}
-
-
-
-
-
-{/if}
-
-
diff --git a/src/libs/components/Form/index.ts b/src/libs/components/Form/index.ts
deleted file mode 100644
index a5c81c0..0000000
--- a/src/libs/components/Form/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import FormInput from './form-input.svelte';
-import FormWrap from './form-wrap.svelte';
-
-const Form = { Wrap: FormWrap, Input: FormInput };
-export default Form;
-export { FormInput, FormWrap };
diff --git a/src/libs/components/setting-panel.svelte b/src/libs/components/setting-panel.svelte
deleted file mode 100644
index 783e2b6..0000000
--- a/src/libs/components/setting-panel.svelte
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
- {#each settingItems as item (item.key)}
-
-
-
- {/each}
-
\ No newline at end of file
diff --git a/src/libs/const.ts b/src/libs/const.ts
deleted file mode 100644
index 2dd3e06..0000000
--- a/src/libs/const.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2024 by frostime. All Rights Reserved.
- * @Author : frostime
- * @Date : 2024-06-08 20:36:30
- * @FilePath : /src/libs/const.ts
- * @LastEditTime : 2024-06-08 20:48:06
- * @Description :
- */
-
-
-export const BlockType2NodeType: {[key in BlockType]: string} = {
- d: 'NodeDocument',
- p: 'NodeParagraph',
- query_embed: 'NodeBlockQueryEmbed',
- l: 'NodeList',
- i: 'NodeListItem',
- h: 'NodeHeading',
- iframe: 'NodeIFrame',
- tb: 'NodeThematicBreak',
- b: 'NodeBlockquote',
- s: 'NodeSuperBlock',
- c: 'NodeCodeBlock',
- widget: 'NodeWidget',
- t: 'NodeTable',
- html: 'NodeHTMLBlock',
- m: 'NodeMathBlock',
- av: 'NodeAttributeView',
- audio: 'NodeAudio'
-}
-
-
-export const NodeIcons = {
- NodeAttributeView: {
- icon: "iconDatabase"
- },
- NodeAudio: {
- icon: "iconRecord"
- },
- NodeBlockQueryEmbed: {
- icon: "iconSQL"
- },
- NodeBlockquote: {
- icon: "iconQuote"
- },
- NodeCodeBlock: {
- icon: "iconCode"
- },
- NodeDocument: {
- icon: "iconFile"
- },
- NodeHTMLBlock: {
- icon: "iconHTML5"
- },
- NodeHeading: {
- icon: "iconHeadings",
- subtypes: {
- h1: { icon: "iconH1" },
- h2: { icon: "iconH2" },
- h3: { icon: "iconH3" },
- h4: { icon: "iconH4" },
- h5: { icon: "iconH5" },
- h6: { icon: "iconH6" }
- }
- },
- NodeIFrame: {
- icon: "iconLanguage"
- },
- NodeList: {
- subtypes: {
- o: { icon: "iconOrderedList" },
- t: { icon: "iconCheck" },
- u: { icon: "iconList" }
- }
- },
- NodeListItem: {
- icon: "iconListItem"
- },
- NodeMathBlock: {
- icon: "iconMath"
- },
- NodeParagraph: {
- icon: "iconParagraph"
- },
- NodeSuperBlock: {
- icon: "iconSuper"
- },
- NodeTable: {
- icon: "iconTable"
- },
- NodeThematicBreak: {
- icon: "iconLine"
- },
- NodeVideo: {
- icon: "iconVideo"
- },
- NodeWidget: {
- icon: "iconBoth"
- }
-};
diff --git a/src/libs/dialog.ts b/src/libs/dialog.ts
deleted file mode 100644
index d0fe582..0000000
--- a/src/libs/dialog.ts
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2024 by frostime. All Rights Reserved.
- * @Author : frostime
- * @Date : 2024-03-23 21:37:33
- * @FilePath : /src/libs/dialog.ts
- * @LastEditTime : 2024-10-16 14:31:04
- * @Description : Kits about dialogs
- */
-import { Dialog } from "siyuan";
-import { type SvelteComponent } from "svelte";
-
-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);
- });
-};
-
-
-export const simpleDialog = (args: {
- title: string, ele: HTMLElement | DocumentFragment,
- width?: string, height?: string,
- callback?: () => void;
-}) => {
- const dialog = new Dialog({
- title: args.title,
- content: ``,
- width: args.width,
- height: args.height,
- destroyCallback: args.callback
- });
- dialog.element.querySelector(".dialog-content").appendChild(args.ele);
- return {
- dialog,
- close: dialog.destroy.bind(dialog)
- };
-}
-
-
-export const svelteDialog = (args: {
- title: string, constructor: (container: HTMLElement) => SvelteComponent,
- width?: string, height?: string,
- callback?: () => void;
-}) => {
- let container = document.createElement('div')
- container.style.display = 'contents';
- let component = args.constructor(container);
- const { dialog, close } = simpleDialog({
- ...args, ele: container, callback: () => {
- component.$destroy();
- if (args.callback) args.callback();
- }
- });
- return {
- component,
- dialog,
- close
- }
-}
diff --git a/src/libs/index.d.ts b/src/libs/index.d.ts
index 27a27ed..b46f655 100644
--- a/src/libs/index.d.ts
+++ b/src/libs/index.d.ts
@@ -1,43 +1,20 @@
-/*
- * 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 16:39:54
- * @Description :
- */
-type TSettingItemType = "checkbox" | "select" | "textinput" | "textarea" | "number" | "slider" | "button" | "hint" | "custom";
-
-interface ISettingItemCore {
- type: TSettingItemType;
+type TSettingItemType = "checkbox" | "select" | "textinput" | "textarea" | "slider" | "button";
+interface ISettingItem {
key: string;
value: any;
- placeholder?: string;
+ type: TSettingItemType;
+ title: string;
+ description?: string;
slider?: {
min: number;
max: number;
step: number;
};
- options?: { [key: string | number]: string };
+ select?: {
+ options: {val: any; text: string}[];
+ };
button?: {
label: string;
callback: () => void;
}
}
-
-interface ISettingItem extends ISettingItemCore {
- title: string;
- description: string;
- direction?: "row" | "column";
-}
-
-
-//Interface for setting-utils
-interface ISettingUtilsItem extends ISettingItem {
- action?: {
- callback: () => void;
- }
- createElement?: (currentVal: any) => HTMLElement;
- getEleVal?: (ele: HTMLElement) => any;
- setEleVal?: (ele: HTMLElement, val: any) => void;
-}
diff --git a/src/libs/promise-pool.ts b/src/libs/promise-pool.ts
deleted file mode 100644
index e20b0b8..0000000
--- a/src/libs/promise-pool.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-export default class PromiseLimitPool {
- private maxConcurrent: number;
- private currentRunning = 0;
- private queue: (() => void)[] = [];
- private promises: Promise[] = [];
-
- constructor(maxConcurrent: number) {
- this.maxConcurrent = maxConcurrent;
- }
-
- add(fn: () => Promise): void {
- const promise = new Promise((resolve, reject) => {
- const run = async () => {
- try {
- this.currentRunning++;
- const result = await fn();
- resolve(result);
- } catch (error) {
- reject(error);
- } finally {
- this.currentRunning--;
- this.next();
- }
- };
-
- if (this.currentRunning < this.maxConcurrent) {
- run();
- } else {
- this.queue.push(run);
- }
- });
- this.promises.push(promise);
- }
-
- async awaitAll(): Promise {
- return Promise.all(this.promises);
- }
-
- /**
- * Handles the next task in the queue.
- */
- private next(): void {
- if (this.queue.length > 0 && this.currentRunning < this.maxConcurrent) {
- const nextRun = this.queue.shift()!;
- nextRun();
- }
- }
-}
diff --git a/src/libs/setting-item.svelte b/src/libs/setting-item.svelte
new file mode 100644
index 0000000..b728cf4
--- /dev/null
+++ b/src/libs/setting-item.svelte
@@ -0,0 +1,92 @@
+
+
+
diff --git a/src/libs/setting-panel.svelte b/src/libs/setting-panel.svelte
new file mode 100644
index 0000000..ccf424e
--- /dev/null
+++ b/src/libs/setting-panel.svelte
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
This setting panel is provided by a svelte component
+
+
+ See:
+ /lib/setting-pannel.svelte
+
+
+
+
+
{
+ showMessage(
+ `Checkbox changed: ${event.detail.key} = ${event.detail.value}`
+ );
+ }}
+ />
+ {
+ showMessage(
+ `Input changed: ${event.detail.key} = ${event.detail.value}`
+ );
+ }}
+ />
+ {
+ showMessage("Button clicked");
+ }}
+ />
+ {
+ showMessage(
+ `Select changed: ${event.detail.key} = ${event.detail.value}`
+ );
+ }}
+ />
+ {
+ showMessage(
+ `Slide changed: ${event.detail.key} = ${event.detail.value}`
+ );
+ }}
+ />
+
diff --git a/src/libs/setting-utils.ts b/src/libs/setting-utils.ts
index ae316e2..ff78af8 100644
--- a/src/libs/setting-utils.ts
+++ b/src/libs/setting-utils.ts
@@ -1,142 +1,60 @@
/*
* Copyright (c) 2023 by frostime. All Rights Reserved.
* @Author : frostime
- * @Date : 2023-12-17 18:28:19
+ * @Date : 2023-09-16 18:05:00
* @FilePath : /src/libs/setting-utils.ts
- * @LastEditTime : 2024-05-01 17:44:16
- * @Description :
+ * @LastEditTime : 2023-09-16 18:17:03
+ * @Description : A utility for siyuan plugin settings
*/
import { Plugin, Setting } from 'siyuan';
-
-/**
- * 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;
- };
- 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 = () => null;
- break;
- }
- return getter;
-}
-
-
-/**
- * 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;
- default:
- setter = () => {};
- 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: {
- plugin: Plugin,
- name?: string,
- callback?: (data: any) => void,
- width?: string,
- height?: string
- }) {
- this.name = args.name ?? 'settings';
- this.plugin = args.plugin;
+ 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: args.width,
- height: args.height,
+ width: width,
+ height: height,
confirmCallback: () => {
for (let key of this.settings.keys()) {
- this.updateValueFromElement(key);
+ this.updateValue(key);
}
let data = this.dump();
- if (args.callback !== undefined) {
- args.callback(data);
- }
this.plugin.data[this.name] = data;
- this.save(data);
- },
- destroyCallback: () => {
- //Restore the original value
- for (let key of this.settings.keys()) {
- this.updateElementFromValue(key);
- }
+ this.save();
}
});
}
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;
}
- async save(data?: any) {
- data = data ?? this.dump();
+ async save() {
+ let data = this.dump();
await this.plugin.saveData(this.file, this.dump());
- console.debug('Save config:', data);
return data;
}
/**
- * read the data after saving
+ * Get setting item value
* @param key key name
* @returns setting item value
*/
@@ -144,88 +62,6 @@ export class SettingUtils {
return this.settings.get(key)?.value;
}
- /**
- * Set data to this.settings,
- * but do not save it to the configuration file
- * @param key key name
- * @param value value
- */
- set(key: string, value: any) {
- let item = this.settings.get(key);
- if (item) {
- item.value = value;
- this.updateElementFromValue(key);
- }
- }
-
- /**
- * Set and save setting item value
- * If you want to set and save immediately you can use this method
- * @param key key name
- * @param value value
- */
- async setAndSave(key: string, value: any) {
- let item = this.settings.get(key);
- if (item) {
- item.value = value;
- this.updateElementFromValue(key);
- 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 item = this.settings.get(key);
- let element = this.elements.get(key) as any;
- if (!element) {
- return
- }
- if (apply) {
- this.updateValueFromElement(key);
- }
- return item.getEleVal(element);
- }
-
- /**
- * Read data from html and save it
- * @param key key name
- * @param value value
- * @return value in html
- */
- async takeAndSave(key: string) {
- let value = this.take(key, true);
- await this.save();
- return value;
- }
-
- /**
- * Disable setting item
- * @param key key name
- */
- disable(key: string) {
- let element = this.elements.get(key) as any;
- if (element) {
- element.disabled = true;
- }
- }
-
- /**
- * Enable setting item
- * @param key key name
- */
- enable(key: string) {
- let element = this.elements.get(key) as any;
- if (element) {
- element.disabled = false;
- }
- }
-
/**
* 将设置项目导出为 JSON 对象
* @returns object
@@ -239,59 +75,9 @@ export class SettingUtils {
return data;
}
- addItem(item: ISettingUtilsItem) {
+ addItem(item: ISettingItem) {
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);
- }
- if (item.setEleVal === undefined) {
- item.setEleVal = createDefaultSetter(item.type);
- }
-
- 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,
- direction: item?.direction,
- createActionElement: () => {
- this.updateElementFromValue(item.key);
- let element = this.getElement(item.key);
- return element;
- }
- });
- } else {
- 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);
- this.elements.set(item.key, element);
- return element;
- }
- });
- }
- }
-
- 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');
@@ -299,21 +85,17 @@ export class SettingUtils {
element.checked = item.value;
element.className = "b3-switch fn__flex-center";
itemElement = element;
- element.onchange = item.action?.callback ?? (() => { });
break;
case 'select':
let selectElement: HTMLSelectElement = document.createElement('select');
selectElement.className = "b3-select fn__flex-center fn__size200";
- let options = item?.options ?? {};
- for (let val in options) {
+ for (let option of item.select?.options ?? []) {
let optionElement = document.createElement('option');
- let text = options[val];
- optionElement.value = val;
- optionElement.text = text;
+ optionElement.value = option.val;
+ optionElement.text = option.text;
selectElement.appendChild(optionElement);
}
selectElement.value = item.value;
- selectElement.onchange = item.action?.callback ?? (() => { });
itemElement = selectElement;
break;
case 'slider':
@@ -327,7 +109,6 @@ export class SettingUtils {
sliderElement.value = item.value;
sliderElement.onchange = () => {
sliderElement.ariaLabel = sliderElement.value;
- item.action?.callback();
}
itemElement = sliderElement;
break;
@@ -335,63 +116,77 @@ export class SettingUtils {
let textInputElement: HTMLInputElement = document.createElement('input');
textInputElement.className = 'b3-text-field fn__flex-center fn__size200';
textInputElement.value = item.value;
- textInputElement.onchange = item.action?.callback ?? (() => { });
itemElement = textInputElement;
- textInputElement.addEventListener('keydown', preventEnterConfirm);
break;
case 'textarea':
let textareaElement: HTMLTextAreaElement = document.createElement('textarea');
textareaElement.className = "b3-text-field fn__block";
textareaElement.value = item.value;
- textareaElement.onchange = item.action?.callback ?? (() => { });
itemElement = textareaElement;
break;
- case 'number':
- let numberElement: HTMLInputElement = document.createElement('input');
- numberElement.type = 'number';
- 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');
buttonElement.className = "b3-button b3-button--outline fn__flex-center fn__size200";
buttonElement.innerText = item.button?.label ?? 'Button';
- buttonElement.onclick = item.button?.callback ?? (() => { });
+ buttonElement.onclick = item.button?.callback ?? (() => {});
itemElement = buttonElement;
break;
- case 'hint':
- let hintElement: HTMLElement = document.createElement('div');
- hintElement.className = 'b3-label fn__flex-center';
- itemElement = hintElement;
- break;
}
- return itemElement;
+ 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;
+ }
+ })
}
- /**
- * return the setting element
- * @param key key name
- * @returns element
- */
- getElement(key: string) {
- // let item = this.settings.get(key);
+ 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 updateValueFromElement(key: string) {
+ private updateValue(key: string) {
let item = this.settings.get(key);
- if (item.type === 'button') return;
let element = this.elements.get(key) as any;
- item.value = item.getEleVal(element);
+ console.log(element, element?.value);
+ switch (item.type) {
+ case 'checkbox':
+ item.value = element.checked;
+ break;
+ case 'select':
+ item.value = element.value;
+ break;
+ case 'slider':
+ item.value = parseInt(element.value);
+ break;
+ case 'textinput':
+ item.value = element.value;
+ break;
+ case 'textarea':
+ item.value = element.value;
+ break;
+ }
}
- private updateElementFromValue(key: string) {
- let item = this.settings.get(key);
- if (item.type === 'button') return;
- let element = this.elements.get(key) as any;
- item.setEleVal(element, item.value);
- }
}
\ No newline at end of file
diff --git a/src/setting-example.svelte b/src/setting-example.svelte
deleted file mode 100644
index 2a2c809..0000000
--- a/src/setting-example.svelte
+++ /dev/null
@@ -1,139 +0,0 @@
-
-
-
-
- {#each groups as group}
-
- - {
- focusGroup = group;
- }}
- on:keydown={() => {}}
- >
- {group}
-
- {/each}
-
-
-
{ console.debug("Click:", detail.key); }}
- >
-
- 💡 This is our default settings.
-
-
-
{ console.debug("Click:", detail.key); }}
- >
-
-
-
-
-
-
diff --git a/src/types/index.d.ts b/src/types/index.d.ts
index f224b3e..1891c1a 100644
--- a/src/types/index.d.ts
+++ b/src/types/index.d.ts
@@ -1,13 +1,10 @@
-/*
- * Copyright (c) 2024 by frostime. All Rights Reserved.
- * @Author : frostime
- * @Date : 2023-08-15 10:28:10
- * @FilePath : /src/types/index.d.ts
- * @LastEditTime : 2024-06-08 20:50:53
- * @Description : Frequently used data structures in SiYuan
+/**
+ * Copyright (c) 2023 frostime. All rights reserved.
*/
-
+/**
+ * Frequently used data structures in SiYuan
+ */
type DocumentId = string;
type BlockId = string;
type NotebookId = string;
@@ -31,25 +28,7 @@ type NotebookConf = {
dailyNoteTemplatePath: string;
}
-type BlockType =
- | 'd'
- | 'p'
- | 'query_embed'
- | 'l'
- | 'i'
- | 'h'
- | 'iframe'
- | 'tb'
- | 'b'
- | 's'
- | 'c'
- | 'widget'
- | 't'
- | 'html'
- | 'm'
- | 'av'
- | 'audio';
-
+type BlockType = "d" | "s" | "h" | "t" | "i" | "p" | "f" | "audio" | "video" | "other";
type BlockSubType = "d1" | "d2" | "s1" | "s2" | "s3" | "t1" | "t2" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "table" | "task" | "toggle" | "latex" | "quote" | "html" | "code" | "footnote" | "cite" | "collection" | "bookmark" | "attachment" | "comment" | "mindmap" | "spreadsheet" | "calendar" | "image" | "audio" | "video" | "other";
@@ -91,7 +70,6 @@ type doOperation = {
interface Window {
siyuan: {
- config: any;
notebooks: any;
menus: any;
dialogs: any;
@@ -100,7 +78,5 @@ interface Window {
user: any;
ws: any;
languages: any;
- emojis: any;
};
- Lute: any;
}
diff --git a/svelte.config.js b/svelte.config.js
index d62a343..7c8df62 100644
--- a/svelte.config.js
+++ b/svelte.config.js
@@ -1,26 +1,7 @@
-/*
- * Copyright (c) 2024 by frostime. All Rights Reserved.
- * @Author : frostime
- * @Date : 2023-05-19 19:49:13
- * @FilePath : /svelte.config.js
- * @LastEditTime : 2024-04-19 19:01:55
- * @Description :
- */
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"
-const NoWarns = new Set([
- "a11y-click-events-have-key-events",
- "a11y-no-static-element-interactions",
- "a11y-no-noninteractive-element-interactions"
-]);
-
export default {
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
// for more information about preprocessors
preprocess: vitePreprocess(),
- onwarn: (warning, handler) => {
- // suppress warnings on `vite dev` and `vite build`; but even without this, things still work
- if (NoWarns.has(warning.code)) return;
- handler(warning);
- }
}
diff --git a/tsconfig.json b/tsconfig.json
index 0fcc1ad..e196929 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -47,8 +47,7 @@
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
- "src/**/*.vue",
- "src/**/*.svelte"
+ "src/**/*.vue"
],
"references": [
{
diff --git a/vite.config.ts b/vite.config.ts
index cb7511b..2af9f2f 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,22 +1,19 @@
import { resolve } from "path"
import { defineConfig, loadEnv } from "vite"
+import minimist from "minimist"
import { viteStaticCopy } from "vite-plugin-static-copy"
import livereload from "rollup-plugin-livereload"
import { svelte } from "@sveltejs/vite-plugin-svelte"
import zipPack from "vite-plugin-zip-pack";
import fg from 'fast-glob';
-import vitePluginYamlI18n from './yaml-plugin';
+const args = minimist(process.argv.slice(2))
+const isWatch = args.watch || args.w || false
+const devDistDir = "./dev"
+const distDir = isWatch ? devDistDir : "./dist"
-const env = process.env;
-const isSrcmap = env.VITE_SOURCEMAP === 'inline';
-const isDev = env.NODE_ENV === 'development';
-
-const outputDir = isDev ? "dev" : "dist";
-
-console.log("isDev=>", isDev);
-console.log("isSrcmap=>", isSrcmap);
-console.log("outputDir=>", outputDir);
+console.log("isWatch=>", isWatch)
+console.log("distDir=>", distDir)
export default defineConfig({
resolve: {
@@ -28,69 +25,92 @@ export default defineConfig({
plugins: [
svelte(),
- vitePluginYamlI18n({
- inDir: 'public/i18n',
- outDir: `${outputDir}/i18n`
- }),
-
viteStaticCopy({
targets: [
- { src: "./README*.md", dest: "./" },
- { src: "./plugin.json", dest: "./" },
- { src: "./preview.png", dest: "./" },
- { src: "./icon.png", dest: "./" }
+ {
+ src: "./README*.md",
+ dest: "./",
+ },
+ {
+ src: "./icon.png",
+ dest: "./",
+ },
+ {
+ src: "./preview.png",
+ dest: "./",
+ },
+ {
+ src: "./plugin.json",
+ dest: "./",
+ },
+ {
+ src: "./src/i18n/**",
+ dest: "./i18n/",
+ },
],
}),
-
],
+ // https://github.com/vitejs/vite/issues/1930
+ // https://vitejs.dev/guide/env-and-mode.html#env-files
+ // https://github.com/vitejs/vite/discussions/3058#discussioncomment-2115319
+ // 在这里自定义变量
define: {
- "process.env.DEV_MODE": JSON.stringify(isDev),
- "process.env.NODE_ENV": JSON.stringify(env.NODE_ENV)
+ "process.env.DEV_MODE": `"${isWatch}"`,
},
build: {
- outDir: outputDir,
+ // 输出路径
+ outDir: distDir,
emptyOutDir: false,
- minify: true,
- sourcemap: isSrcmap ? 'inline' : false,
+
+ // 构建后是否生成 source map 文件
+ sourcemap: false,
+
+ // 设置为 false 可以禁用最小化混淆
+ // 或是用来指定是应用哪种混淆器
+ // boolean | 'terser' | 'esbuild'
+ // 不压缩,用于调试
+ minify: !isWatch,
lib: {
+ // Could also be a dictionary or array of multiple entry points
entry: resolve(__dirname, "src/index.ts"),
+ // the proper extensions will be added
fileName: "index",
formats: ["cjs"],
},
rollupOptions: {
plugins: [
- ...(isDev ? [
- livereload(outputDir),
- {
- name: 'watch-external',
- async buildStart() {
- const files = await fg([
- 'public/i18n/**',
- './README*.md',
- './plugin.json'
- ]);
- for (let file of files) {
- this.addWatchFile(file);
+ ...(
+ isWatch ? [
+ livereload(devDistDir),
+ {
+ //监听静态资源文件
+ name: 'watch-external',
+ async buildStart() {
+ const files = await fg([
+ 'src/i18n/*.json',
+ './README*.md',
+ './plugin.json'
+ ]);
+ for (let file of files) {
+ this.addWatchFile(file);
+ }
}
}
- }
- ] : [
- // Clean up unnecessary files under dist dir
- cleanupDistFiles({
- patterns: ['i18n/*.yaml', 'i18n/*.md'],
- distDir: outputDir
- }),
- zipPack({
- inDir: './dist',
- outDir: './',
- outFileName: 'package.zip'
- })
- ])
+ ] : [
+ zipPack({
+ inDir: './dist',
+ outDir: './',
+ outFileName: 'package.zip'
+ })
+ ]
+ )
],
+ // make sure to externalize deps that shouldn't be bundled
+ // into your library
external: ["siyuan", "process"],
output: {
@@ -104,60 +124,4 @@ export default defineConfig({
},
},
}
-});
-
-
-/**
- * Clean up some dist files after compiled
- * @author frostime
- * @param options:
- * @returns
- */
-function cleanupDistFiles(options: { patterns: string[], distDir: string }) {
- const {
- patterns,
- distDir
- } = options;
-
- return {
- name: 'rollup-plugin-cleanup',
- enforce: 'post',
- writeBundle: {
- sequential: true,
- order: 'post' as 'post',
- async handler() {
- const fg = await import('fast-glob');
- const fs = await import('fs');
- // const path = await import('path');
-
- // 使用 glob 语法,确保能匹配到文件
- const distPatterns = patterns.map(pat => `${distDir}/${pat}`);
- console.debug('Cleanup searching patterns:', distPatterns);
-
- const files = await fg.default(distPatterns, {
- dot: true,
- absolute: true,
- onlyFiles: false
- });
-
- // console.info('Files to be cleaned up:', files);
-
- for (const file of files) {
- try {
- if (fs.default.existsSync(file)) {
- const stat = fs.default.statSync(file);
- if (stat.isDirectory()) {
- fs.default.rmSync(file, { recursive: true });
- } else {
- fs.default.unlinkSync(file);
- }
- console.log(`Cleaned up: ${file}`);
- }
- } catch (error) {
- console.error(`Failed to clean up ${file}:`, error);
- }
- }
- }
- }
- };
-}
+})
diff --git a/yaml-plugin.js b/yaml-plugin.js
deleted file mode 100644
index 01c85e2..0000000
--- a/yaml-plugin.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2024 by frostime. All Rights Reserved.
- * @Author : frostime
- * @Date : 2024-04-05 21:27:55
- * @FilePath : /yaml-plugin.js
- * @LastEditTime : 2024-04-05 22:53:34
- * @Description : 去妮玛的 json 格式,我就是要用 yaml 写 i18n
- */
-// plugins/vite-plugin-parse-yaml.js
-import fs from 'fs';
-import yaml from 'js-yaml';
-import { resolve } from 'path';
-
-export default function vitePluginYamlI18n(options = {}) {
- // Default options with a fallback
- const DefaultOptions = {
- inDir: 'src/i18n',
- outDir: 'dist/i18n',
- };
-
- const finalOptions = { ...DefaultOptions, ...options };
-
- return {
- name: 'vite-plugin-yaml-i18n',
- buildStart() {
- console.log('🌈 Parse I18n: YAML to JSON..');
- const inDir = finalOptions.inDir;
- const outDir = finalOptions.outDir
-
- if (!fs.existsSync(outDir)) {
- fs.mkdirSync(outDir, { recursive: true });
- }
-
- //Parse yaml file, output to json
- const files = fs.readdirSync(inDir);
- for (const file of files) {
- if (file.endsWith('.yaml') || file.endsWith('.yml')) {
- console.log(`-- Parsing ${file}`)
- //检查是否有同名的json文件
- const jsonFile = file.replace(/\.(yaml|yml)$/, '.json');
- if (files.includes(jsonFile)) {
- console.log(`---- File ${jsonFile} already exists, skipping...`);
- continue;
- }
- try {
- const filePath = resolve(inDir, file);
- const fileContents = fs.readFileSync(filePath, 'utf8');
- const parsed = yaml.load(fileContents);
- const jsonContent = JSON.stringify(parsed, null, 2);
- const outputFilePath = resolve(outDir, file.replace(/\.(yaml|yml)$/, '.json'));
- console.log(`---- Writing to ${outputFilePath}`);
- fs.writeFileSync(outputFilePath, jsonContent);
- } catch (error) {
- this.error(`---- Error parsing YAML file ${file}: ${error.message}`);
- }
- }
- }
- },
- };
-}