跳转到正文

格式化程序

Phasis 提供原生 JavaScript 格式化程序,基于自有解析器构建。它会按照兼容 prettier 的布局语义重新打印源代码,完全在 PHP 中运行:无需 Node.js、无需解释型格式化程序包,也无需外部进程。

formatSource

PHP
public static function formatSource(
    string $source,
    string $sourceType = 'script',
    ?FormatOptions $options = null,
): string

Phasis\Formatter\Formatter 上的一站式调用入口。$sourceType 用于选择语言:script 或 module 对应 JavaScript、json 或 css。JavaScript 会按给定的目标解析,重新附加注释,然后按照配置的打印宽度输出。

PHP
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 在单个进程中从头到尾通常不到一秒。