diff --git a/src/adaptors/api/base/baseBlogApi.ts b/src/adaptors/api/base/baseBlogApi.ts index 2f1abd71..59ee5223 100644 --- a/src/adaptors/api/base/baseBlogApi.ts +++ b/src/adaptors/api/base/baseBlogApi.ts @@ -27,6 +27,7 @@ import { BlogApi, BlogConfig, Post } from "zhi-blog-api" import { AppInstance } from "~/src/appInstance.ts" import { createAppLogger, ILogger } from "~/src/utils/appLogger.ts" import { useProxy } from "~/src/composables/useProxy.ts" +import { BaseExtendApi } from "~/src/adaptors/base/baseExtendApi.ts" /** * API授权统一封装基类 @@ -39,6 +40,7 @@ export class BaseBlogApi extends BlogApi { protected logger: ILogger protected cfg: BlogConfig protected readonly proxyFetch: any + protected readonly baseExtendApi: BaseExtendApi /** * 初始化API授权适配器 @@ -51,14 +53,14 @@ export class BaseBlogApi extends BlogApi { this.cfg = cfg this.logger = createAppLogger("base-blog-api") + this.baseExtendApi = new BaseExtendApi(this) const { proxyFetch } = useProxy(cfg.middlewareUrl) this.proxyFetch = proxyFetch } public async preEditPost(post: Post, id?: string, publishCfg?: any): Promise { - this.logger.info("未处理,原样返回。如需处理,请在子类重写") - return post + return await this.baseExtendApi.preEditPost(post, id, publishCfg) } // ================ diff --git a/src/adaptors/api/cnblogs/cnblogsApiAdaptor.ts b/src/adaptors/api/cnblogs/cnblogsApiAdaptor.ts index 8cb08d3e..71e811e3 100644 --- a/src/adaptors/api/cnblogs/cnblogsApiAdaptor.ts +++ b/src/adaptors/api/cnblogs/cnblogsApiAdaptor.ts @@ -23,13 +23,12 @@ * questions. */ -import {MediaObject, Post, UserBlog} from "zhi-blog-api" +import { Post, UserBlog } from "zhi-blog-api" import { CnblogsConfig } from "~/src/adaptors/api/cnblogs/cnblogsConfig.ts" import { AppInstance } from "~/src/appInstance.ts" import { createAppLogger } from "~/src/utils/appLogger.ts" import { CnblogsConstants } from "~/src/adaptors/api/cnblogs/cnblogsConstants.ts" import { MetaweblogBlogApiAdaptor } from "~/src/adaptors/api/base/metaweblog/metaweblogBlogApiAdaptor.ts" -import {usePicgoBridge} from "~/src/composables/usePicgoBridge.ts"; /** * 博客园 API 适配器 @@ -64,35 +63,6 @@ class CnblogsApiAdaptor extends MetaweblogBlogApiAdaptor { return result } - public async preEditPost(post: Post, id?: string, publishCfg?: any): Promise { - // const pubCfg = publishCfg as IPublishCfg - // 找到所有的图片 - const { getImageItemsFromMd } = usePicgoBridge() - const images = await getImageItemsFromMd(id, post.markdown) - if (images.length === 0) { - this.logger.info("未找到图片,不处理") - return post - } - // 批量处理图片上传 - this.logger.info(`找到${images.length}张图片,开始上传`) - - for (const image of images) { - const imageBlob = await this.readFileToBlob(image.url) - this.logger.debug("read blob from image", { imageBlob }) - const file = new File([imageBlob], image.name, { type: imageBlob.type, lastModified: Date.now() }) - this.logger.debug("convert blob to file", { imageBlob }) - - const mediaObject = new MediaObject(image.name, imageBlob.type, file as any) - const attachResult = await this.newMediaObject(mediaObject) - this.logger.debug("attachResult =>", attachResult) - throw new Error("开发中") - } - - this.logger.info("图片全部上传完成") - return post - } - - public async newPost(post: Post, publish?: boolean): Promise { // 设置markdown分类 post = this.assignMdCategory(post) diff --git a/src/adaptors/base/baseExtendApi.ts b/src/adaptors/base/baseExtendApi.ts new file mode 100644 index 00000000..321b78e0 --- /dev/null +++ b/src/adaptors/base/baseExtendApi.ts @@ -0,0 +1,101 @@ +/* + * 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 { IBlogApi } from "zhi-blog-api/dist/lib/IBlogApi" +import { IWebApi } from "zhi-blog-api/dist/lib/IWebApi" +import { BaseBlogApi } from "~/src/adaptors/api/base/baseBlogApi.ts" +import { BaseWebApi } from "~/src/adaptors/web/base/baseWebApi.ts" +import { MediaObject, Post, WebApi } from "zhi-blog-api" +import { createAppLogger, ILogger } from "~/src/utils/appLogger.ts" +import { CommonBlogConfig } from "~/src/adaptors/api/base/commonBlogConfig.ts" +import { LuteUtil } from "~/src/utils/luteUtil.ts" +import { usePicgoBridge } from "~/src/composables/usePicgoBridge.ts" +import { base64ToBuffer, remoteImageToBase64Info } from "~/src/utils/polyfillUtils.ts" + +/** + * 各种模式共享的扩展基类 + * + * @author terwer + * @since 1.8.0 + */ +class BaseExtendApi extends WebApi implements IBlogApi, IWebApi { + private readonly logger: ILogger + private readonly api: BaseBlogApi | BaseWebApi + protected readonly picgoBridge: any + + constructor(api: BaseBlogApi | BaseWebApi) { + super() + this.logger = createAppLogger("base-extend-api") + this.api = api + + this.picgoBridge = usePicgoBridge() + } + + public async preEditPost(post: Post, id?: string, publishCfg?: any): Promise { + const cfg: CommonBlogConfig = publishCfg.cfg + + // const unsupportedPicturePlatform = ["custom_Zhihu","common_notion"],判断key包含zhihu、notion,custom_Zhihu 或者 /custom_Zhihu-\w+/ + // PictureStoreTypeEnum.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 + } + // 批量处理图片上传 + this.logger.info(`找到${images.length}张图片,开始上传`) + for (const image of images) { + const imageUrl = image.url + const base64Info = await remoteImageToBase64Info(imageUrl) + 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.newMediaObject(mediaObject) + this.logger.debug("attachResult =>", attachResult) + throw new Error("开发中") + } + + this.logger.info("图片全部上传完成") + return post + } +} + +export { BaseExtendApi } diff --git a/src/adaptors/web/base/baseWebApi.ts b/src/adaptors/web/base/baseWebApi.ts index 9e5fd501..87d1da7f 100644 --- a/src/adaptors/web/base/baseWebApi.ts +++ b/src/adaptors/web/base/baseWebApi.ts @@ -26,6 +26,7 @@ import { Attachment, ElectronCookie, MediaObject, Post, WebApi, WebConfig } from import { AppInstance } from "~/src/appInstance.ts" import { createAppLogger, ILogger } from "~/src/utils/appLogger.ts" import { useProxy } from "~/src/composables/useProxy.ts" +import { BaseExtendApi } from "~/src/adaptors/base/baseExtendApi.ts" /** * 网页授权统一封装基类 @@ -38,6 +39,7 @@ class BaseWebApi extends WebApi { protected logger: ILogger protected cfg: WebConfig protected readonly proxyFetch: any + protected readonly baseExtendApi: BaseExtendApi /** * 初始化网页授权 API 适配器 @@ -50,6 +52,7 @@ class BaseWebApi extends WebApi { this.cfg = cfg this.logger = createAppLogger("base-web-api") + this.baseExtendApi = new BaseExtendApi(this) const { proxyFetch } = useProxy(cfg.middlewareUrl) this.proxyFetch = proxyFetch @@ -66,8 +69,7 @@ class BaseWebApi extends WebApi { } public async preEditPost(post: Post, id?: string, publishCfg?: any): Promise { - this.logger.info("未处理,原样返回。如需处理,请在子类重写") - return post + return await this.baseExtendApi.preEditPost(post, id, publishCfg) } // 兼容的方法 diff --git a/src/adaptors/web/zhihu/zhihuWebAdaptor.ts b/src/adaptors/web/zhihu/zhihuWebAdaptor.ts index 2c2256f3..534af2af 100644 --- a/src/adaptors/web/zhihu/zhihuWebAdaptor.ts +++ b/src/adaptors/web/zhihu/zhihuWebAdaptor.ts @@ -24,12 +24,9 @@ */ import { BaseWebApi } from "~/src/adaptors/web/base/baseWebApi.ts" -import { MediaObject, Post, UserBlog } from "zhi-blog-api" +import { Post, UserBlog } from "zhi-blog-api" import * as cheerio from "cheerio" import { JsonUtil, StrUtil } from "zhi-common" -import { usePicgoBridge } from "~/src/composables/usePicgoBridge.ts" -import { IPublishCfg } from "~/src/types/IPublishCfg.ts" -import { base64ToBuffer, remoteImageToBase64Info } from "~/src/utils/polyfillUtils.ts" /** * 知乎网页授权适配器 @@ -98,36 +95,6 @@ class ZhihuWebAdaptor extends BaseWebApi { return result } - public async preEditPost(post: Post, id?: string, publishCfg?: any): Promise { - const pubCfg = publishCfg as IPublishCfg - const cfg = pubCfg.cfg - - const { getImageItemsFromMd } = usePicgoBridge() - - // 找到所有的图片 - const images = await getImageItemsFromMd(id, post.markdown) - if (images.length === 0) { - this.logger.info("未找到图片,不处理") - return post - } - // 批量处理图片上传 - this.logger.info(`找到${images.length}张图片,开始上传`) - - for (const image of images) { - const imageUrl = image.url - const base64Info = await remoteImageToBase64Info(imageUrl) - 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.newMediaObject(mediaObject) - this.logger.debug("attachResult =>", attachResult) - throw new Error("开发中") - } - - this.logger.info("图片全部上传完成") - return post - } - public async addPost(post: Post) { const params = JSON.stringify({ title: post.title, @@ -258,6 +225,7 @@ class ZhihuWebAdaptor extends BaseWebApi { public async uploadFile(file: File): Promise { this.logger.debug("zhihu start uploadFile =>", file) + throw new Error("开发中=>zhihu uploadFile") return {} } } diff --git a/src/composables/usePublish.ts b/src/composables/usePublish.ts index 86ba9ff8..6f8e0326 100644 --- a/src/composables/usePublish.ts +++ b/src/composables/usePublish.ts @@ -39,7 +39,6 @@ import { IPublishCfg } from "~/src/types/IPublishCfg.ts" import { usePublishConfig } from "~/src/composables/usePublishConfig.ts" import { ElMessage } from "element-plus" import { usePicgoBridge } from "~/src/composables/usePicgoBridge.ts" -import { LuteUtil } from "~/src/utils/luteUtil.ts" /** * 通用发布组件 @@ -56,7 +55,6 @@ const usePublish = () => { const { updateSetting } = useSettingStore() const { kernelApi, blogApi } = useSiyuanApi() const { getPublishApi } = usePublishConfig() - const { handlePicgo } = usePicgoBridge() // datas const singleFormData = reactive({ @@ -113,11 +111,6 @@ const usePublish = () => { // 分配文章属性 - 初始化和发布都会调用 post = await assignAttrs(post, id, publishCfg) - // 全局正文预处理 - 仅在发布的时候调用 - logger.debug(`before preHandlePost, isAdd ${singleFormData.isAdd}, doc=>`, toRaw(post)) - post = await preHandlePost(post, id, publishCfg) - logger.debug(`after preHandlePost, post=>`, toRaw(post)) - // =================================== // 文章处理结束 // =================================== @@ -125,7 +118,7 @@ const usePublish = () => { // 初始化API const api = await getPublishApi(key, cfg) - // 平台相关的预处理 - 仅在发布的时候调用 + // 平台相关的正文预处理 - 仅在发布的时候调用 logger.debug(`before preEditPost, isAdd ${singleFormData.isAdd}, post=>`, toRaw(post)) post = await api.preEditPost(post, id, publishCfg) logger.debug(`after preEditPost, post=>`, toRaw(post)) @@ -311,26 +304,6 @@ const usePublish = () => { return isAbsoluteUrl ? previewUrl : `${cfg?.home ?? ""}${previewUrl}` } - /** - * 文章预处理 - 仅在发布的时候调用 - * - * @param post - 文章对象 - * @param id - 思源笔记文档ID - * @param publishCfg - 发布配置 - */ - const preHandlePost = async (post: Post, id: string, publishCfg: IPublishCfg): Promise => { - const cfg: CommonBlogConfig = publishCfg.cfg - - // 图片替换 - logger.debug("开始图片处理, post =>", { post }) - post.markdown = await handlePicgo(id, post.markdown) - // 利用 lute 把 md 转换成 html - post.html = LuteUtil.mdToHtml(post.markdown) - logger.debug("图片处理完毕, post.markdown =>", { md: post.markdown }) - - return post - } - // const assignCompareValue = (title1: string, title2: string) => (title1.length > title2.length ? title1 : title2) /**