
# Formateur

Phasis fournit un formateur JavaScript natif, basé sur son propre analyseur. Il réimprime le code source avec une mise en page sémantiquement compatible avec prettier, entièrement en PHP : sans Node.js, sans bundles de formateur interprétés, sans processus externes.

## formatSource

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

Le point d'entrée en un appel de `Phasis\Formatter\Formatter`. `$sourceType` sélectionne le langage : `script` ou `module` pour JavaScript, `json` ou `css`. JavaScript analyse selon l'objectif indiqué, rattache les commentaires, puis imprime en respectant la largeur configurée.

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

Une source non valide déclenche le même `Phasis\Exceptions\SyntaxError` que l'analyseur, avec la ligne, la colonne et le décalage.

## FormatOptions

Les options de mise en page reprennent celles de prettier 3.x et utilisent par défaut les valeurs de prettier :

| Option          | Valeur par défaut | Signification                                                   |
| --------------- | ---------------- | --------------------------------------------------------------- |
| `printWidth`    | `80`            | Largeur de ligne cible à laquelle la mise en page est ajustée.  |
| `tabWidth`      | `2`             | Espaces par niveau d'indentation (et largeur mesurée d'une tabulation). |
| `useTabs`       | `false`         | Indenter avec des tabulations plutôt qu'avec des espaces.       |
| `semi`          | `true`          | Points-virgules de fin d'instruction.                           |
| `singleQuote`   | `false`         | Préférer `'` à `"` lorsqu'il nécessite moins d'échappements. |
| `trailingComma` | `'all'`         | `'all'`, `'es5'` ou `'none'`.                    |
| `bracketSpacing`| `true`          | Espaces à l'intérieur des accolades d'objet : `{ a }` ou `{a}`. |
| `arrowParens`   | `'always'`      | `'always'` ou `'avoid'` pour les fonctions fléchées à un seul paramètre. |

## CSS

`formatSource($css, 'css')` formate les feuilles de style selon la mise en page de feuille de style de prettier : un sélecteur par ligne dans les listes de sélecteurs, une déclaration par ligne, espaces normalisés autour des combinateurs et des valeurs, listes simples de valeurs remplies au maximum, listes séparées par des virgules sur une ligne par élément pour les ombres et dégradés, arguments de fonction traités comme un tout, lignes vides et commentaires préservés, et préambules inchangés pour les règles at inconnues telles que Tailwind de `@apply`. Les longs sélecteurs composés sont coupés aux combinateurs descendants, et les arguments trop longs des pseudo-classes sont renvoyés à la ligne à l'intérieur des parenthèses.

## JSON

`formatSource($json, 'json')` réutilise l'analyseur et les imprimeurs JavaScript avec les règles JSON de prettier : les clés restent entre guillemets, les chaînes restent entre guillemets doubles quel que soit `singleQuote`, aucune virgule finale n'apparaît et les commentaires `//` dans le document sont conservés.

## Sémantique de mise en page

L'imprimeur implémente le modèle de document de prettier : les groupes sont aplatis lorsqu'ils tiennent dans la largeur d'impression et passent à la ligne sinon, les arguments d'appel restent accolés à un argument final de fonction ou d'objet, les chaînes d'accès aux membres passent à la ligne avant chaque point lorsqu'elles dépassent la largeur, les objets écrits sur plusieurs lignes le restent, et une seule ligne vide au maximum est conservée entre les instructions. Sur du code déjà formaté par prettier avec les mêmes options, le formateur produit un résultat identique octet par octet sur du code réel ; sa suite de conformité le vérifie précisément avec des fixtures générées par prettier lui-même.

## Commentaires

Les commentaires sont recueillis pendant la tokenisation (`Parser::setCollectComments(true)`, exposés par l'analyseur aux outils), puis rattachés à l'arbre comme éléments précédents, suivants ou flottants. Les commentaires de ligne restent sur leur propre ligne, les commentaires de fin de ligne restent avec leur instruction, les lignes vides autour des commentaires sont préservées et les blocs `/** ... */` sont réindentés avec leur gouttière `*` alignée.

## Garanties

Trois invariants sont respectés pour chaque sortie formatée et vérifiés par la suite de tests :

- La sortie peut être analysée à nouveau en un programme équivalent (hormis les emplacements).
- Tous les commentaires de l'entrée sont conservés dans la sortie.
- Le formatage est idempotent : reformater une sortie déjà formatée ne change rien.

## Performances

Le formatage s'effectue à la vitesse de l'analyseur : les fichiers réels sont formatés en quelques dizaines de millisecondes et le JavaScript écrit à la main d'un projet typique est formaté de bout en bout en moins d'une seconde dans un seul processus.
