从零开始撸一个 VSCode Extension

2,405 阅读5分钟

前言

作为一个天天写 React 的前端,工作中经常遇到 React Style 和 CSS 之间的相互转换,所以抽空撸了个 VSCode Extension(扩展/插件): css-style-transformer,记录一下这次 VSCode 插件的开发过程。

1. VSCode 与 Extension

什么是 VSCode Extension

作为前端开发,应该对 VSCode 都不陌生,它是用前端最熟悉的语言—— JavaScript(Electron.js + TypeScript) 开发的代码编辑器,目前市占率最高。

Visual Studio Code 是一个运行在桌面上,并且可用于Windows,Mac OS X和Linux平台的的轻量级且功能强大的源代码编辑器。它配备了内置的JavaScript的,TypeScript和Node.js的支持,并具有其他语言(C ++,C#,Python和PHP)的扩展以及一个丰富的生态系统。

Visual Studio Code 在构建时考虑了可扩展性。从 UI 到编辑体验,几乎 VS Code 的每个部分都可以通过 Extension API 进行定制和增强。事实上,VSCode 的许多核心功能都是作为扩展构建的,并且使用相同的扩展 API。

因为 VSCode 是用 JS 开发的,所以 Extension(下文简称插件) 也是用的 JS,对前端很友好,开发起来也非常方便。

VSCode Extension 能做什么

只有你想不到的,没有 VSCode Extension 做不到的:

  • 使用颜色或文件图标主题更改 VS Code 的外观

  • 在 UI 中添加自定义组件和视图 -扩展工作台

  • 创建 Webview 以显示使用 HTML/CSS/JS 构建的自定义网页

  • 支持一种新的编程语言

  • 支持调试特定运行时

  • ...

2. 从零开撸

1. 项目初始化

VSCode 提供了开发插件的官方脚手架,所以只需要两行命令就可以生成初始项目:

 // 安装 Yeoman 和 VS Code Extension Generator :
npm install -g yo generator-code

// 生成项目
yo code

2. 目录结构

.
├── .vscode
│   ├── launch.json     // 插件加载和调试的配置
│   └── tasks.json      // 配置TypeScript编译任务
├── .gitignore          // 忽略构建输出和node_modules文件
├── README.md           // 一个友好的插件文档
├── src
│   └── extension.ts    // 插件源代码
├── package.json        // 插件配置清单
├── tsconfig.json       // TypeScript配置

package.json

每个 VSCode 插件都必须包含一个package.json,它就是插件的配置清单。package.json混合了Node.js字段,如:scriptsdependencies,还加入了一些VS Code独有的字段,如:publisheractivationEventscontributes等。其中一些非常重要的字段:

  • namepublisher: VS Code 使用<publisher>.<name>作为一个插件的ID。你可以这么理解,Hello World 例子的 ID 就是vscode-samples.helloworld-sample。VS Code 使用 ID 来区分各个不同的插件。
  • main: 插件的主入口。
  • activationEvents: 激活事件。当配置的激活事件触发时, 插件就会被激活.。
  • contributes: 发布内容配置。通过注册各种发布内容配置来实现各种扩展功能。
  • engines.vscode: 描述了这个插件依赖的最低VS Code API版本。

插件入口文件(这里是 extension.ts)

插件入口文件会导出两个函数,activatedeactivate,你注册的激活事件被触发之时执行activatedeactivate则提供了插件关闭前执行清理工作的机会。

通常,我们会在 activate 中注册命令。

        // 'vscode'模块包含了VS Code extensibility API
        // 按下述方式导入这个模块
        import * as vscode from 'vscode';// 一旦你的插件激活,vscode会立刻调用下述方法
        export function activate(context: vscode.ExtensionContext) {

            // 用console输出诊断信息(console.log)和错误(console.error)
            // 下面的代码只会在你的插件激活时执行一次
            console.log('Congratulations, your extension "my-first-extension" is now active!');

            // 入口命令已经在package.json文件中定义好了,现在调用registerCommand方法
            // registerCommand中的参数必须与package.json中的command保持一致
            let disposable = vscode.commands.registerCommand('extension.sayHello', () => {
                // 把你的代码写在这里,每次命令执行时都会调用这里的代码
                // ...
                // 给用户显示一个消息提示
                vscode.window.showInformationMessage('Hello World!');
            });

            context.subscriptions.push(disposable);
        }

3. 功能开发

我们要实现将选定代码在 React Style 和 CSS 之间进行相互转换的功能。

  • 首先,我们在 package.json 文件中配置命令 css-style-transformer.transform

       {
        // ...
        "activationEvents": [
            // 配置可以用命令的形式触发
           "onCommand:css-style-transformer.transform"
         ],
        "contributes": {
            // 配置命令
           "commands": [
             {
               "command": "css-style-transformer.transform",
               "title": "css style transform"
             }
           ],
           // 配置可以用相应快捷键触发
           "keybindings": [
             {
               // 配置快捷键触发的命令
               "command": "css-style-transformer.transform",
               "key": "ctrl+alt+shift+t",
               "mac": "ctrl+alt+cmd+t",
               // 配置触发时机
               "when": "editorTextFocus"
             }
           ],
           // 配置鼠标右键菜单
           "menus": {
             // 编辑器内容菜单
             "editor/context": [
               {
                 // 配置触发时机
                 "when": "editorHasSelection",
                 // 配置菜单触发的命令
                 "command": "css-style-transformer.transform"
               }
             ]
           }
         },
         // ...
       }
    
  • 然后,我们要在插件入口文件中注册相应的命令

        // 'vscode'模块包含了VS Code extensibility API
        // 按下述方式导入这个模块
        import * as vscode from 'vscode';
        // 实现命令的方法
        import { main } from "./main";
    
        // 一旦你的插件激活,vscode会立刻调用下述方法
        export function activate(context: vscode.ExtensionContext) {
    
            // 用console输出诊断信息(console.log)和错误(console.error)
            // 下面的代码只会在你的插件激活时执行一次
    
            // registerCommand中的参数必须与package.json中的command保持一致
            let disposable = vscode.commands.registerCommand("css-style-transformer.transform",
            main);
    
            context.subscriptions.push(disposable);
        }
    
  • 最后,在 main 方法中具体实现功能,主要是一些字符串操作,其中涉及到的一些 VSCode 的 API:

    • vscode.window.activeTextEditor: 编辑器实例

      • .selection: 选中的范围
      • .document.getText: 获取文本
      • .edit: 编辑文本
    • vscode.window.showInformationMessage: 消息提示

4. 发布插件

开发完插件,我们可以将它分享出去:

这里我们选择发布到 VSCode 扩展市场,让所有人都能查找、使用我们的插件。

  1. 注册开发者账号,获取 token( 参考 code.visualstudio.com/api/working…

  2. 通过 VSCode官方提供的 vsce 发布:

        // 安装 vsce
        npm install -g vsce
    
        // 登陆
        vsce login (publisher name)
    
        // 发布
        vsce publish -p <token>
    
        // 其他操作
        // 增量更新
        vsce publish <version>
        // 下架
        vsce unpublish (publisher name).(extension name)
        // 只打包为 VSIX 格式
        vsce package
    

然后我们就可以在 VSCode 上搜索安装了。

3. 写在最后

最后,还是要安利一下刚撸出来的这个插件:css-style-transformer,感兴趣可以下载试试,希望能派上用场。

06z5s-z9wrr.gif

参考资料