Skip to content

Commit

Permalink
feat: #27 使用插件系统挂载菜单-优化插件系统集成
Browse files Browse the repository at this point in the history
  • Loading branch information
terwer committed Mar 4, 2023
1 parent 4eee75f commit 179a30c
Show file tree
Hide file tree
Showing 6 changed files with 287 additions and 20 deletions.
76 changes: 75 additions & 1 deletion src/apps/zhi/plugin-system/plugin-system-hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}
}

Expand Down
5 changes: 0 additions & 5 deletions src/utils/logUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
171 changes: 171 additions & 0 deletions src/utils/otherlib/pluginSystemUtil.js
Original file line number Diff line number Diff line change
@@ -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
28 changes: 16 additions & 12 deletions src/utils/otherlib/siyuanUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 0 additions & 2 deletions src/utils/sysUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@
* @since 1.0.0
*/
class SysUtil {
public getCrossPlatformAppDataFolder = () => {
}
}

const sysUtil = new SysUtil()
Expand Down
25 changes: 25 additions & 0 deletions typings/custom.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<any>

function getPluginSystemVersion(): string

async function initPluginSystem()

class HackPluginSystem {
async getManifest(manifest)

async scanPlugins(pluginFolder)
}
}

0 comments on commit 179a30c

Please sign in to comment.