From e1bb32b137a56a8734a8ab445a00483932cd2754 Mon Sep 17 00:00:00 2001 From: purocean Date: Sat, 23 Oct 2021 03:48:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20PicGo=20=E5=9B=BE?= =?UTF-8?q?=E5=BA=8A=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + src/renderer/context/build-in-plugins.ts | 2 + src/renderer/plugins/image-hosting-picgo.ts | 119 ++++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 src/renderer/plugins/image-hosting-picgo.ts diff --git a/README.md b/README.md index 7caed84f..b1203bed 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ V3 核心目标是重构代码,提升应用健壮性、可拓展性、Markdown - 文档交叉链接跳转:支持在文档中引入其他文档,互相跳转 - 脚注功能:支持在文档中书写脚注 - 容器块:支持类似 VuePress 默认主题的自定义容器 +- 图床:支持 [PicGo](https://picgo.github.io/PicGo-Doc/) 图床 - 自定义插件:支持编写 JavaScript 插件拓展编辑器功能。插件放置在 `主目录/plugins` 中,文档待完善 ## 界面截图 diff --git a/src/renderer/context/build-in-plugins.ts b/src/renderer/context/build-in-plugins.ts index bb7ff8f8..e9354641 100644 --- a/src/renderer/context/build-in-plugins.ts +++ b/src/renderer/context/build-in-plugins.ts @@ -38,6 +38,7 @@ import markdownEcharts from '@fe/plugins/markdown-echarts' import markdownLuckysheet from '@fe/plugins/markdown-luckysheet' import markdownContainer from '@fe/plugins/markdown-container' import syncScroll from '@fe/plugins/sync-scroll' +import imageHostingPicgo from '@fe/plugins/image-hosting-picgo' export default [ documentHistoryStack, @@ -80,4 +81,5 @@ export default [ markdownLuckysheet, markdownContainer, syncScroll, + imageHostingPicgo, ] diff --git a/src/renderer/plugins/image-hosting-picgo.ts b/src/renderer/plugins/image-hosting-picgo.ts new file mode 100644 index 00000000..2a14d14f --- /dev/null +++ b/src/renderer/plugins/image-hosting-picgo.ts @@ -0,0 +1,119 @@ +import { Plugin, Ctx } from '@fe/context/plugin' +import { FLAG_DEMO } from '@fe/support/global-args' + +export default { + name: 'image-hosting-picgo', + register: (ctx: Ctx) => { + const logger = ctx.utils.getLogger('plugin.image-hosting-picgo') + const uploadActionName = 'plugin.image-hosting-picgo.upload' + const settingKeyUrl = 'plugin.image-hosting-picgo.server-url' + const settingKeyPaste = 'plugin.image-hosting-picgo.enable-paste-image' + + ctx.setting.tapSchema((schema) => { + schema.properties[settingKeyUrl] = { + title: 'PicGo 接口', + description: 'PicGo 默认接口地址:http://127.0.0.1:36677/upload', + type: 'string', + defaultValue: '', + pattern: '^(http://|https://|$)', + options: { + patternmessage: '必须以 http:// 开头', + inputAttributes: { placeholder: 'http://127.0.0.1:36677/upload' } + }, + } + + schema.properties[settingKeyPaste] = { + title: '粘贴图片使用 PicGo 图床', + type: 'boolean', + format: 'checkbox', + defaultValue: false, + } + }) + + ctx.action.registerAction({ + name: uploadActionName, + handler: async (file: File) => { + if (FLAG_DEMO) { + ctx.ui.useToast().show('warning', 'DEMO 模式下此功能不可用') + return URL.createObjectURL(file) + } + + const url = ctx.setting.getSettings()[settingKeyUrl] + + if (!url) { + ctx.ui.useToast().show('warning', '请先配置 PicGo 图床接口地址') + ctx.action.getActionHandler('status-bar.show-setting')() + throw new Error('未配置 PicGo 图床上传地址') + } + + ctx.ui.useToast().show('info', '上传中……') + + logger.debug('upload', url, file) + + const tmpFileName = 'picgo-tmp-file-' + file.name + + try { + const { data: { path } } = await ctx.api.writeTmpFile(tmpFileName, await ctx.utils.fileToBase64URL(file), true) + logger.debug('tmp file', path) + + const { result } = await ctx.api.proxyRequest( + url, + { + method: 'post', + body: JSON.stringify({ list: [path] }), + headers: { 'Content-Type': 'application/json' } + }, + ).then(r => r.json()) + + if (result.length > 0) { + return result[0] + } + } catch (error) { + ctx.ui.useToast().show('warning', '上传失败') + throw new Error('上传失败') + } finally { + ctx.api.deleteTmpFile(tmpFileName) + } + } + }) + + ctx.registerHook('ON_PASTE_IMAGE', async (file: File) => { + if (!ctx.setting.getSettings()[settingKeyPaste]) { + return false + } + + await insertImage(file) + + return true + }) + + async function insertImage (file: File) { + if (!ctx.store.state.currentFile) { + throw new Error('当前未打开文件') + } + const url = await ctx.action.getActionHandler(uploadActionName)(file) + ctx.editor.insert(`![图片](${url})\n`) + } + + function addImage () { + const input = window.document.createElement('input') + input.type = 'file' + input.multiple = true + input.onchange = async () => { + for (let i = 0; i < input.files!.length; i++) { + await insertImage(input.files![i]) + } + } + input.click() + } + + ctx.editor.whenEditorReady().then(({ editor }) => { + editor.addAction({ + id: 'plugin.image-hosting-picgo.add-image', + contextMenuGroupId: 'modification', + label: '上传图片(PicGo)', + run: addImage, + }) + }) + } +} as Plugin