Zum Inhalt springen

Formatter

Phasis bietet einen nativen JavaScript-Formatter, der auf einem eigenen Parser basiert. Er gibt Quellcode mit einem prettier-kompatiblen Layout aus, vollständig in PHP: kein Node.js, keine interpretierten Formatter-Bundles, keine externen Prozesse.

formatSource

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

Der Einstiegspunkt mit einem Aufruf in Phasis\Formatter\Formatter. $sourceType legt die Sprache fest: script oder module für JavaScript, json oder css. JavaScript parst mit dem angegebenen Ziel, fügt die Kommentare wieder ein und gibt den Code mit der konfigurierten Zeilenbreite aus.

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"

Ungültiger Quellcode löst denselben Phasis\Exceptions\SyntaxError wie der Parser aus, einschließlich Zeile, Spalte und Offset.

FormatOptions

Die Layoutoptionen entsprechen prettier 3.x und verwenden standardmäßig die Voreinstellungen von prettier:

Option Standard Bedeutung
printWidth 80 Zielzeilenbreite, an die das Layout angepasst wird.
tabWidth 2 Leerzeichen pro Einrückungsebene (und gemessene Breite eines Tabs).
useTabs false Tabs statt Leerzeichen zur Einrückung verwenden.
semi true Semikolons nach Anweisungen.
singleQuote false ' gegenüber " bevorzugen, wenn dadurch weniger Escape-Sequenzen nötig sind.
trailingComma 'all' 'all', 'es5' oder 'none'.
bracketSpacing true Leerzeichen innerhalb von Objektklammern: { a } gegenüber {a}.
arrowParens 'always' 'always' oder 'avoid' bei Arrow-Funktionen mit einem Parameter.

CSS

formatSource($css, 'css') formatiert Stylesheets nach dem Stylesheet-Layout von prettier: ein Selektor pro Zeile in Selektorlisten, eine Deklaration pro Zeile, normalisierte Abstände bei Kombinatoren und Werten, kompakt gesetzte einfache Wertelisten, kommaseparierte Listen mit einem Eintrag pro Zeile bei Schatten und Verläufen, Funktionsargumente entweder alle in einer Zeile oder alle mit Zeilenumbruch, erhaltene Leerzeilen und Kommentare sowie unveränderte Präambeln bei unbekannten At-Regeln wie @apply von Tailwind. Lange zusammengesetzte Selektoren werden an Nachfahren-Kombinatoren umgebrochen, und zu lange Argumente von Pseudoklassen werden innerhalb ihrer Klammern umgebrochen.

JSON

formatSource($json, 'json') verwendet den JavaScript-Parser und die Printer erneut, diesmal mit den JSON-Regeln von prettier: Schlüssel bleiben in Anführungszeichen, Strings bleiben unabhängig von singleQuote in doppelten Anführungszeichen, nachgestellte Kommas entfallen immer und //-Kommentare im Dokument bleiben erhalten.

Layoutsemantik

Der Printer setzt das Dokumentmodell von prettier um: Gruppen werden zu einer Zeile zusammengezogen, wenn sie in die Druckbreite passen, und andernfalls umgebrochen; Aufrufargumente bleiben bei einem abschließenden Funktions- oder Objektargument, Elementketten werden bei Überschreiten der Zeilenbreite vor jedem Punkt umgebrochen, mehrzeilig geschriebene Objekte bleiben mehrzeilig, und zwischen Anweisungen bleibt höchstens eine Leerzeile erhalten. Bei mit passenden Optionen von prettier formatiertem Eingabecode ist die Ausgabe bei echtem Code byte-identisch; die Konformitätstestsuite prüft dies genau anhand von Fixtures, die mit prettier selbst erzeugt wurden.

Kommentare

Kommentare werden während der Tokenisierung gesammelt (Parser::setCollectComments(true), im Parser für Tools zugänglich) und als vorangestellte, nachgestellte oder freistehende Anhänge wieder am Baum angebracht. Zeilenkommentare bleiben in ihrer eigenen Zeile, nachgestellte Kommentare in derselben Zeile bleiben bei ihrer Anweisung, Leerzeilen um Kommentare bleiben erhalten und /** ... */-Blöcke werden mit ausgerichteter *-Einrückung neu eingerückt.

Garantien

Für jede formatierte Ausgabe gelten drei Invarianten, die von der Testsuite geprüft werden:

  • Die Ausgabe lässt sich zu einem gleichwertigen Programm parsen (abgesehen von Positionen).
  • Jeder Kommentar aus der Eingabe bleibt in der Ausgabe erhalten.
  • Die Formatierung ist idempotent: Wird eine formatierte Ausgabe erneut formatiert, ändert sich nichts.

Leistung

Formatierung ist so schnell wie das Parsen: Dateien aus der Praxis werden in wenigen Dutzend Millisekunden formatiert, und der handgeschriebene JavaScript-Code eines typischen Projekts wird in einem einzelnen Prozess in deutlich weniger als einer Sekunde komplett formatiert.