当前位置: 代码迷 >> 综合 >> typora+picgo实现本地自动转储图片base64值
  详细解决方案

typora+picgo实现本地自动转储图片base64值

热度:38   发布时间:2023-12-01 10:54:59.0

Typora是一款非常优秀的markdown编辑器,他自带的图片上传服务以及其他各种功能方便了很多。但是因为使用picgo实现的图片上传服务依赖于网络,哪怕是本地图床转储,这不利于离线环境的跨设备传输。有时候我们要给别人拷贝一份md文件,却因为对方链接不到自己的图床而苦恼,于是我尝试了在md文件中用data协议嵌入图片数据的方式,尝试后发现可以成功。

结合utools的图片压缩插件和编码解码插件,使用了一段时间,但是每次都有截图,复制到utools压缩,编码,还是有些麻烦。后来想着魔改一个picgo的插件,让它直接返回data协议格式的数据。

魔改picgo的插件web-uploader

web-uploader是picgo-core的上传插件,主要用来支持picgo不支持的一些OSS服务。

首先在Typora中安装picgo-core,具体不在说,网上都有教程。另外,picgo-core插件运行依赖于npm,所以还得装node.js,并添加至环境变量。这不是本文 的重点。

然后进入picgo程序的目录(因为没有添加到环境变量中,所以得去其目录下面运行)%APPDATA%/Typora/picgo/win64。在这里打开控制台窗口,输入

.\picgo install web-uploader

这样picgo就会安装插件web-uploader,插件安装的目录在%USERPROFILE%/.picgo/node_modules,该插件的主要功能代码在picgo-plugin-web-uploader\src\index.js中。我们对其进行修改,其代码原来的功能大概就是读取配置文件的信息,获取图片数据,构造POST的数据包,发往OSS服务,获取响应包,读取返回的图片链接,写入picgo提供的接口中,我们去掉数据发送,改成直接返回base64数据即可

module.exports = (ctx) => {
    const register = () => {
    ctx.helper.uploader.register('web-uploader', {
    handle,name: '自定义Web图床',})}const handle = async function (ctx) {
    try {
    let imgList = ctx.outputfor (let i in imgList) {
    let image = imgList[i].base64Imageif (!image && imgList[i].buffer) {
    image = imgList[i].buffer.toString('base64')}let body = await ((ext,base64)=>{
    return "data://image/"+ext.substr(1)+";base64,"+base64})(imgList[i].extname,image)delete imgList[i].base64Imagedelete imgList[i].bufferif(body){
    imgList[i]['imgUrl'] =body}else{
    ctx.emit('notification', {
    title: '数据异常',//JSON解析失败body: '请检查'})}}} catch (err) {
    ctx.emit('notification', {
    title: '上传失败',body: JSON.stringify(err)})}}return {
    uploader: 'web-uploader',// transformer: 'web-uploader',// config: config,register}
}

修改配置文件

picgo默认使用的上传服务是其自带的sms上传服务,所以需要修改配置文件,这个配置文件可以在Typora里面打开,也可以在%USERPROFILE%/.picgo/config.json中直接打开。修改如下,这里展示的是只有web-uploader的情况,我们的代码里面没有读取配置,所以web-uploader的配置项空着,picgoBed["uploader"]="web-uploader"声明使用web-uploader,这里会默认有一个配置项叫picgoBed["current"]="sms",删掉就好

{
    "picgoPlugins": {
    "picgo-plugin-web-uploader": true},"picBed": {
    "uploader": "web-uploader","web-uploader": {
    }}
}

修改Typora的处理代码

经过上面的修改,图片上传后picgo就会返回图片的base64数据

但是直接在Typora中上传会报错fail to parse result image path from:后面跟的是picgo的运行结果。根据Typora的官方文档,它是只支持https和http协议的返回结果的。我们打开开发者工具,发现picgo的结果会被一个叫frame.js文件输出,我们在该文件(最新版的Typora中位于resources/appsrc/window/frame.js)中全局搜索该错误信息,定位到以下代码

            )).then(t=>{
    var i = "picgo-app" == n ? t : N(t, n);return i.length == e.length ? Promise.resolve(i) : (console.log(t),Promise.reject("fail to parse result image path from: " + t))})

可以看到,执行正确则使用Promise.resolve(i)解析结果,否则就报错。而结果i来自与N(t,n)函数的执行。t在这里是picgo的执行输出,就上图的内容,n是使用的命令行cmdline,我们定位到N函数

        function N(e, t) {
    //e是picgo的结果,t是使用的命令return "picgo-app" == t ? function(e) {
    try {
    var t = JSON.parse(e);return t.success ? t.result : []} catch (e) {
    return []}}(e) : function(e) {
    for (var t = e.split(/\r?\n/), n = [], i = t.length - 1; i >= 0; i--) {
    var r = t[i].trim();if (r)if (/^(https?|ftp|file):\//.exec(r))//重点在这里,这里对结果每行进行判断,如果是`http|https|file|ftp`协议就将该行写入数组,这里没有data协议,所以会报错,我们在这里加上data协议。正则表达式改成// ^(https?|ftp|file|data):\///这里匹配的是data:/,所以我们在picgo的插件中加上的是`data://`,而不是只有`data:`n.unshift(r);else if (/^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}\/.*$/.exec(r))n.unshift("http://" + r);else if (n.length)break}return n}(e)}

修改后保存。

大功告成

修改后保存。

大功告成

  相关解决方案