Prettier 1.4: Unterstützung für TypeScript und CSS
Diese Seite wurde von PageTurner AI übersetzt (Beta). Nicht offiziell vom Projekt unterstützt. Fehler gefunden? Problem melden →
Diese Version führt Unterstützung für die Sprachen TypeScript, CSS, Less und SCSS in Prettier ein!
TypeScript-Unterstützung
Dies ist die am häufigsten angefragte Funktion für Prettier. Mit Version 1.4.0 können Sie nun Prettier verwenden, um Ihre .ts- und .tsx-Dateien zu formatieren!
Prettier funktioniert, indem es Projekte verwendet, um eine AST-Darstellung des Codes zu generieren und auszugeben. Sowohl Babylon (der Parser, der Babel antreibt) als auch Flow erzeugen einen AST, der für die JavaScript-Teile ungefähr dem estree-Format folgt, und haben dann spezielle Knoten für Flow-spezifische Elemente.
TypeScript führt, genauso wie Flow, spezielle Knoten für die von ihm eingeführte Syntax ein. Leider folgt es nicht dem estree-Format für den Rest der JavaScript-Sprache. Das bringt uns bei Prettier in eine schwierige Lage, da wir es im Wesentlichen komplett forken müssten, um TypeScript auszugeben.
Diese Inkompatibilität mit dem AST ist kein neues Problem und ein anderes Projekt hatte damit zu kämpfen: ESLint. Weil der AST unterschiedlich ist, funktionieren keine der ESLint-Regeln. Glücklicherweise haben @JamesHenry und @soda0289 ein Projekt namens typescript-eslint-parser geschrieben, das einen TypeScript-AST nimmt und in einen estree-AST konvertiert – genau das, was wir für Prettier brauchen!
Nachdem dieses Projekt in Prettier eingerichtet wurde, haben @azz, @despairblue und @Pajn alle TypeScript-spezifischen Knoten implementiert und sichergestellt, dass die 13.000 Tests der TypeScript-Testsuite korrekt bestehen. Dies war eine enorme Aufgabe und ist nun endlich einsatzbereit :)
Wir haben Prettier an den größten TypeScript-Projekten getestet, die wir auf GitHub finden konnten, um sicherzustellen, dass es korrekten Code ausgibt. Wir haben noch nicht viel Zeit darauf verwendet, die Formatierung des Codes zu optimieren. Wenn Ihnen also etwas seltsam vorkommt, melden Sie bitte ein Issue!
Unterstützung für CSS, Less und SCSS
Während TypeScript die am häufigsten angefragte Funktion aus der Open-Source-Community ist, ist CSS die wichtigste von Facebook-Ingenieuren. Sobald man sich daran gewöhnt hat, Code in einer Sprache automatisch zu formatieren, möchte man das überall tun!
Es stellt sich heraus, dass CSS eine viel kleinere Sprache als JavaScript ist und die Unterstützung nur wenige Tage dauerte. Wir verwenden postcss von @ai als zugrunde liegenden Parser, der CSS, Less und SCSS parsen kann. Außerdem setzen wir auf postcss-values-parser, postcss-selector-parser von @ben-eb und postcss-media-query-parser von @dryoma.
Leider parst postcss derzeit weder Sass noch Stylus. Wir würden sie gerne unterstützen, wenn jemand bereit ist, die Arbeit für deren Ausgabe zu übernehmen.
Beachten Sie, dass Prettier derzeit nur den Code formatiert. Es berücksichtigt noch keine Optionen wie singleQuote und führt auch keine Farb- oder Zahlenormalisierung durch, wie wir es für JavaScript tun.
Editor-Integration
Die erste Phase des Projekts bestand darin, dass Prettier korrekten und gut aussehenden Code ausgibt. Jetzt, da es in guter Verfassung ist, können wir uns Zeit nehmen, um die Integrationen zu verbessern. Wir haben gerade Unterstützung für zwei großartige Funktionen eingeführt: Beibehalten der Cursorposition und die Möglichkeit, einen Bereich anstatt der gesamten Datei zu formatieren.
Beachte, dass wir die Unterstützung gerade erst in Prettier selbst integriert haben – noch nutzt keine der Editor-Integrationen diese Funktion. Außerdem haben wir sie praktisch noch nicht umfassend getestet, daher werden wir wahrscheinlich noch einige Ecken und Kanten ausbügeln müssen!
Hinzufügen der cursorOffset-Option für Cursor-Positionierung (#1637) von @josephfrazier
Bisher überlassen wir es den Editoren, die Cursor-Position zu bestimmen, was sie einigermaßen gut machen. Da wir aber den Code selbst ausgeben, können wir die genaue Position liefern!
Hinzufügen der --range-start/end-Optionen zum Formatieren von Codeabschnitten (#1609) von @josephfrazier
Diese oft gewünschte Funktion ermöglicht jetzt das Formatieren von Codebereichen, während Prettier bisher nur ganze Dateien verarbeitete.
Die Funktion durchläuft den AST rückwärts, um die nächstgelegene Anweisung zu finden. Dadurch muss der markierte Bereich nicht exakt syntaktisch valide sein – eine grobe Auswahl genügt!
Hinzufügen der filepath-Option zur Dateityp-Erkennung (#1835) von @mitermayer
Da wir jetzt CSS und TypeScript formatieren, ist die manuelle Parser-Angabe unpraktisch. Mit dem Dateipfad ermittelt Prettier automatisch den passenden Parser anhand der Dateiendung.
Höhepunkte
Textumbruch in JSX-Inhalten (#1120, #1671, #1827, #1829) von @karl
Das größte verbliebene Problem bei JSX-Formatierungen war der Umgang mit Textinhalten. Statt hässliche {" "}-Elemente einzufügen oder lange Zeilen unverändert zu lassen, behandeln wir jetzt jedes Wort als Token für korrekten Umbruch.
Diese herausragende Arbeit von @karl führte nicht nur die Funktion ein, sondern etablierte auch ein neues Grundprinzip in Prettier: Sequenzen brechen automatisch, sobald ein Element die Zeilenlänge überschreitet.
// Before
<div>
Please state your
{" "}
<b>name</b>
{" "}
and
{" "}
<b>occupation</b>
{" "}
for the board of directors.
</div>
// After
<div>
Please state your <b>name</b> and <b>occupation</b> for the board of
directors.
</div>
Entfernen von Klammern bei JSX in Pfeilfunktionen (#1733) von @xixixao
Ein Gewinn für funktionale Komponenten: Pfeilfunktionen, die JSX zurückgeben, benötigen keine umschließenden Klammern mehr.
// Before
const render1 = ({ styles }) => (
<div style={styles}>
Keep the wrapping parens. Put each key on its own line.
</div>
);
// After
const render1 = ({ styles }) =>
<div style={styles}>
Keep the wrapping parens. Put each key on its own line.
</div>;
Verbesserte Template-Literal-Formatierung (#1664, #1714) von @josephfrazier
Template-Literals bereiteten Prettier stets Schwierigkeiten. Version 1.3.0 verbesserte dies bereits deutlich – jetzt behandeln wir alle gängigen Fälle optimal.
Eine Workaround-Utility, die Leerzeilen entfernte, führte zu seltsamen Ergebnissen und wurde entfernt. Statt beim ${-Start einzurücken, beginnt die Einrückung nun bei der Zeile, die ${ enthält.
Lasst uns wissen, ob ihr weiterhin Probleme mit der Ausgabe von Template-Literals nach diesem Release habt!
// Before
const Bar = styled.div`
color: ${props => (props.highlight.length > 0 ? palette([
'text',
'dark',
'tertiary'
])(props) : palette([
'text',
'dark',
'primary'
])(props))} !important;
`
// After
const Bar = styled.div`
color: ${props =>
props.highlight.length > 0
? palette(["text", "dark", "tertiary"])(props)
: palette(["text", "dark", "primary"])(props)} !important;
`
Gleiche Umbruchregeln für Zuweisungen und Objektwerte verwenden (#1721)
Wir haben viel Feinjustierung für den Umbruch nach Zuweisungen (z.B. a = ...). Diese Regeln wenden wir nun auch auf Objektwerte an. Das sollte bei mehrzeiliger boolescher Logik oder großen Bedingungen helfen. Dies ist auch ein gutes Beispiel dafür, wie wir einen konsistenten Drucker erstellen können.
// Before
const o = {
somethingThatsAReallyLongPropName: this.props.cardType ===
AwesomizerCardEnum.SEEFIRST,
};
// After
const o = {
somethingThatsAReallyLongPropName:
this.props.cardType === AwesomizerCardEnum.SEEFIRST,
};
Bedingungen innerhalb von !() einrücken (#1731)
Es gab kontinuierlich Beschwerden über die Darstellung, und es stand auf der Liste der Dinge, die wahrscheinlich schwer umzusetzen sind und später überprüft werden sollten. Es stellte sich jedoch als super einfach heraus – also bitte sehr!
// Before
const anyTestFailures = !(aggregatedResults.numFailedTests === 0 &&
aggregatedResults.numRuntimeErrorTestSuites === 0);
// After
const anyTestFailures = !(
aggregatedResults.numFailedTests === 0 &&
aggregatedResults.numRuntimeErrorTestSuites === 0
);
Formatkorrekturen
Schleifenkörper bei Möglichkeit in derselben Zeile belassen (#1498)
Wir haben dies bereits bei if-Anweisungen umgesetzt. Für Konsistenz sollten wir es auch bei Schleifen tun.
// Before
for (a in b)
var c = {};
// After
for (a in b) var c = {};
Leerzeile bei Flow-Union-Typen beheben (#1511) von @existentialism
Wir sollten nichts doppelt einrücken ;)
// Before
type Foo = Promise<
| { ok: true, bar: string, baz: SomeOtherLongType }
| { ok: false, bar: SomeOtherLongType }
>;
// After
type Foo = Promise<
{ ok: true, bar: string, baz: SomeOtherLongType } |
{ ok: false, bar: SomeOtherLongType }
>;
Keine Klammern für einzelnes Argument mit Endzeilenkommentar (#1518)
Die Erkennungslogik für Klammern bei Pfeilfunktionen prüfte bisher nur auf Kommentare generell. Stattdessen wollen wir nur Inline-Kommentare wie (/* comment */ num) berücksichtigen, nicht aber Endzeilenkommentare.
// Before
KEYPAD_NUMBERS.map((num) => ( // Buttons 0-9
<div />
));
KEYPAD_NUMBERS.map(num => ( // Buttons 0-9
<div />
));
Verschachtelte ternäre Operatoren nicht einrücken (#1822)
Dies vermeidet den Eindruck einer 4-Zeichen-Einrückung statt zwei. Nachteilig ist, dass mehrzeilige Bedingungen nicht exakt ausgerichtet werden. Wir halten dies für den besseren Kompromiss, da verschachtelte ternäre Operatoren meist kurze Bedingungen haben.
// Before
aaaaaaaaaaaaaaa
? bbbbbbbbbbbbbbbbbb
: ccccccccccccccc
? ddddddddddddddd
: eeeeeeeeeeeeeee ? fffffffffffffff : gggggggggggggggg;
// After
aaaaaaaaaaaaaaa
? bbbbbbbbbbbbbbbbbb
: ccccccccccccccc
? ddddddddddddddd
: eeeeeeeeeeeeeee ? fffffffffffffff : gggggggggggggggg;
Verkettete Bedingungen innerhalb von JSX-Attributen inline setzen (#1519)
Eine Einrückung zur Blockabgrenzung ist unnötig, da danach nichts mehr folgen kann.
// Before
<div
src={
!isEnabled &&
diffUpdateMessageInput != null &&
this.state.isUpdateMessageEmpty
}
/>;
// After
<div
src={
!isEnabled &&
diffUpdateMessageInput != null &&
this.state.isUpdateMessageEmpty
}
/>;
Überflüssige Escape-Zeichen in Strings entfernen (#1575) von @josephfrazier
Wir optimieren Strings bereits auf verschiedene Weise – diese Ergänzung entfernt unnötige \-Zeichen.
// Before
a = 'hol\a';
// After
a = 'hola';
Boolesche Logik für leere Objekte korrigieren (#1590) von @dmitrika
Objekte in booleschen Ausdrücken sollten inline bleiben, da eine eigenständige {-Zeile seltsam wirkt. Bei leeren Objekten führte dies jedoch zu Problemen, daher bleiben diese in einer eigenen Zeile.
const x = firstItemWithAVeryLongNameThatKeepsGoing ||
secondItemWithALongNameAsWell || {};
// After
const x =
firstItemWithAVeryLongNameThatKeepsGoing ||
secondItemWithALongNameAsWell ||
{};
Klammern bei Sequenzausdrücken in For-Schleifen entfernen (#1597) von @k15a
Mehrfachzuweisungen in For-Schleifen sind üblich – wir setzen nun keine Klammern mehr.
// Before
for ((i = 0), (len = arr.length); i < len; i++) {
// After
for (i = 0, len = arr.length; i < len; i++) {
Pfeilfunktionen nicht inline setzen bei vorangestelltem Kommentar (#1660)
Blockkommentare innerhalb von Pfeilfunktionen werden jetzt korrekt behandelt!
// Before
export const bem = block => /**
* @param {String} [element] - the BEM Element within that block; if undefined, selects the block itself.
*/
element => /**
* @param {?String} [modifier] - the BEM Modifier for the Block or Element; if undefined, selects the Block or Element unmodified.
*/
modifier =>
// After
export const bem = block =>
/**
* @param {String} [element] - the BEM Element within that block; if undefined, selects the block itself.
*/
element =>
/**
* @param {?String} [modifier] - the BEM Modifier for the Block or Element; if undefined, selects the Block or Element unmodified.
*/
modifier =>
Letzte Kommentare bei Imports korrigieren (#1677)
Ein weiterer Bereich, in dem wir Speziallogik für Kommentare benötigen!
// Before
import {
ExecutionResult,
DocumentNode,
/* tslint:disable */
SelectionSetNode,
} /* tslint:enable */ from 'graphql';
// After
import {
DocumentNode,
/* tslint:disable */
SelectionSetNode,
/* tslint:enable */
} from 'graphql';
Kommentare in Member-Ketten behandeln (#1686, #1691)
Zuvor wurden nur bestimmte Platzierungen behandelt – jetzt gehen wir einen allgemeineren Ansatz. Hoffentlich treten diese Probleme künftig nicht mehr auf.
// Before
const configModel = this.baseConfigurationService.getCache().consolidated // global/default values (do NOT modify)
.merge(this.cachedWorkspaceConfig);
// After
const configModel = this.baseConfigurationService
.getCache()
.consolidated // global/default values (do NOT modify)
.merge(this.cachedWorkspaceConfig);
expandLast für verschachtelte Pfeilfunktionen verwenden (#1720)
// Before
f(action => next =>
next(action));
// After
f(action => next =>
next(action),
);
JSX-Kommentare innerhalb der Klammern platzieren (#1712)
Betrifft vor allem Facebook-Entwickler, wo bei neuen Flow-Versionen automatisch $FlowFixMe hinzugefügt wird. Diese Kommentare werden nun nicht mehr durcheinandergebracht.
// Before
const aDiv = /* $FlowFixMe */
(
<div className="foo">
Foo bar
</div>
);
// After
const aDiv = (
/* $FlowFixMe */
<div className="foo">
Foo bar
</div>
);
Zeilenumbruch bei mehreren Variablendeklarationen erzwingen (#1723)
Häufig angefragt: Bisher brachen wir nur bei >80 Spalten um. Jetzt immer, wenn mindestens eine Zuweisung existiert.
// Before
var numberValue1 = 1, numberValue2 = 2;
// After
var numberValue1 = 1,
numberValue2 = 2;
Inline | null und | void halten (#1734)
Ausgeschriebene Flow-Union-Typen sehen bei Objekten gut aus, bei Nullability jedoch seltsam. Daher setzen wir jetzt | null und | void inline.
// Before
interface RelayProps {
articles:
| Array<
| {
__id: string,
}
| null
>
| null
}
// After
interface RelayProps {
articles: Array<{
__id: string,
} | null> | null,
}
Bei implements statt extends umbrechen (#1730)
Kein Umbruch mehr bei extends. Verbessert das Aussehen von Klassen mit potenziell umbruchbedürftigen Erweiterungen.
// Before
class MyContractSelectionWidget
extends React.Component<
void,
MyContractSelectionWidgetPropsType,
void
> {
method() {}
}
// After
class MyContractSelectionWidget extends React.Component<
void,
MyContractSelectionWidgetPropsType,
void
> {
method() {}
}
Einzelne Importe inline halten (#1729)
Analog zu langen require-Aufrufen: import-Anweisungen werden bei Einzelimporten nicht mehr umgebrochen.
// Before
import somethingSuperLongsomethingSuperLong
from "somethingSuperLongsomethingSuperLongsomethingSuperLong";
// After
import somethingSuperLongsomethingSuperLong from "somethingSuperLongsomethingSuperLongsomethingSuperLong";
Umbruchmöglichkeit für SequenceExpression hinzufügen (#1749)
Wussten Sie, dass man bei reinen Ausdrücken statt {} einfach () und statt ; ein , verwenden könnte? Manche nutzen das bei Arrow-Function-Returns. Nicht empfohlen, aber einfach zu unterstützen ¯\_(ツ)_/¯
// Before
const f = (argument1, argument2, argument3) =>
(doSomethingWithArgument(argument1), doSomethingWithArgument(
argument2
), argument1);
// After
const f = (argument1, argument2, argument3) => (
doSomethingWithArgument(argument1),
doSomethingWithArgument(argument2),
argument1
);
Kein erzwungener Zeilenumbruch bei leeren Schleifenkörpern (#1815)
Leere Schleifenkörper {} werden nicht mehr in zwei Zeilen aufgeteilt.
// Before
while (true) {
}
// After
while (true) {}
Leerzeilen zwischen Switch-Cases mit Kommentaren erhalten (#1708)
// Before
switch (true) {
case true:
// Good luck getting here
case false:
}
// After
switch (true) {
case true:
// Good luck getting here
case false:
}
Korrektheit
Entfernung von ast-types (#1743, #1744, #1745, #1746, #1747)
Früher haben wir Kommentarpositionen durch AST-Traversierung mit ast-types-Definitionen ermittelt. Dies verursachte gelegentlich Probleme bei undefinierten Feldern – wir fanden den Knoten nicht und platzierten Kommentare falsch oder warfen Fehler. Tatsächlich benötigen wir diese Mapping-Logik nicht und können einfach Objekte traversieren: Jedes Objekt mit einem type-Feld ist ein Knoten.
// Before
Error: did not recognize object of type "ObjectTypeSpreadProperty"
// After
type X = {...Y/**/};
type X = {/**/...Y};
Ungewöhnliche Unicode-Leerzeichen erhalten (#1658, #1165) von @karl und @yamafaktory
Unsichtbare Zeichen in JSX-Texten wurden bisher durch normale Leerzeichen ersetzt. Wir verstehen zwar nicht, warum jemand das tun würde, aber jetzt erhalten wir diese Zeichen original!
Verhindern, dass abschließende Template-Literal-Kommentare entweichen (#1580, #1713, #1598, #1713) von @josephfrazier und @k15a
Unsere bisherige Logik für Kommentare in Template-Literalen war komplex und unzuverlässig. Für JSX-{}-Ausdrücke hatten wir bereits eine elegante Lösung: Wir setzen eine Grenze vor der schließenden } und drucken unverarbeitete Kommentare mit Zeilenumbruch vor der } aus. Diese Logik wenden wir jetzt auch auf Template-Literale an.
// Before
`${0} // comment`;
// After
`${
0
// comment
}`;
Klammerung von await korrigieren (#1513, #1595, #1593) von @bakkot und @existentialism
Statt automatischer Klammerung definieren wir alle möglichen Knotenkombinationen mit Klammerregeln – daher bleiben seltene Fälle oft unentdeckt. Für await haben wir die Logik jetzt deutlich robuster gemacht: Klammern werden bei Bedarf hinzugefügt und unnötige entfernt.
// Before
(await spellcheck) && spellcheck.setChecking(false);
new A((await x));
// After
await (spellcheck && spellcheck.setChecking(false));
new A(await x);
Getter/Setter-Informationen in Flow-ObjectTypeProperty erhalten (#1585) von @josephfrazier
Ein weiterer Randfall, den wir bisher nicht korrekt handhabten!
// Before
type T = { method: () => void };
// After
type T = { get method(): void }
Klammern für einzelne Argumente mit Generics hinzufügen (#1814)
Noch ein Fall von tückischen Klammern, die wir vergaßen!
// Before
type ExtractType = <A>B<C> => D
// After
type ExtractType = <A>(B<C>) => D
Fallback auf Nicht-Strict-Mode in Babylon (#1587, #1608) von @josephfrazier
Prettier soll allen JavaScript-Code parsen können. Bei Babylon müssen wir entscheiden, ob eine Datei Strict Mode verwendet. Standardmäßig nutzen wir Strict Mode, da dies der gängigste Fall ist. Bei Oktalliteralen wie 0775 würde das Parsen jedoch scheitern. Jetzt versuchen wir bei Strict-Mode-Fehlern einen zweiten Durchlauf im Non-Strict-Mode. Auch return außerhalb von Funktionen erlauben wir, da es in Node-Dateien gültig ist.
// Before
SyntaxError
// After
return 0775;
CLI
Erlaubt die kombinierte Verwendung von --write mit --list-different (#1633)
Dies ist nützlich, wenn man beide Optionen kombiniert, um beispielsweise in einem Commit-Hook dem Benutzer in einem einzigen Befehl anzuzeigen, was tatsächlich geändert wurde.
Ignorieren von node_modules bei CLI-Ausführung (#1683) von @thymikee
Es passiert leicht, versehentlich den node_modules/-Ordner zu formatieren, was normalerweise unerwünscht ist. Daher deaktivieren wir dies nun standardmäßig und bieten die Option --with-node-modules für den Fall, dass es explizit gewünscht wird.
Berücksichtigung von Dotfiles bei Glob-Mustern (#1844) von @jhgg
Wir haben die Option aktiviert, Dotfiles in der verwendeten Glob-Parsing-Bibliothek zu berücksichtigen. Das bedeutet, dass der Ausdruck * nun auch Dateien wie .eslintrc erfassen wird.

