Aller au contenu

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.