直接用ast实现html在线编辑器自动格式化不现实,因成本高、收益低;应使用prettier浏览器版配合parser-html插件,通过format()方法调用并配置参数,而非手动操作ast。

AST 格式化和普通格式化根本不是一回事
直接用 AST 实现 HTML 在线编辑器的自动格式化,现实中几乎没人这么做——因为成本高、收益低。AST 是解析器用来理解代码语义的中间结构,不是为排版缩进设计的。在线编辑器(比如 Monaco、CodeMirror)的格式化功能,底层调用的是 prettier 或 html-beautify 这类工具,它们内部确实会构建 AST(或类似结构),但你作为使用者不需要、也不应该手动操作 AST 来做格式化。
为什么不能自己写 AST 解析 + 手动拼接来格式化 HTML
看似“可控”,实则容易踩坑:
-
prettier的 HTML 支持依赖完整 parser(如@prettier/parser-html),它能处理自闭合标签、可选结束标签(p、li)、CDATA、注释嵌套等边界情况;手写正则或简易 AST 构建器大概率漏掉这些 - 属性顺序、引号风格(单/双/无引号)、是否换行、缩进空格数等,都是格式化策略层的配置,硬编码在 AST 遍历逻辑里会让维护爆炸
- 在线环境对 bundle 体积敏感,引入完整 HTML 解析器(如
parse5)+ 自定义打印器,JS 包可能增加 200KB+,远超prettier浏览器版的按需加载方案
真正可行的在线 AST 格式化路径:用 prettier 的浏览器版
如果你确实需要“基于 AST”的保障(比如团队强依赖 Prettier 规则),就直接用官方支持的方案:
- 通过
import { format } from "https://unpkg.com/prettier@3.3.3/esm/standalone.mjs"加载浏览器可用版本 - 搭配
parser-html:同样从 unpkg 加载https://unpkg.com/prettier@3.3.3/esm/parser-html.mjs,并传入plugins选项 - 调用时指定
parser: "html"和tabWidth、useTabs等参数,而非自己遍历 AST 节点 - 注意:
prettier.format()返回的是字符串,不是 AST 对象;你拿到的 AST 是它内部用的,不暴露给用户
在线编辑器里该关掉什么、该配什么
以 Monaco Editor 为例,别被“AST”字眼带偏重点:
- 关掉默认的
html.format.enable(VS Code 风格的内置格式化),它不走 AST,规则僵硬且不可配 - 启用
formatOnSave或监听onDidSave事件,触发时调用prettier.format() - 把
prettier的配置项(如printWidth、singleAttributePerLine)做成 UI 设置项,而不是去改 AST 节点生成逻辑 - 如果要高亮显示格式化差异(比如 diff view),用
diff-match-patch比解析两次 AST 再比对 child 数组靠谱得多
真正难的从来不是“怎么生成 AST”,而是怎么让格式化结果既符合规范、又不破坏原有语义(比如把 <div><span>text</span></div> 错误地拆成多行导致渲染异常)。工具链已经帮你压平了这些细节,没必要绕回去重造轮子。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











