提高Vuepress编写效率:开发自己的VSCode插件

1,101 阅读5分钟

时光不负,创作不停,本文正在参加2022年中总结征文大赛

背景

工欲善其事,必先利其器。本人近期一直在使用Vuepress2进行帮助文档的撰写和修改,由于该帮助文档有超过100个页面,且分别列在几个不同的目录下,那么就产生了两个痛点:

  1. 文档writer不是技术出身,每次在命令行里打cd project-name(因为同一工程下还有其他文件夹负责保存产品新特性的PDF)和npm run docs:dev都很难受,有时问我怎么跑不起来,一看是没有cd进入相应目录;
  2. Markdown文件太多,当我想修改目录A下的x文件时都要去跑起来的界面里看效果,为什么不直接装markdown预览插件呢,因为预览效果与实际的渲染结果有一定的差距。

那么我灵机一动,就想能不能实现类似open-in-browser插件的功能呢,直接在Markdown文件中右击或者在资源管理器中右击打开对应的页面。

image.png

如上图所示,对于HTML文件,open-in-browser可以在右击菜单中显示这两个选项。

初识Visual Studio Code Extension

对于一项新的技术,毫无疑问学习它的最简单的办法是去找它的官方文档,跟着它我们可以很快把项目框架建出来。在开发过程中遇到什么问题的话我们也可以查阅open-in-browser的源代码。

根据教程:

  1. 首先要安装 Yeoman 和 VS Code Extension Generator,运行npm install -g yo generator-code即可

  2. 在合适的目录内打开终端,运行yo code,选择想要构建的工程,此处选择第一个

image.png

  1. 给项目命名、添加描述,是否初始化git仓库,是否用webpack,用npm还是yarn等,按照需求进行选择即可。

项目最终如图所示:

image.png

主要关注extension.tspackage.json两个文件。点开前者,按F5即可启动调试模式 image.png

在主程序代码中↓,activate()函数是当插件被激活时调用,log里的内容会显示在调试控制台中且只会在激活时执行一次,disposable负责注册命令,该命令只会在插件执行时调用,helloworld.helloworld点号前的是我们的插件名称,点号后面的是当前命令名称,我们可以在package.json文件中找到它。 image.png

命令要在activationEventscommands都定义一次。在contributes中写的内容被称为Contribution Points,这里可以添加一些字段以拓展插件功能,比如图标、主题、案件绑定等,之后细说。 image.png

规划插件

在背景中我们已经介绍了希望实现了功能,现在也了解了一个插件是如何工作的,那么我们就可以来规划一下项目的运行流程:

  1. 让用户在settings中定义他目前使用的端口portbase(vuepress的config.ts中的属性)、命令command
  2. 获得当前打开的md文件的路径,比如C:/Users/UserA/Desktop/project-name/.vuepress/docs/dirA/A.md,那么运行vuepress之后A.md就会在http://localhost:${port}/${base}/dirA/A.html中呈现,那么只要将文件路径用docs/分割,再把.md替换成.html就能获得dirA/A.html,再获取portbase进行字符串拼接即可获得最终的可访问的url
  3. 检测当前port是否被占用,若占用则说明用户已经开启了服务,那么直接打开url即可。若没被占用,就在终端里执行定义好的command并打开url,同时也要把终端显示出来,不能让它默默在背后运行

tips:我一开始也不知道如何调用终端、获取settings等,都是通过Google搜索出来的,比如搜

how to display terminal in vscode extension

StackOverflow上通常都会有很好的答案

开始编写

package.json

首先在package.json中的contributes-menus里设置好两个右键指令(右击打开的文件窗口或资源管理器中的文件),此处可以在官方APIContribution Points中找到详细表述。

image.png

editor/context指在当前打开的文件右击,explorer/context指资源管理器中右击,让两者只有当文件为markdown时才能生效,command分别写上主程序里registerCommand中定义的命令名称,group可以让该右键菜单中的这行与谁归为一组,比如下图是三组不同的命令

image.png

然后在configuration中写上用户打开settings后可以定义的字段,API文档链接

image.png

最后在activationEventscommands把两个命令写进去即可,最终完成了package.json的编写。

extension.ts和utils.ts

为了保持主程序的整洁,我把一些工具类的函数提取到了utils.ts中,比如获得用户定义的settings、获取当前页面uri、获取资源管理器中某文件uri、裁切uri、拼接字符串、运行命令等,大家看代码就懂了: image.png

image.png

extension.ts中,我们只要按部就班地使用这些函数即可,检测端口用的是tcpPortUsed.check(port, ip)方法,注意这个方法返回promise,所以要使用async-await关键字。打开页面使用open库,传入网址就会使用默认浏览器打开它。

image.png

image.png

最后把两个命令推入就大功告成啦:

image.png

按F5测试一下,成功!

image.png

我也是第一次写插件,仓库在SummerGua/OpenThisVuepressPage,欢迎大家批评指正:)