给 Any Rule 加一个新功能:图解正则

初衷

正则表达式这个东西,一旦写出来,可能就不愿意再去看了,毕竟写容易,读很费劲了😂,所以很早之前就想着在 AnyRule 上加一个功能,就是用来对正则表达式进行解释。起初是想像 Regex101 那样子,展示一个树状描述,对正则表达式的各个部分进行解释和说明,但是随着实验的进行,发现还是图更具有表现力,树状的结构在表达能力上还是有所欠缺,不过后期可能还是考虑加入树接口来进行解释。

Regulex

这是在到处找解析正则表达式的库的时候发现的一个开源项目,这个库能够将正则表达式解析为 AST,同时还可以画出正则表达式的图解,很厉害。于是就决定用这个库了。

不过由于种种原因(主要是我太菜了),原来的 AMD 导出方式我在 Webpack + TypeScript 的环境下怎么都不能正确的引入,于是我就 Fork 了一份,并作了一些改动:

  • 使用 cjs 的方式导出模块
  • 加了一部分必要的类型定义,来支持 TypeScript 中的使用
  • 修改了生成的图片的配色
  • 导出了一个参数供定制图片的颜色

现在在我的 Github 上进行维护,并且发布到 npm,包名叫做 regulex-cjs 有需要的同学们可以直接安装使用。

插件功能

作为一个辅助工具,它的交互和体验希望是最简单直接的,不过又受限于 VSCode 的开放能力,暂时决定是在正则所在行(或选中正则表达式)按快捷键,然后可以弹出 WebView,进行图解的展示,如果有多个则一次展示多个。参考图片如下(未做细节处理):

Diagram-Preview

插件实现

给项目重新配置了一下 Webpack,使之能够把 VSCode 需要的 extension.js 打包为一个,同时把 Webview 内的 HTML 文件和需要的 JS 进行打包和处理。

配置 Webpack

不得不说,文档没具体看,就会导致查找资料的时候,处处是惊喜(逃。比如突然发现,Webpack 配置支持导出一个数组,从而支持多个配置。形如:

1
2
3
const vscodeConfig = {};
const webviewConfig = {};
module.exports = [vscodeConfig, webviewConfig];

这么一来,用 Webpack 真的是可以为所欲为了鸭。

配置 React

现在习惯写带有 Web 页面的程序(包括但不限于 Chrome Extension,VSCode Extension 等),都使用 React 来绘制界面,所以配置上 React 是必要的。

使用 TypeScript 的情况下是很容易配置的,首先增加对 JSX 的支持:

1
2
3
4
5
6
7
// tsconfig.json
{
"compilerOptions": {
// ...
"jsx": "react"
}
}

然后在 Webpack 中配置对 .tsx 扩展名的支持,并将使用 ts-loader 的规则微调一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const config = {
// ...
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader',
},
],
},
],
},
};

再安装 reactreact-dom@types/react@types/react-dom 这些依赖即可。

添加 Webview

由于VSCode 内的资源引入限制,需要对内部的 HTML 进行一些处理,具体的函数没有自己写,从 小茗同学的博客 这里直接复制的。具体作用是

1
2
3
4
5
// 使用 fs 从某个 HTML 文件读取能被 Webview 加载的 HTML 内容
function getWebViewContent(context: ExtensionContext, templatePath: string): string;

// 获取某个扩展文件相对于 Webview 需要的一种特殊路径格式(vscode-resource 协议)
function getExtensionFileVscodeResource(context: ExtensionContext, relativePath: string): string;

然后在 HTML 模板中替换指定字符串为 script 的引入标签,当然 src 是通过上述函数处理过的 vscode-resource 协议的地址。

然后剩下的就是标准的写 React 的流程了。

绑定快捷键

这个最容易,在 package.json 中绑定 keybinding 到一个 Command 即可。

1
2
3
4
5
6
7
8
9
10
"contributes": {
"keybindings": [
{
"command": "extension.showDiagram",
"key": "ctrl+f10",
"mac": "cmd+f10",
"when": "editorTextFocus"
}
],
}

小结

整体的实现还是很容易的,毕竟踩在大佬们的肩膀上。等再做一些细节的处理,就可以更新插件的版本了。感兴趣的朋友可以拭目以待了哟。

末尾再放几个相关的库或者地址。