手把手教你寫一個 VSCode 外掛

anonther writer發表於2019-03-24

前言

團隊的新專案整體採用 vh, vw 單位, 眼見團隊成員默默調出了計算器...

img
我想我應該做點什麼
手把手教你寫一個 VSCode 外掛
考慮到團隊整體使用 VSCode 編輯器,於是這個外掛誕生了.
手把手教你寫一個 VSCode 外掛

專案搭建

yeoman / VS Code Extension Generator

VSCode 官方推薦使用 yeoman 和 VS Code Extension Generator 搭建專案

// 安裝 yeoman 
npm install -g yo generator-code

// 生成專案
yo code
複製程式碼

目錄結構

├── CHANGELOG.md
├── README.md
├── node_modules                                
├── out                                         // 輸出檔案
├── package-lock.json                           // package-lock.json
├── package.json                                // package.json
├── src                                         // src
│   ├── extension.ts                            // 註冊外掛
│   ├── process.ts                              // 功能處理函式
│   ├── provider.ts                             // 外掛功能提供(呼叫vscode擴充套件)
│   └── test                                    // test
├── tsconfig.json                               
├── tslint.json                                 
└── vsc-extension-quickstart.md
複製程式碼

基本功能

  • 匹配程式碼輸入,如捕捉 pxw 根據比率自動轉換為 vw; pxh 根據比率自動轉換為 vh,
  • 轉化比率可配置

功能實現

process.ts

process.ts主要實現對捕捉使用者輸入相應字元反應的工具類,執行 px 到 vh/vw 轉換.包含以下幾種方法:

class CSSPercent {
    ...
    // 匹配觸發條件字元正則
    regPxVw: RegExp = /([-]?[\d.]+)pxw/;  
    regPxVh: RegExp = /([-]?[\d.]+)pxh/;
    
    pxToPercent () {} // 轉化 px 為百分比值方法
    getBaseData () {} // 獲取預設值(外掛預設的設定)
    getPxStr () {}    // 捕獲使用者輸入px欄位
    cover () {}       // 呼叫getPxStr並執行pxToPercent函式,完成 px 2 vw/wh
}
複製程式碼

下面詳細解釋一下以上方法

cover

cover (text: string) { // text 是傳入使用者輸入的值
    let match = this.getPxStr(text); // 呼叫getPxStr匹配是否具備pxw/pxh 欄位
    if (!match) {return null;}

    return this.pxToPercent(match[0]); // 匹配成功呼叫pxToPercent完成轉化
  }
複製程式碼

getPxStr

// 匹配輸入字元是否觸發轉換
private getPxStr (str: string) {
    if (this.regPxVw.test(str)) {
      return str.match(this.regPxVw);
    } else if (this.regPxVh.test(str)) {
      return str.match(this.regPxVh);
    }

    return false;
  }
複製程式碼

pxToPercent

// 實現 px => vh / vh 轉換
private pxToPercent (pxStr: string) { // pxStr 是捕捉到使用者輸入px單位時傳入的引數
    interface BaseDataVale {
      unit: string;
      designValue: number;
    }
    const pxValue = parseFloat(pxStr);
    const baseData: BaseDataVale = this.getBaseData(pxStr); // 根據當前字元 pxw 或者 pxh 返回相應的基礎配置資料
    const percentValue: number | string = +(pxValue / baseData.designValue * 100).toFixed(this.config.fixedDigits); 
    const percentValueStr: string = `${percentValue}${baseData.unit}`;
    // 返回需要用到的欄位
    return {
      pxStr,
      pxValue,
      percentValue,
      percentValueStr
    };
  }
複製程式碼

getBaseData

  // 根據當前值返回配置資料值
  private getBaseData (str: string) {
    if (this.regPxVw.test(str)) {
      return {
        unit: 'vw',
        designValue: this.config.designWidth
      };
    } else if (this.regPxVh.test(str)) {
      return {
        unit: 'vh',
        designValue: this.config.designHeight
      };
    }

    return {
      unit: '',
      designValue: 0
    };
  }
複製程式碼

看到上邊的 this.config 大家可能會有疑問,後邊會闡述,以上就實現了 px 到百分比值的轉換,我們可以呼叫函式檢查到執行結果沒有問題,那接下來將通過 VSCode 本身的擴充套件獲取到輸入值,並執行 CSSPercent 方法

provide.ts

provider 主要會用到 VSCode 提供的 CompletionItemProvider 方法, 文件地址.

import * as vscode from 'vscode';
import CSSPercent from './process';

class CSSPercentProvider implements vscode.CompletionItemProvider { // CompletionItemProvider 可以在使用者鍵入字元之後提供可供選擇的 item, 用這個方法內獲取字元並匹配需要觸發的點(pxw / pxh)
  constructor (private process: CSSPercent) {}

  provideCompletionItems (
    document: vscode.TextDocument,
    position: vscode.Position
  ): Thenable<vscode.CompletionItem[]> {
    return new Promise((resolve, reject) => {
      const lineText = document.getText(new vscode.Range(position.with(undefined, 0), position)); // 匹配到當前行字元
      const result = this.process.cover(lineText); // 呼叫 csspercent 方法
      if (!result) {
        return resolve([]);
      }
      // 在匹配成功後提供 snippet 選項, 選中即轉化 px => vw / vh
      const item = new vscode.CompletionItem(`${result.pxValue}px => ${result.percentValueStr}`, vscode.CompletionItemKind.Snippet);
      item.insertText = result.percentValueStr;
      return resolve([item]);
    });
  }

}

export default CSSPercentProvider;
複製程式碼

extension.ts

在上邊部分已經完成了所有功能的開發, 但是我們的外掛還沒有真正在 vscode 中註冊成功, 同時我們也需要根據程式碼語言型別去呼叫外掛功能, 比如在 js, ts 等檔案裡如果也執行這個的外掛, 會造成不必要的浪費, extension.ts 就是做這部分的工作.

'use strict';
import * as vscode from 'vscode';
import CSSPercent from './process';
import CSSPercentProvider from './provider';

let config;

export function activate(context: vscode.ExtensionContext) { // vscode 啟用外掛會呼叫 activate 方法, 銷燬/禁用時呼叫 deactivate 方法

    config = vscode.workspace.getConfiguration('CSSPercent'); // 這裡獲取到我們的配置選項, 配置寫在 package.json 中

    const process = new CSSPercent(config); // 傳入預設配置, 這是 csspercent 裡呼叫 config 的來源
    const provider = new CSSPercentProvider(process);

    const TYPES = [
        'html',
        'vue',
        'css',
        'less',
        'scss',
        'sass',
        'stylus'
    ];
    // 遍歷註冊外掛需要執行的文字型別
    TYPES.forEach(item => {
        let providerDisposable = vscode.languages.registerCompletionItemProvider(
            {
                scheme: 'file',
                language: item
            },
            provider,
            'w',     // 這裡穿傳入 w, h 是 tigger 選項, 為了精確配置觸發條件
            'h'
        );
        context.subscriptions.push(providerDisposable); // 完成訂閱
    });
}

複製程式碼

package.json

配置項

    // config
   "contributes": {
        "configuration": {  // 配置項會在安裝外掛後的設定中找到, 這樣可以根據不同的 UI 稿實現不同的比率轉換
            "type": "object",
            "title": "CSS-Percent configuration",
            "properties": {
                "CSSPercent.designWidth": { // 設計稿寬度, 用於執行 px => vw
                    "type": "number",
                    "default": 1920,
                    "description": "design page's width (unit: px), default: 1920"
                },
                "CSSPercent.fixedDigits": { // 預設小數點精度
                    "type": "number",
                    "default": 4,
                    "description": "Px to percent decimal point maximum length, default: 4"
                },
                "CSSPercent.designHeight": { // 設計稿高度, 用於執行 px => vh
                    "type": "number",
                    "default": 1080,
                    "description": "design page's height (unit: px), default: 1080"
                }
            }
        }
    }
    
    // 觸發語言
    "activationEvents": [
        "onLanguage:html",
        "onLanguage:vue",
        "onLanguage:css",
        "onLanguage:less",
        "onLanguage:scss",
        "onLanguage:sass",
        "onLanguage:stylus",
        "onLanguage:tpl"
    ]

複製程式碼

釋出

VSCode外掛需要使用 vsc 釋出, 首先需要註冊一個Azure DevOps賬號, 主要根據官方文件即可

npm install -g vsce

$ vsce package // 打包外掛 .vsix 格式

$ vsce publish // 釋出到 MarketPlace
複製程式碼

完整專案地址

github.com/morehardy/v…

也可以在 VSCode 外掛中搜尋 CSS-Percent 安裝

歡迎使用, 歡迎star

參考

code.visualstudio.com/api/working…

code.visualstudio.com/api/referen…

相關文章