From 090425ccec393ef0f582b89e91f846d35c850b80 Mon Sep 17 00:00:00 2001 From: terwer Date: Mon, 14 Aug 2023 12:39:40 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=85=BC=E5=AE=B9=E5=B9=B3=E5=8F=B0?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E4=B8=8A=E4=BC=A0-Picgo=20=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/adaptors/api/hexo/hexoApiAdaptor.ts | 7 +- src/adaptors/base/baseExtendApi.ts | 102 +++++++++++++++--------- src/utils/siyuanUtils.ts | 46 +++++++++++ 3 files changed, 117 insertions(+), 38 deletions(-) create mode 100644 src/utils/siyuanUtils.ts diff --git a/src/adaptors/api/hexo/hexoApiAdaptor.ts b/src/adaptors/api/hexo/hexoApiAdaptor.ts index 90efb087..9f76aaa0 100644 --- a/src/adaptors/api/hexo/hexoApiAdaptor.ts +++ b/src/adaptors/api/hexo/hexoApiAdaptor.ts @@ -38,7 +38,12 @@ import { HexoYamlConverterAdaptor } from "~/src/adaptors/api/hexo/hexoYamlConver * @since 0.8.1 */ class HexoApiAdaptor extends CommonGithubApiAdaptor { - public async preEditPost(post: Post, dynCfg: any): Promise { + public async preEditPost(post: Post, id?: string, publishCfg?: any): Promise { + // 调用父类预处理 + await super.preEditPost(post, id, publishCfg) + this.logger.info("handled preEditPost with parent") + + // 处理 YAML const cfg = this.cfg as CommonGithubConfig const yamlApi: YamlConvertAdaptor = new HexoYamlConverterAdaptor() const yamlObj: YamlFormatObj = yamlApi.convertToYaml(post, cfg) diff --git a/src/adaptors/base/baseExtendApi.ts b/src/adaptors/base/baseExtendApi.ts index 998918b7..28e7bd90 100644 --- a/src/adaptors/base/baseExtendApi.ts +++ b/src/adaptors/base/baseExtendApi.ts @@ -34,6 +34,10 @@ import { usePicgoBridge } from "~/src/composables/usePicgoBridge.ts" import { base64ToBuffer, remoteImageToBase64Info, toBase64Info } from "~/src/utils/polyfillUtils.ts" import { StrUtil } from "zhi-common" import { useSiyuanDevice } from "~/src/composables/useSiyuanDevice.ts" +import { isFileExists } from "~/src/utils/siyuanUtils.ts" +import { useSiyuanApi } from "~/src/composables/useSiyuanApi.ts" +import { SiyuanKernelApi } from "zhi-siyuan-api" +import { DynamicConfig } from "~/src/platforms/dynamicConfig.ts" /** * 各种模式共享的扩展基类 @@ -46,6 +50,7 @@ class BaseExtendApi extends WebApi implements IBlogApi, IWebApi { private readonly api: BaseBlogApi | BaseWebApi protected readonly picgoBridge: any private readonly isSiyuanOrSiyuanNewWin: boolean + private readonly kernelApi: SiyuanKernelApi constructor(api: BaseBlogApi | BaseWebApi) { super() @@ -55,58 +60,81 @@ class BaseExtendApi extends WebApi implements IBlogApi, IWebApi { this.picgoBridge = usePicgoBridge() const { isInSiyuanOrSiyuanNewWin } = useSiyuanDevice() this.isSiyuanOrSiyuanNewWin = isInSiyuanOrSiyuanNewWin() + const { kernelApi } = useSiyuanApi() + this.kernelApi = kernelApi } public async preEditPost(post: Post, id?: string, publishCfg?: any): Promise { const cfg: BlogConfig = publishCfg.cfg + const dynCfg: DynamicConfig = publishCfg.dynCfg - // const unsupportedPicturePlatform = ["custom_Zhihu","common_notion"],判断key包含zhihu、notion,custom_Zhihu 或者 /custom_Zhihu-\w+/ - // PictureStoreTypeEnum.Picgo 先检测是否安装了Picgo插件,如果设置了图片存储方式 PicGO图床 类型就使用 PicGO图床 上传 - // PictureStoreTypeEnum.Platform or key in unsupportedPicturePlatform 如果设置了图片存储方式为 平台存储 类型或者 知乎、Notion等不兼容链接方式的平台,就使用 平台特定的存储方式 上传 - // PictureStoreTypeEnum.Default 默认不处理,即使用 思源笔记图床 上传 - - // ========================== - // 使用 PicGO上传图片 - // ========================== - // 图片替换 - this.logger.debug("开始图片处理, post =>", { post }) - post.markdown = await this.picgoBridge.handlePicgo(id, post.markdown) - // 利用 lute 把 md 转换成 html - post.html = LuteUtil.mdToHtml(post.markdown) - this.logger.debug("图片处理完毕, post.markdown =>", { md: post.markdown }) - - // ========================== - // 使用平台上传图片 - // ========================== - // 找到所有的图片 - const images = await this.picgoBridge.getImageItemsFromMd(id, post.markdown) - if (images.length === 0) { - this.logger.info("未找到图片,不处理") - return post + // 判断key包含zhihu、notion,custom_Zhihu 或者 /custom_Zhihu-\w+/ + const unsupportedPicturePlatform: string[] = ["custom_Zhihu", "custom_Notion"] + const isPicgoInstalled: boolean = await this.checkPicgoInstalled() + if (!isPicgoInstalled) { + this.logger.warn("未安装 PicGO 插件,将使用平台上传图片") } - // 批量处理图片上传 - this.logger.info(`找到${images.length}张图片,开始上传`) - const urlMap = {} - for (const image of images) { - const imageUrl = image.url - const base64Info = await this.readFileToBase64(imageUrl, cfg) - const bits = base64ToBuffer(base64Info.imageBase64) - const mediaObject = new MediaObject(image.name, base64Info.mimeType, bits) - this.logger.debug("before upload, mediaObject =>", mediaObject) - const attachResult = await this.api.newMediaObject(mediaObject) - this.logger.debug("attachResult =>", attachResult) - if (attachResult && attachResult.url) { - urlMap[image.originUrl] = attachResult.url + // 注意如果 platformKey=custom_Zhihu 或者 custom_Zhihu-xxx custom_Notion-xxx 也算 可以参考 /custom_Zhihu-\w+/ + const notSupportPictureUrl: boolean = unsupportedPicturePlatform.some((platform) => { + const regex = new RegExp(`${platform}(-\\w+)?`) + return regex.test(dynCfg.platformKey) + }) + if (notSupportPictureUrl) { + this.logger.warn("该平台不支持 Picgo 插件,将使用平台上传图片") + } + const usePicgo: boolean = isPicgoInstalled && !notSupportPictureUrl + + if (usePicgo) { + // ========================== + // 使用 PicGO上传图片 + // ========================== + // 图片替换 + this.logger.debug("使用 PicGO上传图片") + this.logger.debug("开始图片处理, post =>", { post }) + post.markdown = await this.picgoBridge.handlePicgo(id, post.markdown) + // 利用 lute 把 md 转换成 html + post.html = LuteUtil.mdToHtml(post.markdown) + this.logger.debug("图片处理完毕, post.markdown =>", { md: post.markdown }) + } else { + // ========================== + // 使用平台上传图片 + // ========================== + this.logger.debug("使用平台上传图片") + // 找到所有的图片 + const images = await this.picgoBridge.getImageItemsFromMd(id, post.markdown) + if (images.length === 0) { + this.logger.info("未找到图片,不处理") + return post + } + // 批量处理图片上传 + this.logger.info(`找到${images.length}张图片,开始上传`) + const urlMap = {} + for (const image of images) { + const imageUrl = image.url + const base64Info = await this.readFileToBase64(imageUrl, cfg) + const bits = base64ToBuffer(base64Info.imageBase64) + const mediaObject = new MediaObject(image.name, base64Info.mimeType, bits) + this.logger.debug("before upload, mediaObject =>", mediaObject) + const attachResult = await this.api.newMediaObject(mediaObject) + this.logger.debug("attachResult =>", attachResult) + if (attachResult && attachResult.url) { + urlMap[image.originUrl] = attachResult.url + } } + this.logger.info("平台图片全部上传完成,urlMap =>", urlMap) } - this.logger.info("图片全部上传完成,urlMap =>", urlMap) return post } // ================ // private methods // ================ + private async checkPicgoInstalled() { + // 检测是否安装 picgo 插件 + return await isFileExists(this.kernelApi, "/data/plugins/siyuan-plugin-picgo/plugin.json", "text") + } + private async readFileToBase64(url: string, cfg: BlogConfig): Promise { let base64Info: any if (this.isSiyuanOrSiyuanNewWin) { diff --git a/src/utils/siyuanUtils.ts b/src/utils/siyuanUtils.ts new file mode 100644 index 00000000..80f6385e --- /dev/null +++ b/src/utils/siyuanUtils.ts @@ -0,0 +1,46 @@ +/* + * 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 { SiyuanKernelApi } from "zhi-siyuan-api" +import { StrUtil } from "zhi-common" + +/** + * 文件是否存在 + * + * @param kernelApi - kernelApi + * @param p - 路径 + * @param type - 类型 + */ +export const isFileExists = async (kernelApi: SiyuanKernelApi, p: string, type: "text" | "json") => { + try { + const res = await kernelApi.getFile(p, type) + if (type === "text") { + return !StrUtil.isEmptyString(res) + } + return res !== null + } catch { + return false + } +}