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

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

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

咱们的主角是:「PicGo」。web

安装 PicGo

npm install picgo --save
复制代码

配置 PicGo

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

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

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

固然也能够根据本身的须要,将配置文件放在不一样路径下,主要参考 picgo 官网描述来配置便可,下面是是 upyun 配置内容。api

{
  "picBed": {
    "current": "upyun",
    "uploader": "upyun",
    "upyun": {
    	"bucket": "coding", // 存储空间名,及你的服务名
	  	"operator": "coding01", // 操做员
	  	"password": "**********", // 密码
	  	"options": "", // 针对图片的一些后缀处理参数
	  	"path": "blog/", // 自定义存储路径,好比img/
	  	"url": "http://***.****.com"
    }
  },
  "picgoPlugins": {}
}

复制代码

若是没配置,则可使用默认的 sm.ms 图床。bash

触发上传图床

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

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

剪切板

首先,必需要借助 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? }
})
复制代码

其中,咱们须要用到的有:uploadProgressafterUploadfailednotification

若是上传错误的话,能够经过多方面来判断: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})`);
});
复制代码

直接看结果

总结

接下来还有不少东西须要作,如:

  1. 增长各个图床 (七牛、又拍云等)的配置设置;
  2. 将上传图床的功能封装;
  3. 增长拖拽图片上传图床功能;
  4. 增长图片上传进度和成功与否的提示等。

固然,咱们的目标是在写出知足本身写做须要的 markdown 编辑器的同时,也学习如何使用 Electron 框架。

学会了

  1. electron 菜单项 electronjs.org/docs/api/me…
  2. electron「本地快捷键」和「全局快捷键」electronjs.org/docs/tutori…
  3. electron 剪贴板 electronjs.org/docs/api/cl…

「Markdown编辑器」系列

  1. 利用Electron简单撸一个Markdown编辑器 (1) mp.weixin.qq.com/s/lXESP6Sa0…
相关文章
相关标签/搜索