diff --git a/build.ts b/build.ts index 65b0ca1d..0075c04f 100644 --- a/build.ts +++ b/build.ts @@ -27,7 +27,6 @@ import { build } from "vite" import path from "path" -import dts from "vite-plugin-dts" // libraries const libraries = [ @@ -47,7 +46,6 @@ const libraries = [ for (const libItem of libraries) { await build({ configFile: false, - plugins: [dts()], resolve: { alias: [ { @@ -76,7 +74,7 @@ for (const libItem of libraries) { return chunkName }, }, - external: ["path"], + external: ["path", "fs"], }, }, }) diff --git a/package.json b/package.json index 67cbee3f..dc8cdeaa 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "vitest": "^0.29.2" }, "dependencies": { + "compare-versions": "6.0.0-rc.1", "zhi-log": "^1.5.5" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 321c7e5b..5bc21ed9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,7 @@ specifiers: '@typescript-eslint/eslint-plugin': ^5.54.1 '@typescript-eslint/parser': ^5.54.1 '@vitest/coverage-c8': ^0.29.2 + compare-versions: 6.0.0-rc.1 eslint: ^8.35.0 eslint-config-prettier: ^8.7.0 jsdoc-babel: ^0.5.0 @@ -23,6 +24,7 @@ specifiers: zhi-log: ^1.5.5 dependencies: + compare-versions: 6.0.0-rc.1 zhi-log: 1.5.5 devDependencies: @@ -3860,6 +3862,10 @@ packages: engines: {node: '>=8'} dev: true + /compare-versions/6.0.0-rc.1: + resolution: {integrity: sha512-cFhkjbGY1jLFWIV7KegECbfuyYPxSGvgGkdkfM+ibboQDoPwg2FRHm5BSNTOApiauRBzJIQH7qvOJs2sW5ueKQ==} + dev: false + /concat-map/0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true diff --git a/src/apps/zhi/plugin-system/index.ts b/src/apps/zhi/plugin-system/index.ts index 8ecc4345..ebbbe7cb 100644 --- a/src/apps/zhi/plugin-system/index.ts +++ b/src/apps/zhi/plugin-system/index.ts @@ -38,6 +38,7 @@ const initPluginSystem = (): DependencyItem[] => { "/appearance/themes/zhi/dist-cjs/plugin-system/plugin-system-hook.cjs", format: "cjs", importType: "require", + runAs: "electron", }, ] } diff --git a/src/apps/zhi/plugin-system/plugin-system-hook.ts b/src/apps/zhi/plugin-system/plugin-system-hook.ts index 9de9aa5a..63782a34 100644 --- a/src/apps/zhi/plugin-system/plugin-system-hook.ts +++ b/src/apps/zhi/plugin-system/plugin-system-hook.ts @@ -24,7 +24,25 @@ */ import ZhiUtil from "~/src/utils/ZhiUtil" +import strUtil from "~/src/utils/strUtil" +import nodeUtil from "~/src/utils/nodeUtil" +import pluginSystemUtil, { + HackPluginSystem, +} from "~/src/apps/zhi/plugin-system/pluginSystemUtil" +import siyuanUtil from "~/src/utils/siyuanUtil" +import { compareVersions } from "compare-versions" +import cjsUtil from "~/src/utils/cjsUtil" +const fs = cjsUtil.safeRequire("fs") +const path = cjsUtil.safeRequire("path") + +/** + * 插件系统入口(由theme.js动态调用,请勿主动调用) + * vite构建配置:config/vite.cjs.config.plugin.system.hook + * + * @author terwer + * @since 1.0.0 + */ class PluginSystemHook { private readonly logger @@ -32,11 +50,167 @@ class PluginSystemHook { this.logger = ZhiUtil.zhiSdk().getLogger() } + /** + * 获取插件同步信息 + * + * @param p 插件系统对象 + * @param zhiPlugin 插件对象 + */ + getOldPluginInfo(p: any, zhiPlugin: any) { + let isSynced = false + let isUpdate = false + let oldVersion = pluginSystemUtil.OLD_VERSION_ZERO + + const plugins = p.pslm.storageMangager.thirdPartyPlugins + for (const item of plugins) { + // this.logger.debug("Plugin=>", item) + // 不是当前插件跳过 + if (zhiPlugin.name !== item.name) { + continue + } + + // 当前插件有新版本 + if (compareVersions(zhiPlugin.version, item.version) > 0) { + isUpdate = true + } + + oldVersion = item.version + isSynced = true + } + + return { isSynced, oldVersion, isUpdate } + } + + async syncZhiPlugins(p: any) { + const hack = new HackPluginSystem() + + this.logger.info("Start syncing zhi plugins ...") + + // 主题插件目录 + const zhiPluginsPath = path.join( + siyuanUtil.ZHI_CJS_PATH(), + pluginSystemUtil.ZHI_PLUGIN_FOLDER + ) + // this.logger.info("Zhi plugins folder=>", zhiPluginsPath) + + // 插件系统默认目录 + const pluginsPath = path.join( + siyuanUtil.SIYUAN_DATA_PATH(), + pluginSystemUtil.PLUGIN_FOLDER + ) + // this.logger.info("Plugins folder=>", pluginsPath) + + let syncedCount = 0 + let zhiPlugins: any = [] + // 未找到主题差距,不同步 + if (!fs.existsSync(zhiPluginsPath)) { + this.logger.warn("No zhi plugins found, stop!") + } else { + // 扫描插件并同步 + zhiPlugins = await hack.scanPlugins(zhiPluginsPath) + // this.logger.debug("zhiPlugins=>", zhiPlugins) + for (const item of zhiPlugins) { + const pluginBasename = path.basename(item) + const from = item + const to = path.join(pluginsPath, pluginBasename) + this.logger.debug( + strUtil.f("Try syncing zhi plugin {0}", pluginBasename) + ) + + const manifest = await hack.getManifest( + path.join(item, pluginSystemUtil.MANIFEST) + ) + // this.logger.debug("ZhiPlugin=>", manifest) + + const oldPluginInfo = this.getOldPluginInfo(p, manifest) + const oldVersion = oldPluginInfo.oldVersion + this.logger.info( + strUtil.f( + "Plugin status : [{0}] isSynced=>{1}, isUpdate=>{2}, forceUpdate=>{3}, version Info: {4} -> {5}", + pluginBasename, + oldPluginInfo.isSynced, + oldPluginInfo.isUpdate, + manifest.forceUpdate, + oldVersion, + manifest.version + ) + ) + + // 同步需满足下面条件 + // 1. 未同步过或者有新版本 + // 2. 新旧插件注册信息目录均保持一致 + if (!oldPluginInfo.isSynced) { + // 未同步过,但是目标目录已存在 + if (fs.existsSync(to)) { + throw new Error( + strUtil.f("Expected forder already exists=>{0}", to) + ) + } + + strUtil.f("Do syncing, please wait...") + nodeUtil.copyFolderSync(from, to) + syncedCount++ + } else if (oldPluginInfo.isSynced && oldPluginInfo.isUpdate) { + // 新插件目录不一致,但是有版本号 + if (!fs.existsSync(to)) { + throw new Error( + strUtil.f( + "Conflict plugin exists, manifest exists but dest folder is not correct with original, please fix plugin folder name.Expected forder is=>{0}", + to + ) + ) + } + + strUtil.f("Do syncing, please wait...") + nodeUtil.copyFolderSync(from, to) + syncedCount++ + } else if (manifest.forceUpdate) { + this.logger.warn( + strUtil.f( + "Find forceUpdate flag in manifest.json, try forcing update plugin, [{0}] {1}.This flag is development only, before publish plugin, you should remove this flag from manifest.json!", + pluginBasename, + manifest.version + ) + ) + + nodeUtil.rmFolder(to) + nodeUtil.copyFolderSync(from, to) + syncedCount++ + } else { + this.logger.debug( + strUtil.f( + "Already synced and the latest version [{0}] {1}", + pluginBasename, + manifest.version + ) + ) + } + } + } + + this.logger.info( + strUtil.f( + "Zhi theme plugins Synced.Scaned {0}, synced {1} plugin(s).", + zhiPlugins.length, + syncedCount + ) + ) + + if (syncedCount > 0) { + this.logger.warn( + strUtil.f( + "Synced {0} zhi plugins, you need to reload siyuan to take effect.", + syncedCount + ) + ) + } + } + async init() { - // await pluginSystemUtil.initPluginSystem() - // - // const sys = await pluginSystemUtil.getPluginSystem() - // await this.syncZhiPlugins(sys) + await pluginSystemUtil.initPluginSystem() + + const sys = await pluginSystemUtil.getPluginSystem() + await this.syncZhiPlugins(sys) this.logger.info("PluginSystemHook inited.") } diff --git a/src/apps/zhi/plugin-system/pluginSystemUtil.ts b/src/apps/zhi/plugin-system/pluginSystemUtil.ts new file mode 100644 index 00000000..47a33945 --- /dev/null +++ b/src/apps/zhi/plugin-system/pluginSystemUtil.ts @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +// 警告⚠️:请勿在非思源笔记Electron环境调用此文件中的任何方法 + +import strUtil from "~/src/utils/strUtil" +import cjsUtil from "~/src/utils/cjsUtil" +import siyuanUtil from "~/src/utils/siyuanUtil" +import ZhiUtil from "~/src/utils/ZhiUtil" + +const fs = cjsUtil.safeRequire("fs") +const path = cjsUtil.safeRequire("path") + +const logger = ZhiUtil.zhiSdk().getLogger() + +const ZHI_PLUGIN_FOLDER = "zhi-plugins" +const PLUGIN_FOLDER = "plugins" +const MANIFEST = "manifest.json" +const SCRIPT = "main.js" + +const SIYUAN_ZHI_THEME_PLUGIN_PATH = path.join( + path.join(siyuanUtil.SIYUAN_DATA_PATH(), "dist-cjs") +) + +const OLD_VERSION_ZERO = "0.0.0" + +const getPluginSystem = () => { + return siyuanUtil.syWin().pluginSystem +} +const getPluginSystemVersion = () => { + return siyuanUtil.syWin().pluginSystemVersion +} + +/** + * hack插件系统的某些功能 + * + * @author terwer + * @since 1.0.0 + */ +export class HackPluginSystem { + logger = ZhiUtil.zhiSdk().getLogger() + + isDir(p: any) { + return fs.statSync(p).isDirectory() + } + + isExists(p: any) { + try { + fs.statSync(p) + return true + } catch (e) { + return false + } + } + + getFileContent = async (f: any) => { + return new Promise((resolve, reject) => { + fs.readFile(f, (err: any, data: any) => { + if (err) { + reject(err) + return + } + return resolve(data.toString("utf8")) + }) + }) + } + + getManifest = async (manifest: any) => { + const content: any = await this.getFileContent(manifest) + try { + return JSON.parse(content) + } catch (e) { + this.logger.error("loading manifest: " + manifest, e) + return null + } + } + + async scanPlugins(pluginFolder: string) { + return new Promise((resolve, reject) => { + fs.readdir(pluginFolder, (err: any, files: any) => { + if (err) { + logger.error(err) + resolve([]) + return + } + resolve( + files + .filter((f: any) => { + return ( + this.isDir(path.join(pluginFolder, f)) && + this.isExists(path.join(pluginFolder, f, MANIFEST)) && + this.isExists(path.join(pluginFolder, f, SCRIPT)) + ) + }) + ?.map((g: any) => path.resolve(pluginFolder, g)) || [] + ) + }) + }) + } +} + +const initPluginSystem = async () => { + const pluginSystem = await getPluginSystem() + if (pluginSystem) { + logger.warn("Plugin system already loaded by snapshots, ignore initiation.") + logger.warn("Loaded plugin system version is ", getPluginSystemVersion()) + return + } + + try { + logger.info("Undetected plugin system,initiating plugin system...") + + const data = fs.readFileSync( + path.join( + siyuanUtil.getCrossPlatformAppDataFolder(), + ".siyuan", + "plugin.js" + ) + ) + const script = data.toString("utf8") + logger.info("local plugin system found, loading...") + eval(script) + } catch (e) { + logger.info("local plugin system not found, load online", e) + return fetch( + "https://gitee.com/zuoez02/siyuan-plugin-system/raw/main/main.js", + { cache: "no-cache" } + ) + .then((res) => res.text()) + .then((sc) => { + siyuanUtil.syWin().siyuanPluginScript = sc + eval(sc) + }) + } + + const sysv = getPluginSystemVersion() + logger.info(strUtil.f("Plugin system initiation finished=>{0}.", sysv)) +} + +const pluginSystemUtil = { + SIYUAN_ZHI_THEME_PLUGIN_PATH, + + ZHI_PLUGIN_FOLDER, + PLUGIN_FOLDER, + OLD_VERSION_ZERO, + + MANIFEST, + SCRIPT, + + getPluginSystem, + getPluginSystemVersion, + initPluginSystem, +} +export default pluginSystemUtil diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..041f6b5e --- /dev/null +++ b/src/index.ts @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +import ZhiUtil from "~/src/utils/ZhiUtil" +import Zhi from "~/src/apps/zhi/zhi" +import strUtil from "~/src/utils/strUtil" +import cjsUtil from "~/src/utils/cjsUtil" +import BrowserUtil from "~/src/utils/browserUtil" +import siyuanUtil from "~/src/utils/siyuanUtil" + +/** + * 主题通用类(由theme.js动态调用,除了单元测试之外请勿主动调用) + * + * @public + * @author terwer + * @since 1.0.0 + */ +class Theme { + private readonly logger + private readonly zhiTheme + + constructor() { + this.logger = ZhiUtil.zhiSdk().getLogger() + this.zhiTheme = new Zhi() + } + + /** + * 主流程加载 + * + * @param runAs 运行模式 + */ + public async init(runAs?: any): Promise { + try { + // 初始化第三方依赖 + const dynamicImports = await this.zhiTheme.main([]) + for (const item of dynamicImports) { + const libpath = item.libpath + // 类型校验 + if (item.format !== "cjs" || !libpath.includes(".cjs")) { + this.logger.warn("Only cjs supported, skip this lib!", libpath) + continue + } + + // 运行环境校验 + if (runAs) { + if (runAs !== item.runAs) { + this.logger.warn( + strUtil.f("This lib can only run at {0}, skip!", item.runAs) + ) + continue + } + } + + const path = cjsUtil.safeRequire("path") + this.logger.info("Loading dependency=>", libpath) + + let lib + if (BrowserUtil.isInBrowser) { + const importPath = path.join(siyuanUtil.SIYUAN_CONF_PATH(), libpath) + lib = cjsUtil.safeRequire(importPath) + } + + // 如果有初始化方法,进行初始化 + if (lib && lib.init) { + await lib.init() + } + } + this.logger.info("Theme inited.") + } catch (e) { + this.logger.error("Theme load error=>", e) + } + } +} + +export default Theme diff --git a/src/models/DependencyItem.ts b/src/models/DependencyItem.ts index ed2a909a..02912b6f 100644 --- a/src/models/DependencyItem.ts +++ b/src/models/DependencyItem.ts @@ -33,11 +33,13 @@ class DependencyItem { libpath: string format: "cjs" | "esm" | "js" importType: "require" | "import" + runAs: "browser" | "node" | "electron" | "both" constructor() { this.libpath = "" this.format = "cjs" this.importType = "require" + this.runAs = "both" } } diff --git a/src/utils/browserUtil.ts b/src/utils/browserUtil.ts new file mode 100644 index 00000000..608d89af --- /dev/null +++ b/src/utils/browserUtil.ts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +class BrowserUtil { + public static isInBrowser = typeof window !== "undefined" +} + +export default BrowserUtil diff --git a/src/utils/cjsUtil.ts b/src/utils/cjsUtil.ts index 84eca8d7..628bae19 100644 --- a/src/utils/cjsUtil.ts +++ b/src/utils/cjsUtil.ts @@ -40,11 +40,18 @@ class CjsUtil { * @author terwer * @since 1.0.0 */ - public static safeRequire(moduleName: string): unknown { + public static safeRequire(moduleName: string): any { + // Node环境 + if (typeof window === "undefined") { + return require(moduleName) + } + + // 构建环境 if (require === window.require) { return require(moduleName) } + // Electron浏览器环境 return window.require(moduleName) } } diff --git a/src/utils/nodeUtil.ts b/src/utils/nodeUtil.ts new file mode 100644 index 00000000..22983e30 --- /dev/null +++ b/src/utils/nodeUtil.ts @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023, Terwer . All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Terwer designates this + * particular file as subject to the "Classpath" exception as provided + * by Terwer in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Terwer, Shenzhen, Guangdong, China, youweics@163.com + * or visit www.terwer.space if you need additional information or have any + * questions. + */ + +// 警告⚠️:请勿在非Node环境调用此文件中的任何方法 + +import cjsUtil from "~/src/utils/cjsUtil" + +const fs = cjsUtil.safeRequire("fs") +const path = cjsUtil.safeRequire("path") + +/** + * 可以使用Node.js内置的fs模块中的`copyFileSync`或者`copyFile`方法来复制文件夹。不过需要注意,这两个方法只能复制单个文件,如果想要复制整个文件夹,需要自己编写递归函数实现。 + * 本方法用于复制一个文件夹以及其中所有子文件和子文件夹 + * + * @param source 源文件 + * @param target 目标文件 + * @author terwer + * @since 1.0.0 + */ +const copyFolderSync = (source: string, target: string): void => { + if (!fs.existsSync(target)) { + fs.mkdirSync(target) + } + + if (fs.lstatSync(source).isDirectory()) { + const files: any[] = fs.readdirSync(source) + files.forEach(function (file: any) { + const curSource = path.join(source, file) + if (fs.lstatSync(curSource).isDirectory()) { + copyFolderSync(curSource, path.join(target, file)) + } else { + fs.copyFileSync(curSource, path.join(target, file)) + } + }) + } +} + +/** + * 删除文件夹 + * + * @param folder 文件夹 + */ +const rmFolder = (folder: string) => { + if (fs.existsSync(folder)) { + // fs.rm(folder, { recursive: true, force: true }) + fs.rmdirSync(folder, { recursive: true }) + } +} + +const nodeUtil = { + copyFolderSync, + rmFolder, +} + +export default nodeUtil diff --git a/src/utils/siyuanUtil.ts b/src/utils/siyuanUtil.ts index 5284b9c0..e5e99ce8 100644 --- a/src/utils/siyuanUtil.ts +++ b/src/utils/siyuanUtil.ts @@ -23,10 +23,55 @@ * questions. */ +import cjsUtil from "~/src/utils/cjsUtil" +import BrowserUtil from "~/src/utils/browserUtil" + +const path = cjsUtil.safeRequire("path") + class SiyuanUtil { - public syWin = window as any + public syWin() { + return (BrowserUtil.isInBrowser ? window : {}) as any + } + + public SIYUAN_CONF_PATH() { + return this.syWin()?.siyuan.config.system.confDir + } + + public SIYUAN_DATA_PATH() { + return this.syWin()?.siyuan.config.system.dataDir + } + + public SIYUAN_APPEARANCE_PATH() { + return path.join(this.SIYUAN_CONF_PATH(), "appearance") + } + + public SIYUAN_THEME_PATH() { + return path.join(this.SIYUAN_APPEARANCE_PATH(), "themes") + } + + public ZHI_THEME_PATH() { + return path.join(this.SIYUAN_THEME_PATH(), "zhi") + } + + public ZHI_CJS_PATH() { + return path.join(this.ZHI_THEME_PATH(), "dist-cjs") + } - SIYUAN_CONF_PATH = this.syWin.siyuan.config.system.confDir + getCrossPlatformAppDataFolder = () => { + let configFilePath + if (this.syWin()?.process.platform === "darwin") { + configFilePath = path.join( + this.syWin()?.process.env.HOME, + "/Library/Application Support" + ) + } else if (this.syWin()?.process.platform === "win32") { + // Roaming包含在APPDATA中了 + configFilePath = this.syWin()?.process.env.APPDATA + } else if (this.syWin()?.process.platform === "linux") { + configFilePath = this.syWin()?.process.env.HOME + } + return configFilePath + } } const siyuanUtil = new SiyuanUtil() diff --git a/test/theme.test.ts b/test/theme.test.ts index 05707e1f..0829f728 100644 --- a/test/theme.test.ts +++ b/test/theme.test.ts @@ -24,11 +24,11 @@ */ import { describe, it } from "vitest" -import Theme from "~/theme" +import Theme from "~/src/index" describe("test theme", () => { it("test main", async () => { const theme = new Theme() - await theme.init() + await theme.init("node") }) }) diff --git a/theme.ts b/theme.ts index df695db2..450526ee 100644 --- a/theme.ts +++ b/theme.ts @@ -28,67 +28,8 @@ * 🛍️ 一款自带插件和博客的思源笔记主题 */ -import Zhi from "~/src/apps/zhi/zhi" -import ZhiUtil from "~/src/utils/ZhiUtil" -import siyuanUtil from "~/src/utils/siyuanUtil" -import Bootstrap from "~/src/apps/zhi/bootstrap" -import Lifecycle from "~/src/apps/zhi/Lifecycle" -import DependencyItem from "~/src/models/DependencyItem" - -// 特别提醒1⚠️:此文件是主题的唯一入口,会在构建时自动生成js文件 -// 特别提醒2⚠️:该文件由思源笔记自动加载,请勿主动调用此文件中的任何方法 - -/** - * 主题通用入口(由theme.js动态调用,请勿主动调用) - * vite构建配置:vite.config.ts - * - * @public - * @author terwer - * @since 1.0.0 - */ -class Theme { - private readonly logger - private readonly zhiTheme - - constructor() { - this.logger = ZhiUtil.zhiSdk().getLogger() - this.zhiTheme = new Zhi() - } - - /** - * 主流程加载 - */ - public async init(): Promise { - try { - // 初始化第三方依赖 - const dynamicImports = await this.zhiTheme.main([]) - for (const item of dynamicImports) { - const libpath = item.libpath - if (item.format !== "cjs" || !libpath.includes(".cjs")) { - this.logger.warn("Only cjs supported, skip this lib!", libpath) - continue - } - - const path = siyuanUtil.syWin.require("path") - const importPath = path.join(siyuanUtil.SIYUAN_CONF_PATH, libpath) - this.logger.info("Loading dependency=>", libpath) - const lib = siyuanUtil.syWin.require(importPath) - // 如果有初始化方法,进行初始化 - if (lib && lib.init) { - await lib.init() - } - } - this.logger.info("Theme inited.") - } catch (e) { - this.logger.error("Theme load error=>", e) - } - } -} - +import Theme from "~/src/index" ;(async () => { const theme = new Theme() - await theme.init() + await theme.init("electron") })() - -export default Theme -export { Bootstrap, Lifecycle, DependencyItem }