工作中新写一个页面经常会遇到: 根据想好的布局写完了html片段, 然后要把对应的类名写个sass树.

于是产生了写个vscode来简化这个步骤的想法. 回头来分享这个简单的demo, 发布到vscode商店也是免费的.

vscode插件结构

文件结构

vscode的脚手架是在yeoman的.

1
2
3
4
# 安装
npm install -g yo generator-code
# 使用脚手架创建文件夹和目录结构
yo code

然后根据想使用的语言, 项目名称配置一下就行了.

进入文件夹, 会有很多文件, 都是为我们配置好的, 我们只需要关注2个文件: src/extension.tspackage.json.(需要发布的话需要写readme)

想完成一些插件功能, 入口都是从这2个文件. 所以在深入之前, 需要了解一下vscode插件概念.

vscode插件能力和基本概念

vscode插件提供的能力有:

  • 存储数据
  • 发出通知
  • 绑定快捷键
  • 控制右键菜单
  • 选择文件/文件夹

和一些我不关心的插件能力:

  • 控制颜色主题
  • 翻译语言
  • 语言(计算机语言)高亮
  • 扩展debugger

另外可以扩展一些工作区:

  • 菜单栏
  • 侧边栏
  • 状态栏
  • 新建tab插入webview

这些功能, 基本都通过2种入口来获取, package.json的配置字段contributes, 和引入node api的命名空间vscode. 现在可以开始介绍具体一些的实现了.

command与激活状态

command是vscode插件的一个基本概念, 在src/extension.ts注册, 然后在package.json中设置就会触发对应的动作.

extension.ts中export2个方法, 分别是activatedeactivate. 一般注册方法会写在active里, 所以要通过package.jsonactivationEvents来激活才可以注册command的行为.

完成插件功能

我希望创建一个命令, 通过右击菜单获取当前选中的html, 分析并产生一个sass树字符串, 并复制到剪切板中.

插件实现

package.json中这样配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
"contributes": {
"commands": [
{
"command": "get-sass-structure-from-html.generate-structure",
"title": "生成css节点树"
}
],
"keybindings": [
{
"command": "get-sass-structure-from-html.generate-structure",
"key": "ctrl+i",
"mac": "cmd+i"
}
],
"menus": {
"editor/context": [
{
"when": "",
"command": "get-sass-structure-from-html.generate-structure",
"group": "navigation"
}
]
}
},
  • commands注册一个command
  • keybindings注册一个快捷键, 当使用ctrl + i时就触发这个command
  • 在右击菜单添加一个菜单, 作为触发命令的入口.

src/extension.tsactive方法里注册这个command:

1
2
3
4
5
6
7
8
9
10
11
12
13
const generateStructure = vscode.commands.registerCommand("get-sass-structure-from-html.generate-structure", (fileUri: vscode.Uri) => {

const editor = vscode.window.activeTextEditor;
const tplstring = editor?.document.getText(editor.selection);

const res = parser(tplstring ?? '');

vscode.env.clipboard.writeText(res);
vscode.window.showInformationMessage('已复制');

});

context.subscriptions.push(generateStructure);

首先通过vscode.window.activeTextEditor获取到选区文本.

然后通过parse方法来获取转换后的sass树字符串.

最后通过vscode.env.clipboard.writeText写入剪切板, 并用vscode.window.showInformationMessage发出通知.

剩下的就是parse实现来简单解释一下.

parse实现

要分析一段html代码, 于是我从vue编译template的代码中解析html的方法里找到了他参考的lib, 并简写了一下.

最下层的做法是:

  1. 逐段读取domString.
  2. 用预先写好的一系列正则, 逐段匹配. 匹配目标是: 标签开始, 标签结束. (还有注释, 被我去掉了)
  3. 把匹配成功的段落, 根据匹配的类型, 扔到预先写好的回调里去执行.
  4. 若没有一段正则匹配成功, 则认为匹配到了”直到下个<符号”的字符串, 并扔到字符串回调里去执行.
  5. 从这次匹配结果的下一个字符开始下一轮匹配.

执行以后, 处理标签开始, 结束, 字符串的回调分别会依次执行, vue会在回调里建立自己的ast, 我直接在回调里拼接字符串, 我的parse函数就写好了.

当然, 最好的方式还是建立一个ast, 会更容易测试和开发后续功能和修复问题.

todos

demo级别的完成了, 但是还剩下好多东西没做.

  1. 对输出sass树字符串的格式化.
  2. 对属性”类”检测的和兼容.
  3. 对同级多个类的输出写法.
  4. 对错误输入的兼容.
  5. 对错误情况的处理.

发布到应用市场

发布流程非常简单, 并且是免费的. 教程说得非常清楚, 并且有截图.

总的来说分为2步:

  • azure devops注册一个账号, 并生成一个应用市场专用的token.
  • 用工具vsce发布.

安装vsce(vsce的全称是: vscode插件)的方法:

1
npm install -g vsce

然后登录

1
vsce login

然后发布

1
vsce publish

完事, 提示什么错误解决什么错误就可以了.