- 开发工具
【免费下载链接】astexplorer
A web tool to explore the ASTs generated by various parsers.
AST explorer 是一个开源的在线 Web 工具,核心交互只有一步:把代码粘贴或拖入编辑器,右侧立刻生成对应的抽象语法树(AST)。它内置了覆盖 CSS、JavaScript、HTML、GraphQL、Vue、SQL、Solidity、YAML 等 20 余类语言的几十个解析器,并集成了 babel、ESLint、jscodeshift 等转换器,让开发者可以在浏览器中直接观察语法结构、对比解析器差异,甚至原型化自己的 AST 转换插件。读完本文,你将掌握 AST explorer 的完整解析器/转换器清单、交互特性、如何为其添加新解析器与转换器,以及如何基于当前仓库在本地构建自己的开发版本。
项目定位:粘贴代码,立即看到 AST
项目主页 README.md 给出的定位非常直白:"Paste or drop code into the editor and inspect the generated AST on https://astexplorer.net/"——把代码粘贴或拖入编辑器,即可在线上查看解析器生成的 AST。
从仓库结构看,它由两部分组成:
website/:前端应用,基于 React + Redux + webpack 构建。入口 website/src/app.js 中通过SplitPane将页面组织为**左侧代码编辑器(CodeEditorContainer)+ 右侧 AST 树(ASTOutputContainer)的双栏布局,并可随时切换出转换面板(TransformerContainer)**用于编写转换代码。server/:一个轻量 Node 后端(Express),提供 gist 代码片段的存取 API,路由定义见 server/handlers/gist/index.js。
website/src/parsers/目录则是整个工具的"解析器宇宙":每个子目录对应一种语言分类,每个文件对应一个具体的解析器或转换器实现。
内置解析器全景:覆盖 20 余类语言的解析生态
README 完整列出了当前内置的解析器。这里按语言分类完整罗列如下:
| 语言分类 | 内置解析器 |
|---|---|
| CSS | cssom、csstree、postcss(另含 postcss-safe-parser 与 postcss-scss)、rework |
| GraphQL | graphql |
| Graphviz | redot |
| Handlebars | glimmer、handlebars、ember-template-recast |
| HTML | htmlparser2、parse5、@angular/compiler、@angular-eslint/template-parser、svelte、posthtml、hyntax |
| Vue | vue-template-compiler、@vue/compiler-core、vue-eslint-parser |
| ICU | intl-messageformat-parser |
| Java | java-parser |
| JavaScript | acorn(+ acorn-jsx)、babel-eslint、babylon、espree、esformatter、esprima、flow-parser、hermes-parser、meriyah、recast、seafox、shift、swc、traceur、typescript、typescript-eslint-parser、uglify-js |
| JSON | json-to-ast(README 记为 JSON)、Momoa |
| Lua | luaparse |
| Markdown | remark |
| MDX | mdxhast |
| Monkey | monkey |
| PHP | php-parser |
| Pug | pug |
| Regular Expressions | regexp-tree、regexpp、regjsparser |
| Protocol Buffers | pbkit |
| Scala | Scalameta |
| Solidity | solidity-parser-antlr |
| SQL | sqlite-parser |
| Svelte | svelte |
| WebIDL | webidl2 |
| YAML | yaml、yaml-ast-parser |
这些解析器与website/package.json中的依赖一一对应(如esprima、acorn、flow-parser、typescript、postcss等均为直接依赖),每个解析器目录下的实现文件会从对应 npm 包读取version与homepage元数据,例如 esprima.js 中的version: pkg.version。
值得说明的是,解析器并非硬编码在某个配置文件中,而是通过 website/src/parsers/index.js 中的require.context自动扫描注册的:它会递归匹配每个语言目录下的index.js(分类元数据)、解析器实现和codeExample.txt,构建出categoryByID、parserByID、transformerByID三张索引表,并导出getDefaultCategory()(默认 JavaScript)、getParserByID()、getTransformerByID()等查询函数。这意味着新增一个解析器文件后无需修改注册代码,目录结构本身即注册表。
实验性与自定义语法支持
README 指出,得益于各解析器的可配置选项,工具不只支持 ES5/CSS3,还支持大量实验性语法:
- ES6:箭头函数、解构(destructuring)、类(classes)等;
- ES7 提案:async/await、对象 rest/spread 等;
- JSX:由 React 普及的 JSX 语法;
- 类型化 JavaScript:Flow 与 TypeScript;
- SASS:通过 postcss-scss 等解析器支持。
这一点可以在各解析器的默认选项中得到印证。例如 espree.js 的默认配置将ecmaVersion设为'latest'、sourceType设为'module',并在ecmaFeatures中默认开启jsx与globalReturn;acorn.js 的默认选项同样包含ecmaVersion: 'latest'与'plugins.jsx': true,且在开启 JSX 且非 loose 模式时会用acorn.Parser.extend(acornJsx())组合出支持 JSX 的解析器实例。也就是说,切换解析器、勾选选项,就等于在浏览器里换了一套"方言能力"完全不同的解析前端。
Transforms:在浏览器中直接原型化转换插件
既然支持新语法,AST explorer 自然也是 AST 转换开发者的得力工具。README 明确写道:它内置了下列转换器(transformers),方便你直接在浏览器里编写并验证自己的插件:
- JavaScript:babel(v5、v6)、ESLint(v1、v2、v3)、jscodeshift、tslint
- HTML:posthtml
- CSS:postcss
- MDX:mdx
- Regular Expressions:regexp-tree
- Handlebars:glimmer
这些转换器位于website/src/parsers/*/transformers/目录,每个转换器目录下都有index.js实现与codeExample.txt示例代码。以最常用的 jscodeshift 转换器 为例,其实现要点包括:
- 声明
defaultParserID: 'recast',并将typescript、flow列为compatibleParserIDs; formatCodeExample会根据当前解析器类型把示例中的{{parser}}替换为babel、ts/tsx或flow;transform会先用 Babel 把转换代码转译为 ES5(见 transpilers/babel.js,其通过compileModule在浏览器里模拟模块执行,见 compileModule.js),再以 jscodeshift 的 API 运行转换函数,支持stats()统计与withParser()切换解析器。
转换器的运行逻辑可以这样概括:示例代码经 Babel 转译 →compileModule包装成模块 → 调用转换 API(jscodeshift / eslint rule / postcss plugin 等)→ 输出转换结果,全程在浏览器内完成,刷新即可反复迭代。
更多特性:片段分享、AST 反推源码与联动高亮
README 的 "More Features" 一节列出了若干实用的交互能力,这里结合源码逐一展开:
- 保存与 fork 代码片段,复制 URL 即可分享:前端存储层 website/src/storage/gist.js 实现了与后端的交互,URL 采用
#/gist/{snippetID}/{revisionID}的 hash 格式(如https://astexplorer.net/#/gist/{id}/{rev}),支持 "Current Revision"、"Latest Revision" 与原始 Gist 三种分享链接;后端路由 server/handlers/gist/index.js 提供GET /:snippetid/:revisionid(加载)、POST /(创建匿名片段)、PATCH /:snippetid(更新)、POST /:snippetid/:revisionid(fork)四类接口,snippetMiddleware.js 则在 Redux 层负责加载、保存、fork 的完整流程编排。 - 复制 AST 或将包含 AST 的文件拖入窗口,会用 escodegen 解析 AST 并反推出代码:PasteDropTarget.js 同时监听全局
paste事件与拖放事件。粘贴内容若能被JSON.parse识别为 JSON 格式的 AST,就会动态加载 escodegen(require(['escodegen']))调用escodegen.generate(ast, {format: {indent: {style: ' '}}})还原出源代码;否则按普通文本处理。 - 否则,拖入的文本文件内容会直接替换编辑器内容(例如直接拖入 .js 文件):拖放逻辑按文件的 MIME 类型(如
text/javascript、text/css)匹配到对应语言分类后写入编辑器。 - 在多个解析器之间切换并分别配置:每个解析器通过 defaultParserInterface.js 定义自己的
getDefaultOptions()与_getSettingsConfiguration(),UI 据此自动渲染出复选框(布尔选项)、下拉选择器(列表选项)乃至嵌套分组(如 babylon 的features/plugins分组,见 babylon.js)。 - shift+click 节点展开完整子树:树节点组件 Element.js 用状态机管理节点的
DEFAULT / OPEN / DEEP_OPEN / FOCUS_OPEN / CLOSED五种展开状态,DEEP_OPEN即 shift+click 触发的整棵子树展开。 - 悬停节点高亮源码中对应文本,反之编辑源码或移动光标也会自动高亮对应 AST 节点(未展开时高亮其祖先):这依赖每个解析器实现的
nodeToRange(node)方法(返回[start, end]区间)与树遍历时的坐标换算,例如 esprima 默认输出range、babylon/babel-eslint 输出start/end、postcss 通过 defaultCSSParserInterface.js 把行/列坐标换算为字符偏移。 - 在控制台中使用
$node引用最近打开/切换过的 AST 节点:便于在浏览器 DevTools 里对节点做实验性操作。
扩展指南:如何添加一个新解析器
README 给出了清晰的四步流程,这里将其与解析器接口定义对照展开(实现均位于website/src/parsers/下):
- 进入
website/目录; - 安装新解析器依赖:
yarn add theParser(依赖统一记录在 website/package.json); - 复制
src/parsers/{language}中一个现有示例作为起点; - 按需调整代码,核心是遵循 defaultParserInterface.js 定义的"最小接口":
- 更新元数据:
id(唯一 ID,会写入 snippet 并用于加载解析器,一经确定不应再变)、displayName、version(通常取自 npm 包package.json)、homepage;可选showInMenu(是否出现在 UI 菜单,默认true); - 实现
loadParser(callback):通过require(['模块名'], callback)异步加载真实解析器,例如 esprima.js 的require(['esprima'], callback); - 在
parse(parser, code, options)中调用正确的解析方法并传入必要选项:例如 esprima 是esprima.parse(code, options),typescript 则构造ts.createProgram并返回sourceFile(见 typescript.js); - 实现
nodeToRange(node):返回[start, end]形式的源码区间,供高亮与聚焦使用;默认实现读取node.range,babel-eslint 等则读取node.start/node.end; - 实现
getNodeName(node):返回节点的可读名称,供树中快速浏览;默认返回node.type,typescript 返回syntaxKind[node.kind]; - 实现
opensByDefault(node, key):决定哪些属性默认展开,例如 defaultESTreeParserInterface.js 默认展开Program节点及body、elements、declarations、expression等键; - 定义
_ignoredProperties集合或实现forEachProperty生成器方法:用于过滤不需要展示的属性。默认forEachProperty会跳过_ignoredProperties中的键;esprima 额外跳过函数值,typescript 则跳过parent和以_开头的属性,并合成leadingComments/trailingComments供查看; - 必要时提供
renderSettings方法:用于渲染自定义设置 UI(如 espree 会在设置区顶部附上官方选项说明链接,见 espree.js)。
此外,解析器还可声明locationProps(含位置信息的属性,可被 UI 隐藏)与typeProps(含节点类型名的属性)。解析完成后,parserMiddleware.js 会把这些配置包装成统一的"树适配器",并依次施加ignoreKeysFilter、functionFilter、emptyKeysFilter、locationInformationFilter、typeKeysFilter等过滤,最终渲染成树。
扩展指南:如何添加一个新转换器
README 给出的流程与之类似(同样在website/目录下):
- 安装新转换器依赖(
yarn add theTransformer); - 复制
src/parsers/{language}/transformers中一个现有示例; - 按需调整代码:
- 更新元数据与
defaultParserID(指定默认配合的解析器,如 jscodeshift 默认recast、ESLint v4 默认babel-eslint、tslint 默认typescript、postcss 默认postcss,可同时通过compatibleParserIDs声明兼容解析器); - 实现
loadTransformer(callback)异步加载转换库; - 在
transform()中调用真正的转换方法; - 修改
codeExample.txt中的示例转换代码。
- 更新元数据与
以 tslint 转换器 为例:它先用 TypeScript 转译器处理转换代码,再compileModule注入Lint与ts全局,随后构造tslint.Linter与自定义Rule,对astExplorer.ts源码应用规则并格式化输出违规信息;postcss 转换器 则通过require(name)白名单注入postcss模块,最终执行postcss([plugin]).process(code).css。
本地构建与开发
README 明确指出:出于多种原因,项目目前仍要求 Node.js 16 版本(.tools-versions中声明;若使用 asdf 等版本管理工具会自动切换)。构建步骤如下:
git clone克隆仓库;- 进入
website/目录; - 执行
yarn install安装全部依赖。
之后即可使用 website/package.json 中声明的脚本:
| 命令 | 作用 |
|---|---|
yarn run build | 生成最终的压缩(minified)版本,产物输出到../out |
yarn run watch | 增量编译,适合开发时持续监听文件变更 |
yarn run build-dev | 生成非压缩的开发版本 |
yarn start | 启动一个简单的静态 Web 服务器(serve -l 8080 ../out,监听 8080 端口) |
yarn run dev | 并行启动静态服务器与build-dev,一站式开发体验 |
yarn run lint | 对src/运行 ESLint |
前端还使用了 CodeMirror 作为编辑器(JavaScript、CSS、Handlebars、GraphQL 等分类在各自index.js中加载对应语法模式),并依赖 webpack 与require.context实现解析器的按需分包加载。
总结
AST explorer 的价值在于把"解析器 + 转换器 + 可视化"三者压缩进一个浏览器页面:README 所列举的 20 余类语言解析器由website/src/parsers/的目录结构自动注册,通过统一的解析器接口(loadParser/parse/nodeToRange/getNodeName/opensByDefault/_ignoredProperties/renderSettings)接入;babel、ESLint、jscodeshift、postcss 等转换器让用户能在浏览器里直接编写、运行、调试 AST 转换插件;gist 后端与#/gist/{id}/{rev}的 URL 格式支撑了代码片段的保存、fork 与分享;而"粘贴 AST 反推代码、悬停联动高亮、$node控制台引用"等交互则显著降低了探索 AST 的门槛。无论你是想对比各解析器的差异、学习 ESTree 结构,还是快速原型化一个 codemod,都可以直接以当前仓库为基底,按上文步骤在本地构建自己的版本,并照着"添加解析器 / 添加转换器"指南扩展它。
- 开发工具
【免费下载链接】astexplorer
A web tool to explore the ASTs generated by various parsers.
相关推荐
AST Explorer 插件系统终极指南:如何扩展工具功能
AST Explorer 插件系统终极指南:如何扩展工具功能 AST Explorer 是一款强大的抽象语法树可视化工具,它允许开发者探索各种解析器生成的AST
开发工具Regulex深度解析:正则表达式可视化与AST转换的终极指南
Regulex深度解析:正则表达式可视化与AST转换的终极指南 正则表达式是每个开发者必备的技能,但复杂的模式往往让人头疼。Regulex作为一款强大的Java
开发工具前端3步搞定SiYuan工作区迁移:跨设备无缝转移你的知识库
3步搞定SiYuan工作区迁移:跨设备无缝转移你的知识库 你是否曾因更换电脑或手机而担心珍贵的笔记数据丢失?是否在设备迁移时遇到过配置丢失、附件损坏的困扰?今天
知识管理知识库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考