
# Formater

Phasis udostępnia natywny formatter JavaScript oparty na własnym parserze. Ponownie zapisuje kod źródłowy z semantyką układu zgodną z prettier, całkowicie w PHP: bez Node.js, interpretowanych pakietów formattera ani procesów zewnętrznych.

## formatSource

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

Punkt wejścia wykonujący jedno wywołanie na `Phasis\Formatter\Formatter`. `$sourceType` wybiera język: `script` lub `module` dla JavaScript, `json` lub `css`. JavaScript parsuje kod zgodnie z podanym celem, ponownie dołącza komentarze i drukuje kod z uwzględnieniem skonfigurowanej szerokości wydruku.

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

Nieprawidłowy kod źródłowy powoduje ten sam `Phasis\Exceptions\SyntaxError` co parser, wraz z numerem wiersza, kolumny i przesunięciem.

## FormatOptions

Opcje układu odpowiadają 3.x prettier i domyślnie przyjmują ustawienia prettier:

| Opcja           | Domyślnie | Znaczenie                                                       |
| --------------- | ---------- | -------------------------------------------------------------- |
| `printWidth`    | `80`       | Docelowa szerokość wiersza, do której dopasowywany jest układ.   |
| `tabWidth`      | `2`        | Liczba spacji na poziom wcięcia (i mierzona szerokość tabulatora). |
| `useTabs`       | `false`    | Wcięcia tabulatorami zamiast spacjami.                           |
| `semi`          | `true`     | Średniki po instrukcjach.                                       |
| `singleQuote`   | `false`    | Preferuj `'` zamiast `"`, gdy wymaga mniej znaków ucieczki. |
| `trailingComma` | `'all'`    | `'all'`, `'es5'` lub `'none'`.                                  |
| `bracketSpacing`| `true`     | Spacje wewnątrz nawiasów klamrowych obiektu: `{ a }` kontra `{a}`. |
| `arrowParens`   | `'always'` | `'always'` lub `'avoid'` dla funkcji strzałkowych z jednym parametrem. |

## CSS

`formatSource($css, 'css')` formatuje arkusze stylów zgodnie z układem arkuszy stylów prettier: jeden selektor w wierszu na listach selektorów, jedna deklaracja w wierszu, ujednolicone odstępy wokół kombinatorów i wartości, proste listy wartości wypełniające wiersz, listy rozdzielane przecinkami dla cieni i gradientów zapisywane po jednym elemencie w wierszu, argumenty funkcji formatowane w całości albo wcale, zachowane puste wiersze i komentarze oraz nietknięte preambuły nieznanych reguł at, takich jak Tailwind z `@apply`. Długie złożone selektory są łamane przy kombinatorach potomka, a zbyt długie argumenty pseudoklas zawijane wewnątrz nawiasów.

## JSON

`formatSource($json, 'json')` ponownie wykorzystuje parser i drukarki JavaScript wraz z regułami JSON prettier: klucze pozostają ujęte w cudzysłowy, ciągi pozostają ujęte w podwójne cudzysłowy niezależnie od `singleQuote`, przecinki końcowe nigdy się nie pojawiają, a komentarze `//` wewnątrz dokumentu są zachowywane.

## Semantyka układu

Drukarka implementuje model dokumentu prettier: grupy są rozwijane do jednego wiersza, jeśli mieszczą się w szerokości wydruku, w przeciwnym razie są łamane; argumenty wywołań przylegają do końcowego argumentu funkcji lub obiektu; łańcuchy dostępu do elementów są łamane przed każdą kropką, gdy przekraczają szerokość wiersza; obiekty zapisane w wielu wierszach pozostają wielowierszowe; między instrukcjami zachowywany jest co najwyżej jeden pusty wiersz. Dla kodu sformatowanego przez prettier z tymi samymi opcjami formatter daje identyczne bajtowo wyniki dla rzeczywistego kodu; jego zestaw testów zgodności dokładnie to sprawdza na podstawie przykładów wygenerowanych przez samo prettier.

## Komentarze

Komentarze są zbierane podczas tokenizacji (`Parser::setCollectComments(true)`, udostępniane w parserze narzędziom) i ponownie dołączane do drzewa jako elementy poprzedzające, końcowe lub luźne. Komentarze w wierszu zachowują własne wiersze, komentarze końcowe w tym samym wierszu pozostają przy swojej instrukcji, puste wiersze wokół komentarzy są zachowywane, a bloki `/** ... */` są ponownie wcięte tak, by ich margines `*` był wyrównany.

## Gwarancje

Zestaw testów wymusza trzy niezmienniki dla każdego sformatowanego wyniku:

- Wynik można ponownie sparsować do równoważnego programu (pomijając lokalizacje).
- Wszystkie komentarze z wejścia są zachowane w wyniku.
- Formatowanie jest idempotentne: ponowne formatowanie sformatowanego wyniku niczego nie zmienia.

## Wydajność

Formatowanie działa z szybkością parsera: rzeczywiste pliki są formatowane w dziesiątki milisekund, a typowy, napisany ręcznie JavaScript projektu formatuje się od początku do końca w znacznie mniej niż sekundę w jednym procesie.
