格式化程序
Phasis 提供原生 JavaScript 格式化程序,基于自有解析器构建。它会按照兼容 prettier 的布局语义重新打印源代码,完全在 PHP 中运行:无需 Node.js、无需解释型格式化程序包,也无需外部进程。
formatSource
public static function formatSource(
string $source,
string $sourceType = 'script',
?FormatOptions $options = null,
): string
Phasis\Formatter\Formatter 上的一站式调用入口。$sourceType 用于选择语言:script 或 module 对应 JavaScript、json 或 css。JavaScript 会按给定的目标解析,重新附加注释,然后按照配置的打印宽度输出。
use Phasis\Formatter\Formatter;
use Phasis\Formatter\FormatOptions;
$formatted = Formatter::formatSource(
"const a={x:1,y:2};",
'script',
new FormatOptions(useTabs: true, singleQuote: true),
);
// "const a = { x: 1, y: 2 };\n"
无效源代码会抛出与解析器相同的 Phasis\Exceptions\SyntaxError,并包含行、列和偏移量。
FormatOptions
布局选项与 prettier 的 3.x 相同,默认值也与 prettier 的默认值一致:
| 选项 | 默认值 | 含义 |
|---|---|---|
printWidth |
80 |
布局适配的目标行宽。 |
tabWidth |
2 |
每个缩进级别的空格数(也是制表符的测量宽度)。 |
useTabs |
false |
使用制表符而非空格缩进。 |
semi |
true |
语句分号。 |
singleQuote |
false |
在转义更少时优先使用 ' 而非 "。 |
trailingComma |
'all' |
'all'、'es5' 或 'none'。 |
bracketSpacing |
true |
对象花括号内的空格:{ a } 与 {a}。 |
arrowParens |
'always' |
单参数箭头函数使用 'always' 或 'avoid'。 |
CSS
formatSource($css, 'css') 使用 prettier 的样式表布局规则格式化样式表:选择器列表中每行一个选择器,每行一个声明,规范化组合符和取值的空格,简单取值列表尽量填满行,阴影和渐变的逗号分隔列表每行一个条目,函数参数要么全都换行、要么都不换行,保留空行和注释,并且不改动未知 at 规则的前导内容,例如 Tailwind 的 @apply。较长的复合选择器会在后代组合符处换行,过长的伪类参数则会在括号内换行。
JSON
formatSource($json, 'json') 重用 JavaScript 解析器和打印器,并采用 prettier 的 json 规则:键保持带引号,字符串始终使用双引号,不受 singleQuote 影响,不会出现尾随逗号,文档内的 // 注释也会保留。
布局语义
打印器采用 prettier 文档模型:内容适合打印宽度时会将组展平,否则会换行;调用参数会紧贴末尾的函数或对象参数;成员链超出行宽时会在每个点号前换行;跨多行书写的对象会保持多行;语句间最多保留一个空行。对于选项匹配的 prettier 格式输入,格式化结果与真实项目代码逐字节一致;其一致性测试套件会针对由 prettier 本身生成的样例验证这一点。
注释
注释在词法分析期间收集(Parser::setCollectComments(true),可通过解析器提供给工具使用),随后作为前置、尾随或游离注释重新附加到语法树。行注释保留在各自的行上,同一行的尾随注释仍留在对应语句上,注释周围的空行会保留,/** ... */ 块会重新缩进,并对齐其 * 竖线边栏。
保证
测试套件会强制确保每次格式化输出都满足以下三项不变量:
- 输出重新解析后会得到等效程序(位置除外)。
- 输入中的每条注释都会保留在输出中。
- 格式化具有幂等性:格式化后的输出再次格式化不会发生变化。
性能
格式化速度与解析器相当:真实项目文件通常在几十毫秒内完成格式化,典型项目中手写的 JavaScript 在单个进程中从头到尾通常不到一秒。