从小白到大白 — 如何开发 VSCode 插件

前言

由于之前的国际化的项目中总是要统计老项目中待翻译的内容,然后再交由业务进行翻译,如果总是人为统计不仅相当耗费精力和时间,而且还不能保证是否有遗漏,因此想通过编写一个 i18n-helper 插件来实现这个功能。

11019129311b68dea1cb4da9d50aa670.jpeg

然而,大家的需求总是出奇的相似(因为已经有很多类似的插件存在了),因此没必要重复造轮子了,但是 如何开发 vscode 插件 的过程可以记录下来,分享给大家!

希望本文对你有所帮助!!!

b66b4018d787a319056af5fbb2fa1e29.jpeg

跑通官方插件示例

好了,话不多说,我们先按着 官方文档 跑一下它的插件用例吧!

生成插件目录

安装脚手架

npm install -g yo generator-code

初始化插件目录

终端运行 yo code,按照提示生成目录即可。

d6db4fa4f7ee6037a1fe4c6db915c2f4.jpeg

调试插件

由于官方文档缺少一些细节,很容易导致小白调试插件失败,再常见的有如下情况。

找不到 Hello World 命令

进入对应项目目录后,按照官方文档的指示可通过如下两种方式进行调试:

  • 按快捷键 F5

  • 点击编辑器左下方的 Run Extension

    2378734a2a7345701ef9a37116f2b57b.jpeg

接着按下 Ctrl + Shift + P,并输入 Hello World 命令,发现无法找到对应的命令:

38d009a9d2e6815e556479d11ac405e7.jpeg

这个原因主要是因为 vscode 版本不一致造成的:
  • package.json 文件中指定的 vscode 版本号

    6d1e9b6875093ef610415601cbd1ab72.jpeg

  • 当前实际的 vscode 版本号:

    caa12cc1126006262e9663c52cdbee26.jpeg

解决方案自然就是保持版本的一致性
  • 升级 vscode 版本

    • 适用于当前版本号低于 package.json 文件中指定的版本号

    • 【注意】 现在 vscode 版本的更新模型已经调整为 “默认” 模式,所以现在不会收到 vscode 需要更新的信息,也无法进行通过 “检查更新” 按钮来进行更新

      1522b26459cc082b7c191876066212f5.jpeg

  • 修改 package.json 文件中的 vscode 对应版本号

        • 这种方式比较简单直接,就是修改为和当前正在使用的 vscode 版本保持一致即可,如下:

          1fdf777b7978e41a6fffe709c08611de.jpeg

Hello World 命令报错

经过上述操作后,重新启动调试,按下 Ctrl + Shift + P,并输入 Hello World 命令,就可以找到对应的命令了,但是执行该命令时报错了:

e7550238b0929615839a2c5682298caa.jpeg

原因就在于我们没有编译文件,此时注意查看 package.json 文件中的 main 字段会发现:

c9415dadeed3ecbca4c53183f75d1f7a.jpeg

很明显,我们没有编译源文件生成目标文件,此时我们只需要通过 npm run watch 启用监听模式,让其进行编译即可:

7897ea0cfa5e6b81c37a0fa5607311f4.jpeg

此时在执行命令,就会发现成功了:

56bf34397f2c038031bc22fa4772916a.jpeg

【实战】编写 VSCode 插件

插件的三个概念

  • 激活事件(针对 V1.74.0 之前的 VSCode 版本)

    • 即插件激活的时机,目的是支持用户在输入 Hello World 命令后能够激活插件

    • 例如,使用 onCommand 进行注册 onCommand:extension.helloWorld bce4b120874762b082c1ae4359636186.jpeg

  • 发布内容配置

    • VS Code 通过 package.json 进行扩展,通过配置 插件清单字段 便于开发插件

    • 例如,使用 contributes.commands 绑定一个 命令 ID extension.helloWorld,目的是让 Hello World 命令就可以在命令面板中匹配到等

  • VS Code API

    • 插件代码中需要调用的一系列 JavaScript API 使用 VS Code 的一些功能特性

    • 例如,通过 vscode.commands.registerCommand 将一个函数绑定到对应的 命令 ID extension.helloWorld 上,激活命令时执行的就是该函数等

目录结构比较简单就不过多介绍了。

在 VSCode 中预览 SVG 文件 — <img /> 标签预览

当然相关的 svg 插件已经有不少了,这里只是用这个简单的需求来举个例子,方便让大家更容易理解。

SVG 文件在 VSCode 中的原始展示效果

85841e1de3323caecc7cc1ef303cf294.jpeg

发布内容配置 — package.json 文件

面向用户的命令

首先,我们要注册命令,让用户能够使用我们的插件,这里我们就简单支持如下两种方式:

  • Ctrl + Shift + P 匹配命令

    • 只需要在 package.json 中的 contributes.commands 进行如下配置即可,详情可见 contributes.commands

       
      1. "contributes": {
      2. "commands": [
      3. {
      4. "command": "svg-viewer.previewsvg",
      5. "title": "Preview SVG"
      6. }
      7. ]
      8. }
       
  • 鼠标右键菜单选择命令

    • 这种方式相对于上面的方式来讲更简便,只需要在 package.json 中的 contributes.menus 进行如下配置即可,详情可见 contributes.menus

       
      1. "contributes": {
      2. "menus": {
      3. "editor/context": [
      4. {
      5. "command": "svg-viewer.previewsvg"
      6. }
      7. ]
      8. }
       

上述 鼠标右键菜单选择命令 的配置有一点不好,那就是安装此插件后,在任何文件中右键都会显示 Preview SVG 选项,此时 调试效果如下:

3ed902127714f57a6cb22d63fc5d148a.jpeg

5f0a26e696c4fc13565c52a27a0b4718.jpeg

因为我们的本意是预览 SVG 文件,而不是其他文件,因此对于不符合的文件就没有必要展示此选项了,此时可以通过 when 子句上下文 来控制显示隐藏命令选项,此时配置更改为:

 
  1. "contributes": {
  2. "menus": {
  3. "editor/context": [
  4. {
  5. "command": "svg-viewer.previewsvg",
  6. "when": "resourceExtname == '.svg'"
  7. }
  8. ]
  9. }
 

调试效果如下:

cfa2f6a689f2a53f32813e4c8b01b7a2.jpeg

1e4c9e1868f45c09068ccca34b111529.jpeg

使用 VSCode API

注册命令

上述我们配置好了命令,现在就需要注册命令了,也就是决定当命令激活时需要做些什么事情,即只需要在 extension.ts 文件的 activate 方法中做如下修改即可:

 
  1. // 执行命令时被激活
  2. export function activate(context: vscode.ExtensionContext) {
  3. // 使用控制台输出诊断信息(console.log)和错误(console.error)
  4. // 这行代码只会在你的扩展被激活时执行一次
  5. console.log('Congratulations, your extension "svg-viewer" is now active!');
  6.  
  7.  
  8. // 注册命令,commandId 参数必须与 package.json 中的 command 字段匹配
  9. let disposable = vscode.commands.registerCommand(
  10. "svg-viewer.previewsvg",
  11. () => {
  12. // 具体要做的内容
  13. }
  14. );
  15.  
  16.  
  17. context.subscriptions.push(disposable);
  18. }
 
使用 Webview

平时我们通过浏览器使用 <img> 标签可以查看 svg 文件的效果,例如:

b2c194da5c2c4160137c23222153becd.jpeg

那么在 VSCode 中可不可以也以这样的方式来实现呢?

那当然是可以的。

我们可以使用如下代码编辑器中创建一个 Webview ,然后其中的 html 选项内容就可以用我们常见的 html 结构 来填充,并作为最终结果来进行 渲染,例如:

 
  1. // 创建并显示新的 webview
  2. const panel = vscode.window.createWebviewPanel(
  3. "SVGPreview", // 只供内部使用,即 webview 的标识
  4. "SVG Preview", // 面板标题
  5. vscode.ViewColumn.One, // 给新的 webview 面板一个编辑器视图
  6. {} // Webview 选项
  7. );
  8.  
  9.  
  10. // 设置HTML内容
  11. panel.webview.html = `<!DOCTYPE html>
  12. <html lang="en">
  13. <head>
  14. <meta charset="UTF-8" />
  15. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  16. <title>SVG Preview</title>
  17. </head>
  18. <body>
  19. <img src="${目标文件地址}" />
  20. </body>
  21. </html>
  22.     `;
 
获取目标文件的 base64 格式

由于我们打开相应 svg 文件后右键进行预览,那么第一步就得先获取当前这个文件的路径,这就又得需要使用的 VSCode API 了,如下

 
  1. const editor = vscode.window.activeTextEditor;
  2.  let url = editor.document.fileName// 获取到的就是对应文件的绝对路径
 

8a05816d18f652dd40a59b208814c825.jpeg

但是如果你直接把这个路径作为 <img> 标签的 src 属性是没法没正常渲染的,大致如下:

418422e35bb87a0eeb1a0c68be4870d5.jpeg

既然如此,那么我们可以把这个 svg 文件读取到,然后把它转成 base64 的格式,再交由 <img> 标签使用即可,此时我们就需要使用到 node 内置的 fs 模块了,即:

 
  1. const fs = require("fs");
  2. const content = fs.readFileSync(url);
  3.   return `data:image/svg+xml;base64,${content.toString("base64")}`;
 

源代码 & 效果展示

需要查看源码的可点此获取:源代码

经过上述的处理我们就可以在 VSCode 中预览 svg 文件了,效果如下:

cb2ace6de9aa699fa9b002ec68b06280.gif

在 VSCode 中预览 SVG 文件 — <svg> 标签预览

上述方案虽然可以实现我们需要的功能,但是对于 svg 文件来讲还是复杂了,因为在浏览其中是可以直接渲染 <svg> 标签的,而 svg 文件的内容不就是 <svg> 标签吗,那么我们只需要把文件内容读取出来,直接填充到 webview.html 中就好了,根本不需要转成 base64 格式。

a3163f54120710a43e1e3b15b4b49b7e.jpeg

这个方案比较简单,这里直接贴出 extension.ts 文件中的代码了:

 
  1. import * as vscode from "vscode";
  2.  
  3.  
  4. // 执行命令时被激活
  5. export function activate(context: vscode.ExtensionContext) {
  6. const fs = require("fs");
  7.  
  8.  
  9. // 注册命令,commandId 参数必须与 package.json 中的 command 字段匹配
  10. let disposable = vscode.commands.registerCommand(
  11. "svg-viewer.previewsvg",
  12. () => {
  13. const url = getActiveTextUrl();
  14. const content = fs.readFileSync(url, "utf-8");
  15. opedWebview(content);
  16. }
  17. );
  18.  
  19.  
  20. context.subscriptions.push(disposable);
  21. }
  22.  
  23.  
  24. // 获取当前文件路径
  25. export function getActiveTextUrl(): string {
  26. let url = "";
  27. const editor = vscode.window.activeTextEditor;
  28.  
  29.  
  30. if (editor) {
  31. url = editor.document.fileName;
  32. }
  33.  
  34.  
  35. return url;
  36. }
  37.  
  38.  
  39. // 创建并显示新的 webview
  40. export function opedWebview(content: string) {
  41. const panel = vscode.window.createWebviewPanel(
  42. "SVGPreview", // 只供内部使用,即 webview 的标识
  43. "SVG Preview", // 面板标题
  44. vscode.ViewColumn.One, // 给新的 webview 面板一个编辑器视图
  45. {} // Webview 选项
  46. );
  47.  
  48.  
  49. // 设置HTML内容
  50. panel.webview.html = getWebviewContent(content);
  51. }
  52.  
  53.  
  54. // 渲染模版
  55. export function getWebviewContent(content: string) {
  56. return `<!DOCTYPE html>
  57. <html lang="en">
  58. <head>
  59. <meta charset="UTF-8" />
  60. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  61. <title>SVG Preview</title>
  62. <style>
  63. html,
  64. body {
  65. width: 100%;
  66. height: 100%;
  67. }
  68. body {
  69. display: flex;
  70. justify-content: center;
  71. align-items: center;
  72. }
  73. svg {
  74. max-height: 90%;
  75. }
  76. </style>
  77. </head>
  78. <body>
  79. ${content}
  80. </body>
  81. </html>
  82. `;
  83. }
  84.  
  85.  
  86. // 停用命令时执行
  87. export function deactivate() {}
 

发布

发布到官网应用市场

通过 这个地址 注册开发者账号,然后按提示发布到官网应用市场即可。

19a3310b9e2dde35b81091e4defbbce0.jpeg

使用 vsce 打成 vsix 插件

这种方式可以实现即使 没有发布到应用市场,也可以直接通过对应文件的方式进行插件的安装和使用。

安装 vsce 工具

安装命令 npm i vsce -g

打包生成 .vsix 文件

直接使用 vsce package 命令进行打包,完成后就会生成一个 .vsix 文件,这个也就是在后续安装插件时要使用的文件。

注意】 在使用这个命令打包时,可能会出现 vsce 所需要支持的 VSCode 最低版本和当前使用版本之间存在出入,导致打包失败:

8b40cf4ab4db62a4f2ce8e89e1e691e0.jpeg 特别是如果按照前文的方式直接修改 package.json 文件中的版本号时,此时最好还是将 VSCode 版本进行升级,而不是手动修改版本号。

安装 vsix 插件

按照如下方式操作并选择对应的 .vsix 文件即可.

e746f1d332c628c24bca77434c463cbe.jpeg

最后

欢迎关注同名公众号《 程序员成长指北 》,本公众号会定期分享技术干货,也可快速加入前端交流群!

以上就是本文的全部内容了,文中没有过多介绍那些没有用到的内容(如 package.json 相关配置),因为内容太多了,所以大家多查阅下官方文档即可。

d939260231c05cf74a8576734c43e18b.jpeg

通过本篇文章,希望能让你从一个 VSCode 插件开发 的小白变成大白,能够为团队赋能,或者作为自己的一个技能亮点。

posted @ 2024-03-26 11:15  CharyGao  阅读(56)  评论(0)    收藏  举报