自制 Markdown 编辑器增加图床功能

原创:coding01 原文链接:https://juejin.im/post/5d73c9b45188255d3d29b9e3


使用 markdown,最方便的莫过于利用图床功能,将图片保存到云端,然后转换成![]() 结构。避免担心图片存在某一台电脑设备上,这样就可以把文章内容复制到任何一个地方和平台,继续无缝的写作下去。

今天,我们就来说一说怎么在自建markdown 编辑器上,增加图床功能。

我们的主角是:「PicGo」。

安装 PicGo

npm install picgo --save

复制代码

配置 PicGo

picgo 的默认配置文件为~/.picgo/config.json。其中~为用户目录。不同系统的用户目录不太一样。

linux和macOS均为~/.picgo/config.json。

windows则为 C:\Users\你的用户名.picgo\config.json

当然也可以根据自己的需要,将配置文件放在不同路径下,主要参考 picgo 官网描述来配置即可,下面是是 upyun 配置内容。

{

  "picBed": {

    "current": "upyun",

    "uploader": "upyun",

    "upyun": {

         "bucket": "coding", // 存储空间名,及你的服务名

                  "operator": "coding01", // 操作员

                  "password": "**********", // 密码

                  "options": "", // 针对图片的一些后缀处理参数

                  "path": "blog/", // 自定义存储路径,比如img/

                  "url": "http://***.****.com"

    }

  },

  "picgoPlugins": {}

}


复制代码

如果没配置,则可以使用默认的 sm.ms图床。

触发上传图床

在写作过程中,触发上传比较简单的办法,我觉得有两种方法比较便捷,一种是直接复制粘贴图片,另一种就是拖拽图片到编辑器。

今天重点来说说怎么直接复制粘贴上传图片。

剪切板

首先,必须要借助 electron 的剪切板读取复制的图片信息,clipboard 操作剪切板功能也很简单,直接看代码:

const { clipboard } = require('electron')


// 获取剪切板图片,type String (optional) - Can be selection or clipboard. selection is only

available on Linux.

// 返回NativeImage- 剪贴板中的图像内容。


clipboard.readImage([type])

复制代码

具体参考 electron clipboard electronjs.org/docs/api/cl…

粘贴

我们只需要「Ctrl + Shift +

V」粘贴操作,编辑器会判断,如果剪切板上是图片时,我们就执行上传操作。

全局快捷键

我们先用 electron 提供的「全局快捷键」看看效果。

// 注册一个 'CommandOrControl+X' 的全局快捷键

  const ret =globalShortcut.register('CommandOrControl+v', () => {

    console.log('CommandOrControl+v is pressed')

    //上传剪贴板里的第一张图片(上传时会将格式转为png)

    let callback = picgo.upload()

    console.log(callback)

  })


  if (!ret) {

    console.log('registration failed')

  }


  //检查快捷键是否注册成功

  console.log(globalShortcut.isRegistered('CommandOrControl+v'))

复制代码

看看打印出来的 log,这里也能看出默认上传图床为 SM.MS:

除了使用「全局快捷键」,我们还可以使用「本地快捷键」方式:

本地快捷键

使用「本地快捷键」之前,需要创建菜单和菜单项,通过菜单项绑定对应的快捷键。

mainMenu(mainWindow);


// 设置快捷键和对应的动作

{

    label:'上传图片',

    accelerator: process.platform==='darwin' ? 'Command+Shift+V' : 'Ctrl+Shift+V',

    click: () => {

        mainWindow.webContents.send('uploadImage');

    }

},

复制代码

通过 mainWindow.webContents.send 将快捷键动作推送给 ipcRenderer,接着可以在 renderer 中创建监听事件:

ipcRenderer.on('uploadImage',

(event) => {

  console.log('messageBus CommandOrControl+v is pressed')

  ipcRenderer.send('uploadImage');

})

复制代码

获取剪切板的图片推荐放到 ipcMain上去做,而且上传图片也是耗时事件。所以在 ipcMain 创建uploadImage 事件:

ipcMain.on('uploadImage',function()

{

  let img = clipboard.readImage()

  if (!img.isEmpty()) {

    let callback = picgo.upload()

    console.log(callback)

  }

})

复制代码

好了,到此为止,我们执行,通过快捷键「Command+Shift+V」看看打印 log:

除了以上两种方式外,我们还有第三种使用快捷键的方法,就是利用 ace 编辑器自带的 Command 功能

ace Command

在EditorPage 的editorInit(editor) 初始化方法中增加一个 Command,并绑定对应的快捷键:

editor.commands.addCommand({

    name:'上传图片',

    bindKey: {win: 'Ctrl-Shift-M',  mac:'Command-Shift-M'},

    exec: function(editor)

{

        console.log('上传图片');

        messageBus.uploadImage();

    },

    readOnly: true // false if this command should not apply in readOnly mode

});

复制代码

同样的,创建 messageBus.uploadImage()

uploadImage() {

  console.log('messageBus ACE Command is pressed')

  ipcRenderer.send('uploadImage');

}

复制代码

综上,个人偏向使用 ace

Command 方法,把上传图片的功能局限到编辑器范畴内,也符合功能的使用。

到此,我们初步做到将图片上传到默认的sm.ms 上了,接下来就是显示的问题了。

上传图床后显示

首先看看 picgo 提供给我们几个和上传有关的状态函数:

// 图床上传进度

picgo.on('uploadProgress',

progress => {

  console.log('uploadProgress')

  console.log(progress)

})


picgo.on('beforeTransform',

ctx => {

  console.log('beforeTransform')

  console.log(ctx.input) // ['/xxx/xxx.jpg']

})


picgo.on('beforeUpload',

ctx => {

  console.log('beforeUpload')

  console.log(ctx.output) // [{base64Image, fileName, width, height, extname }]

})


picgo.on('afterUpload',

ctx => {

  console.log('afterUpload')

  console.log(ctx.output) //[{fileName, width, height, extname, imgUrl}] <-注意有imgUrl了。

})


picgo.on('finished',

ctx => {

  console.log('finished')

  console.log(ctx.output) //[{fileName, width, height, extname, imgUrl}] <-注意有imgUrl了。

})


picgo.on('failed', error => {

  console.log('failed')

  console.log(error) //错误信息

})


picgo.on('notification',

notice => {

  console.log('notification')

  console.log(notice) // { title,body, text? }

})

复制代码

其中,我们需要用到的有:uploadProgress、afterUpload、failed、notification。

如果上传错误的话,可以通过多方面来判断:1.可以利用 progress = -1;2. error;3. notification 也会输出错误提示和内容,这里推荐直接使用notification。

我们先看 afterUpload 返回的数据,需要将 imgUrl 内容填充给编辑器。

picgo.on('afterUpload',

ctx => {

  console.log('afterUpload')

  console.log(ctx.output.imgUrl) //[{fileName, width, height, extname, imgUrl}] <-注意有imgUrl了。

  //将 imgUrl 内容发给编辑器。

  mainWindow.webContents.send('imgUrl', ctx.output[0].imgUrl);

})

复制代码

接收端直接接收该事件,并 emit 给 vue 页面:

// renderer/main.js

ipcRenderer.on('imgUrl',

(event, imgUrl) => {

  messageBus.$emit('imgUrl', imgUrl);

})


// EditorPage.vue

messageBus.$on('imgUrl', (imgUrl) => {

    console.log(`imgUrl${imgUrl}`);

    //格式化为markdown 格式,insert到编辑器中

    this.editor.editor.insert(`![](${imgUrl})`);

});

复制代码

直接看结果

总结

接下来还有很多东西需要做,如:

增加各个图床 (七牛、又拍云等)的配置设置;

将上传图床的功能封装;

增加拖拽图片上传图床功能;

增加图片上传进度和成功与否的提示等。

当然,我们的目标是在写出满足自己写作需要的 markdown 编辑器的同时,也学习如何使用 Electron 框架。

学会了

electron 菜单项 electronjs.org/docs/api/me…

electron「本地快捷键」和「全局快捷键」electronjs.org/docs/tutori…

electron 剪贴板 electronjs.org/docs/api/cl…

「Markdown编辑器」系列

利用Electron简单撸一个Markdown编辑器 (1) mp.weixin.qq.com/s/lXESP6Sa0…

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容