
# Formázó

A Phasis saját parserére épülő natív JavaScript formázót biztosít. A forráskódot prettier-kompatibilis elrendezési szabályok szerint írja újra, teljes egészében PHP nyelven: nincs szükség Node.js-re, értelmezett formázócsomagokra vagy külső folyamatokra.

## formatSource

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

Az egyhívásos belépési pont a `Phasis\Formatter\Formatter` része. A `$sourceType` választja ki a nyelvet: `script` vagy `module` a JavaScript esetén, illetve `json` vagy `css`. A JavaScript a megadott cél szerint feldolgozza a forrást, visszailleszti a megjegyzéseket, majd a beállított sorhosszhoz igazítva kiírja.

```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"
```

Érvénytelen forrás esetén ugyanaz a `Phasis\Exceptions\SyntaxError` hiba keletkezik, mint a parsernél, sor-, oszlop- és eltolási adatokkal.

## FormatOptions

Az elrendezési beállítások a prettier 3.x beállításait követik, alapértelmezésük pedig megegyezik a prettier alapértékeivel:

| Beállítás          | Alapérték    | Jelentés                                                        |
| --------------- | ---------- | -------------------------------------------------------------- |
| `printWidth`    | `80`       | Az elrendezés ehhez igazodik: a célként megadott sorhossz.                |
| `tabWidth`      | `2`        | Szóközök száma behúzási szintenként (és a tabulátor mért szélessége).     |
| `useTabs`       | `false`    | Behúzás tabulátorokkal szóközök helyett.                            |
| `semi`          | `true`     | Pontosvesszők az utasítások végén.                                          |
| `singleQuote`   | `false`    | Az `'` előnyben részesítése az `"` értékkel szemben, ha kevesebb escape-et igényel.              |
| `trailingComma` | `'all'`    | `'all'`, `'es5'` vagy `'none'`.                                 |
| `bracketSpacing`| `true`     | Szóközök az objektum kapcsos zárójelei között: `{ a }` a `{a}` helyett.             |
| `arrowParens`   | `'always'` | `'always'` vagy `'avoid'` az egyparaméteres nyílfüggvényeknél.  |

## CSS

A `formatSource($css, 'css')` a stíluslapokat a prettier stílusában formázza: szelektorlistánként egy szelektor soronként, deklarációnként egy sor, egységesített kombinátor- és értékközök, kitöltött egyszerű értéklisták, árnyékok és színátmenetek vesszővel tagolt elemei külön soronként, függvényargumentumok csak teljes egészükben maradnak egy sorban vagy törnek több sorba, megőrzött üres sorok és megjegyzések, az ismeretlen at-szabályok, például a Tailwind `@apply` előtagjai pedig változatlanok. A hosszú összetett szelektorok leszármazott-kombinátoroknál törnek, a túl hosszú pszeudoosztály-argumentumok pedig a zárójeleken belül tördelődnek.

## JSON

A `formatSource($json, 'json')` a JavaScript parserét és kiíróit használja újra a prettier JSON-szabályaival: a kulcsok idézőjelben maradnak, a karakterláncok az `singleQuote` értékétől függetlenül dupla idézőjelet kapnak, a záró vesszők soha nem jelennek meg, és a dokumentumon belüli `//` megjegyzések megmaradnak.

## Elrendezési szabályok

A kiíró a prettier dokumentummodelljét valósítja meg: a csoportok egy sorba rendeződnek, ha beleférnek a megadott sorhosszba, különben sortörést kapnak; a hívási argumentumok közvetlenül a záró függvény vagy objektumargumentumhoz kerülnek; a túl hosszú tagláncok minden pont előtt sort törnek; a több sorban megírt objektumok több sorosak maradnak; az utasítások között pedig legfeljebb egy üres sor marad meg. Az azonos beállításokkal, prettier formázású bemeneten a formázó valós kódon bájtról bájtra azonos kimenetet ad; ezt a megfelelőségi tesztcsomag a prettierrel generált tesztadatokkal ellenőrzi.

## Megjegyzések

A megjegyzések a tokenizálás során gyűlnek össze (`Parser::setCollectComments(true)`, az eszközök számára elérhetők a parseren), majd a fához vezető, követő vagy önálló megjegyzésként kerülnek vissza. A sorvégi megjegyzések a saját sorukban maradnak, az ugyanazon a soron lévő záró megjegyzések az utasításukhoz tapadnak, a megjegyzések körüli üres sorok megmaradnak, a `/** ... */` blokkok pedig új behúzást kapnak, igazított `*` margóval.

## Garanciák

A tesztcsomag három invariánst tartat be minden formázott kimeneten:

- A kimenet azonos értelmű programmá parse-olható (a helyadatokat nem számítva).
- A bemenet összes megjegyzése megmarad a kimenetben.
- A formázás idempotens: a formázott kimenet ismételt formázása nem változtat rajta.

## Teljesítmény

A formázás a parser sebességével fut: valós fájlok néhány tíz milliszekundum alatt formázódnak, egy tipikus projekt saját készítésű JavaScript fájljai pedig egyetlen folyamatban, a teljes feldolgozással együtt, jóval egy másodperc alatt elkészülnek.
