From 179a30c0414c2375d98e2e91da53d34e22da7c6f Mon Sep 17 00:00:00 2001 From: terwer Date: Sun, 5 Mar 2023 03:33:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20#27=20=E4=BD=BF=E7=94=A8=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E7=B3=BB=E7=BB=9F=E6=8C=82=E8=BD=BD=E8=8F=9C=E5=8D=95?= =?UTF-8?q?-=E4=BC=98=E5=8C=96=E6=8F=92=E4=BB=B6=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zhi/plugin-system/plugin-system-hook.ts | 76 +++++++- src/utils/logUtil.ts | 5 - src/utils/otherlib/pluginSystemUtil.js | 171 ++++++++++++++++++ src/utils/otherlib/siyuanUtil.js | 28 +-- src/utils/sysUtil.ts | 2 - typings/custom.d.ts | 25 +++ 6 files changed, 287 insertions(+), 20 deletions(-) create mode 100644 src/utils/otherlib/pluginSystemUtil.js diff --git a/src/apps/zhi/plugin-system/plugin-system-hook.ts b/src/apps/zhi/plugin-system/plugin-system-hook.ts index 2343703f..76fb57f4 100644 --- a/src/apps/zhi/plugin-system/plugin-system-hook.ts +++ b/src/apps/zhi/plugin-system/plugin-system-hook.ts @@ -24,10 +24,16 @@ */ import logFactory from "~/src/utils/logUtil" +import pluginSystemUtil, { HackPluginSystem } from "~/src/utils/otherlib/pluginSystemUtil" +import siyuanUtil from "~/src/utils/otherlib/siyuanUtil" +import strUtil from "~/src/utils/strUtil" // 警告1⚠️:此文件会在购建时生成js文件,并且由theme.js动态调用 // 警告2⚠️:请勿主动调用此文件中的任何方法 +const fs = window.require("fs") +const path = window.require("path") + /** * 插件系统入口(由theme.js动态调用,请勿主动调用) * vite构建配置:config/vite.cjs.config.plugin.system.hook @@ -38,8 +44,76 @@ import logFactory from "~/src/utils/logUtil" class PluginSystemHook { private logger = logFactory.getLogger("plugin-system-hook") + getOldPluginVersion(p: any, zhiPlugin: any) { + 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 + } + oldVersion = item.version + } + + return oldVersion + } + + 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 zhiPlugins = [] + // 未找到主题差距,不同步 + if (!fs.existsSync(zhiPluginsPath)) { + this.logger.warn("No zhi plugins found, stop!") + } else { + // 扫描插件并同步 + zhiPlugins = await hack.scanPlugins(zhiPluginsPath) + for (const item of zhiPlugins) { + const manifest = await hack.getManifest( + path.join(item, pluginSystemUtil.MANIFEST) + ) + this.logger.debug("ZhiPlugin=>", manifest) + + const oldVersion = this.getOldPluginVersion(p, manifest) + this.logger.debug("OldVersion=>", oldVersion) + + // if (oldVersion === OLD_VERSION_ZERO) { + // } + } + } + + this.logger.info( + strUtil.f( + "Syncing zhi theme plugins finished.synced {0} plugin(s).", + zhiPlugins.length + ) + ) + } + async init() { - this.logger.info("Syncing zhi theme plugins finished.") + await pluginSystemUtil.initPluginSystem() + const sysv = pluginSystemUtil.getPluginSystemVersion() + this.logger.info("Plugin system initiation finished.", sysv) + + const sys = await pluginSystemUtil.getPluginSystem() + this.logger.info("Syncing zhi theme plugins...", sys) + await this.syncZhiPlugins(sys) } } diff --git a/src/utils/logUtil.ts b/src/utils/logUtil.ts index 64cfc0b8..56b8278c 100644 --- a/src/utils/logUtil.ts +++ b/src/utils/logUtil.ts @@ -60,11 +60,6 @@ class LogUtil { prefix.reg(loglevel) loglevel.setLevel(LOG_LEVEL_DEBUG) - // if (isDev) { - // loglevel.setLevel(LOG_LEVEL_DEBUG) - // } else { - // loglevel.setLevel(LOG_LEVEL_WARN) - // } prefix.apply(loglevel, { format(level, name, timestamp) { diff --git a/src/utils/otherlib/pluginSystemUtil.js b/src/utils/otherlib/pluginSystemUtil.js new file mode 100644 index 00000000..5155d0ef --- /dev/null +++ b/src/utils/otherlib/pluginSystemUtil.js @@ -0,0 +1,171 @@ +/* + * 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 logFactory from "~/src/utils/logUtil" +import siyuanUtil from "~/src/utils/otherlib/siyuanUtil" + +const fs = window.require("fs") +const path = window.require("path") + +const logger = logFactory.getLogger("pluginSystemUtil") + +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 window.pluginSystem +} +const getPluginSystemVersion = () => { + return window.pluginSystemVersion +} + +/** + * hack插件系统的某些功能 + * + * @author terwer + * @since 1.0.0 + */ +export class HackPluginSystem { + logger = logFactory.getLogger("HackPluginSystem") + + isDir(p) { + return fs.statSync(p).isDirectory() + } + + isExists(p) { + try { + fs.statSync(p) + return true + } catch (e) { + return false + } + } + + getFileContent = async (f) => { + return new Promise((resolve, reject) => { + fs.readFile(f, (err, data) => { + if (err) { + reject(err) + return + } + return resolve(data.toString("utf8")) + }) + }) + } + + getManifest = async (manifest) => { + const content = await this.getFileContent(manifest) + try { + return JSON.parse(content) + } catch (e) { + this.logger.error("loading manifest: " + manifest, e) + return null + } + } + + async scanPlugins(pluginFolder) { + return new Promise((resolve, reject) => { + fs.readdir(pluginFolder, (err, files) => { + if (err) { + logger.error(err) + resolve([]) + return + } + resolve( + files + .filter((f) => { + return ( + this.isDir(path.join(pluginFolder, f)) && + this.isExists(path.join(pluginFolder, f, MANIFEST)) && + this.isExists(path.join(pluginFolder, f, SCRIPT)) + ) + }) + ?.map((g) => 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) => { + window.siyuanPluginScript = sc + eval(sc) + }) + } +} + +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/utils/otherlib/siyuanUtil.js b/src/utils/otherlib/siyuanUtil.js index 2bc2ae33..a722429b 100644 --- a/src/utils/otherlib/siyuanUtil.js +++ b/src/utils/otherlib/siyuanUtil.js @@ -34,24 +34,28 @@ const SIYUAN_THEME_PATH = path.join(SIYUAN_APPEARANCE_PATH, "themes") const ZHI_THEME_PATH = path.join(SIYUAN_THEME_PATH, "zhi") const ZHI_CJS_PATH = path.join(ZHI_THEME_PATH, "dist-cjs") -const ZHI_PLUGIN_FOLDER = "zhi-plugins" -const PLUGIN_FOLDER = "plugins" -const MANIFEST = "manifest.json" -const SCRIPT = "main.js" - -const OLD_VERSION_ZERO = "0.0.0" +const getCrossPlatformAppDataFolder = () => { + let configFilePath + if (window.process.platform === "darwin") { + configFilePath = path.join( + window.process.env.HOME, + "/Library/Application Support" + ) + } else if (window.process.platform === "win32") { + // Roaming包含在APPDATA中了 + configFilePath = window.process.env.APPDATA + } else if (window.process.platform === "linux") { + configFilePath = window.process.env.HOME + } + return configFilePath +} const siyuanUtil = { SIYUAN_CONF_PATH, SIYUAN_DATA_PATH, ZHI_CJS_PATH, - ZHI_PLUGIN_FOLDER, - PLUGIN_FOLDER, - OLD_VERSION_ZERO, - - MANIFEST, - SCRIPT + getCrossPlatformAppDataFolder } export default siyuanUtil diff --git a/src/utils/sysUtil.ts b/src/utils/sysUtil.ts index a107fa68..f0d66ca6 100644 --- a/src/utils/sysUtil.ts +++ b/src/utils/sysUtil.ts @@ -30,8 +30,6 @@ * @since 1.0.0 */ class SysUtil { - public getCrossPlatformAppDataFolder = () => { - } } const sysUtil = new SysUtil() diff --git a/typings/custom.d.ts b/typings/custom.d.ts index 5e687f38..8cb2853e 100644 --- a/typings/custom.d.ts +++ b/typings/custom.d.ts @@ -24,4 +24,29 @@ */ declare module "~/src/utils/otherlib/siyuanUtil" { + const ZHI_CJS_PATH: string + const SIYUAN_DATA_PATH: string + + function getCrossPlatformAppDataFolder() +} + +declare module "~/src/utils/otherlib/pluginSystemUtil" { + const ZHI_PLUGIN_FOLDER: string + const PLUGIN_FOLDER: string + const OLD_VERSION_ZERO: string + + const MANIFEST: string + const SCRIPT: string + + async function getPluginSystem(): Promise + + function getPluginSystemVersion(): string + + async function initPluginSystem() + + class HackPluginSystem { + async getManifest(manifest) + + async scanPlugins(pluginFolder) + } }