前言

一直以来,我都很少在文章中加插图。因为每加一张插图,我都需要先把图片上传到七牛,然后才能获取外链插入文章。

之前写 Markdown 一直是用的 Sublime,直到 Vscode 最近一次更新有了 Tabs 之后,便开始尝试在工作中使用。与最初的预览版相比进步蛮大的,能看到很多 VS 的影子。之前也用过一段时间 Atom,虽然界面挺喜欢,但始终没有原生客户端的流畅感。到底客户端还是微软的强项,Vscode 这方面舒服多了,启动与大文件编辑都不比 Sublime 差。

Vscode 是基于浏览器内核的跨平台编辑器,底层代码大部分都是 TypeScript,当然最终还是会编译为 javascript。这样对于一个前端而言就倍感亲切了,可以轻易的使用自己吃饭的语言去扩展功能。

所以这个七牛图床工具就诞生了。

vscode-qiniu-pv
vscode-qiniu-pv

如何开始插件编写

这里还是有必要把这个插件编写过程回顾一下,因为现在可供参考的中文资料实在不多。
可以参考这篇文章 vscode编写插件详细过程 来完成插件开发环境部署和创建基本项目。

项目配置

以 Javascript 编写插件为例,这里我假设你已经建立了一个基础项目。

就如我们经常在 github 上见到的前端或 Node 项目一样,都有一个 package.json 用于描述项目信息,也可以使用 npm 命令安装你需要的第三方库。此外这个文件中又包含了一些专属于 Vscode 的配置项。

这里不在关注常规的 package.json 配置项,只介绍 Vscode 相关的。

activationEvents

插件在何时被激活。

  • onLanguage:${language}:打开某种格式的文件时
  • onCommand:${command}:输入某种命令时(Vscode中按F1)
  • onDebug:${type}:调试某种语言类型时
  • workspaceContains:${toplevelfilename}:当你的工作区包含某种文件时?
  • *:任何时候,编辑器启动就激活

描述可能有误,对应文档:Activation Events

contributes

Contributes 意思是贡献,这个属性中包含的都是可扩展点。

  • keybindings:绑定按键来执行某个命令
  • configuration:定义你的插件个性化配置
  • menus:扩展菜单
  • commands:用命令名执行某个命令
  • ……

这四项应该是最常用的,更多:Contribution Points

OK,有了这些,大概可以为你的插件编写作构思了。

{
// 插件何时被激活
"activationEvents": [
// 打开一个 Markdown 文件时,插件将被激活
"onLanguage:markdown"
],
// 插件入口文件
"main": "./extension",
// 扩展点
"contributes": {
// 按键绑定,当编辑区具有焦点且语言为 markdown 时,按 ctrl+q 执行 extension.qiniu.upload,也可针对 mac 平台独立配置
"keybindings": [{
"command": "extension.qiniu.upload",
"key": "ctrl+q",
"mac": "ctrl+q",
"when": "editorTextFocus && editorLangId == 'markdown'"
}],
// 插件配置属性,当你想要获取 qiniu 的配置时,以下所有 qiniu.xx 属性将合并于一个对象中
// title 和 description 将作为注释和属性提示分别在默认配置文件和用户配置文件中呈现
"configuration": {
"type": "object",
"title": "qiniu configuration",
"properties": {
"qiniu.enable": {
"type": "boolean",
"default": false,
"description": "七牛图片上传工具开关"
},
"qiniu.access_key": {
"type": "string",
"default": "",
"description": "一个有效的七牛 AccessKey 签名授权。"
},
"qiniu.secret_key": {
"type": "string",
"default": "",
"description": "一个有效的七牛 SecretKey 签名授权。"
},
"qiniu.bucket": {
"type": "string",
"default": "",
"description": "七牛图片上传空间."
},
"qiniu.remotePath": {
"type": "string",
"default": "${fileName}",
"description": "七牛图片上传路径,参数化命名。"
},
"qiniu.domain": {
"type": "string",
"default": "",
"description": "七牛图床域名。"
}
}
}
}
}

以我的 package.json 为例,描述了以下信息:

  1. 当你打开一个 Markdown 文件时,插件将被激活。
  2. 执行 ctrl+Q 将启动一个命令,还有一个 when 属性,表示额外的命令激活条件。
  3. 因为要上传到七牛,所以需要一些你的七牛用户信息,也就是 configuration,这可以在代码中方便的读取到。

最后我需要以合适的方式获取你想上传的本地图片,以 Markdown 的图片格式写入到你的光标位置。

编码

插件的入口文件只有一个,也就是配置中的 "main": "./extension"

一个基础的入口文件是这样的:

var vscode = require('vscode');
// 插件激活时执行
function activate(context) {
// 注册命令
var disposable = vscode.commands.registerCommand('extension.hello', function () {
// 编辑器上方显示一条信息
vscode.window.showInformationMessage('hello!');
})
// 加入释放队列?
context.subscriptions.push(disposable);
}
exports.activate = activate;
// 插件停用时执行
function deactivate() {
}
exports.deactivate = deactivate;

通过这个文件,可以发现 vscode 是个关键的对象,插件能做多少事都取决于这个对象可以提供多少接口支持。

最初我是想通过复制命令实现功能的,也就是用户复制一个图片到编辑器,然后拦截剪贴板拿到图片路径上传、插入文档。事与愿违,Vscode 没有提供这方法的接口支持,见:Issues: Clipboard access through Extensions API。下面提到一个第三方包 node-copy-paste 也仅能访问字符串信息,只好作罢。

Vscode 的接口调用大概分为两类:命令调用:Complex Commands API 和对象方法调用:vscode namespace API

前者很易用,比如预览 html 的示例:

let success = await commands.executeCommand('vscode.previewHtml', Uri.parse('file:///some/path/to/file.html'));

文档的示例是 TypeScript 写的,转换为 ES5 应该是这样:

var success = commands.executeCommand('vscode.previewHtml', Uri.parse('file:///some/path/to/file.html'))
.then(function(ret){
// success
}, function(err) {
// error
})

如果能调用一个选择文件的窗口获取本地图片路径最好不过了。可我翻遍了文档,也只找到了一个选择文件夹的命令 vscode.openFolder,简直就是不想让你写的太轻松。

最终只能使用一个输入框来接收本地图片路径,也就是预览图中的效果。

以下是我用到的一些API:

// 获取配置文件中的插件配置
vscode.workspace.getConfiguration('qiniu')
// 显示错误信息
vscode.window.showErrorMessage('error')
// 显示一个输入框,返回 Promise 对象
vscode.window.showInputBox(option)
// 编辑文件的函数,参数还是一个函数,这个回调函数的参数才是真正的可以用来增删文字的对象
vscode.window.activeTextEditor.edit(function(textEditorEdit) {
// 在光标位置插入文本
// textEditorEdit.insert(editor.selection.active, img);
})

最终技术支持其实是 七牛SDK ヾ(・ω・`。)。
具体的代码可以去 Github 上看。

安装

打包、发布那篇文章中也提到了,我已经打包放到了 Github 仓库中,就是那个 ·vsix 文件。使用 Ctrl+O 选择插件包就可以安装了,在用户配置文件中加一下你的七牛配置,重启下就能用了,快捷键 ctrl+q

同时可以通过编辑器左侧插件面板在线搜索 qiniu-upload-image 安装。

文件 -> 首选项 -> 用户设置,在右侧区域编写插件配置覆盖默认配置。
配置文件示例如下,参考你的七牛用户信息填写:

{
"qiniu.enable": true,
"qiniu.access_key": "xxxxxxxxxxxxx",
"qiniu.secret_key": "xxxxxxxxxxxxx",
"qiniu.bucket": "yourBucket",
"qiniu.remotePath": "${fileName}",
"qiniu.domain": "http://xxx.xxxxx.com"
}

编辑器中鼠标悬浮会显示属性提示。

Enjoy!