前言
团队的新项目整体采用 vh, vw 单位, 眼见团队成员默默调出了计算器...
我想我应该做点什么
考虑到团队整体使用 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…