Перейти до вмісту

Форматувальник

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 із правилами JSON від prettier: ключі залишаються в лапках, рядки завжди беруться в подвійні лапки незалежно від singleQuote, кінцевих ком немає, а коментарі // усередині документа зберігаються.

Правила розмітки

Принтер реалізує модель документа prettier: групи згортаються, якщо вміщуються у ширину друку, інакше переносяться; аргументи виклику прилягають до кінцевого аргументу-функції або об’єкта; ланцюжки властивостей розриваються перед кожною крапкою, якщо виходять за межі рядка; об’єкти, записані в кількох рядках, залишаються багаторядковими; між інструкціями зберігається не більш ніж один порожній рядок. Для коду, відформатованого prettier з відповідними параметрами, форматувальник створює байт-у-байт ідентичний результат на реальному коді; набір перевірок відповідності підтверджує це за допомогою зразків, згенерованих самим prettier.

Коментарі

Коментарі збираються під час токенізації (Parser::setCollectComments(true), доступні в парсері для інструментів) і повертаються до дерева як початкові, кінцеві або висячі вкладення. Коментарі рядка залишаються на своїх рядках, кінцеві коментарі в тому самому рядку залишаються при своїй інструкції, порожні рядки навколо коментарів зберігаються, а блоки /** ... */ отримують відступи, вирівняні за полем *.

Гарантії

Для кожного відформатованого результату виконуються три інваріанти, перевірені набором тестів:

  • Результат повторно розбирається в еквівалентну програму (без урахування розташування).
  • Усі коментарі з вхідного коду зберігаються у результаті.
  • Форматування ідемпотентне: повторне форматування результату нічого не змінює.

Продуктивність

Форматування працює зі швидкістю парсера: файли з реального світу форматуються за десятки мілісекунд, а типовий написаний вручну JavaScript у звичайному проєкті повністю форматується за значно менше ніж секунду в одному процесі.