Zum Hauptinhalt springen

Prettier 3.1: Neue experimentelle Ternär-Formatierung und Angular-Control-Flow-Syntax!

· 12 Min. Lesezeit
Inoffizielle Beta-Übersetzung

Diese Seite wurde von PageTurner AI übersetzt (Beta). Nicht offiziell vom Projekt unterstützt. Fehler gefunden? Problem melden →

Dieses Release bringt die Einrückung für verschachtelte Ternäroperatoren zurück und führt ein neues --experimental-ternaries-Flag ein, um ein neuartiges "curious ternary"-Format zu testen, das besser mit tief verschachtelten Bedingungen skaliert. Wir sind gespannt auf Ihr Feedback zum experimentellen Format, bevor es später im Jahr zum Standardverhalten wird!

Außerdem haben wir Unterstützung für die Control-Flow-Syntax in Angular v17 hinzugefügt. Details zur Syntax finden Sie im offiziellen Angular-Release-Post.

Falls Sie Prettier schätzen und unsere Arbeit unterstützen möchten, erwägen Sie bitte eine direkte Spende über unser OpenCollective oder durch die Förderung der Projekte, von denen wir abhängen, wie typescript-eslint, remark und Babel. Vielen Dank für Ihre fortlaufende Unterstützung!

Höhepunkte

JavaScript

Einrückung für verschachtelte Ternäroperatoren wieder eingeführt (#9559 von @rattrayalex)

// Input
const message =
i % 3 === 0 && i % 5 === 0
? "fizzbuzz"
: i % 3 === 0
? "fizz"
: i % 5 === 0
? "buzz"
: String(i);


// Prettier 3.0
const message =
i % 3 === 0 && i % 5 === 0
? "fizzbuzz"
: i % 3 === 0
? "fizz"
: i % 5 === 0
? "buzz"
: String(i);

// Prettier 3.1
const message =
i % 3 === 0 && i % 5 === 0
? "fizzbuzz"
: i % 3 === 0
? "fizz"
: i % 5 === 0
? "buzz"
: String(i);

Neue experimentelle Ternär-Formatierung: Ein merkwürdiger Fall der Ternäre (#13183 von @rattrayalex)

Dies ist hinter einem --experimental-ternaries-Flag implementiert.

Wir verschieben das ? in mehrzeiligen Ternäroperatoren an das Ende der ersten Zeile statt an den Anfang der zweiten, zusammen mit mehreren verwandten Änderungen.

Obwohl es zunächst ungewöhnlich wirken mag, zeigen Beta-Tests, dass Entwickler nach wenigen Stunden Nutzung feststellen, dass verschachtelte Ternäroperatoren dadurch deutlich besser lesbar und nützlicher werden.

Dieser PR löst eines unserer am häufigsten bewerteten Issues ohne die Probleme, die die ursprünglich vorgeschlagene Lösung wieder eingeführt hätte.

Weitere Details finden Sie unter Ein merkwürdiger Fall der Ternäre.

Beispiel
// "Questioning" ternaries for simple ternaries:
const content =
children && !isEmptyChildren(children) ?
render(children)
: renderDefaultChildren();

// "Case-style" ternaries for chained ternaries:
const message =
i % 3 === 0 && i % 5 === 0 ? "fizzbuzz"
: i % 3 === 0 ? "fizz"
: i % 5 === 0 ? "buzz"
: String(i);

// Smoothly transitions between "case-style" and "questioning" when things get complicated:
const reactRouterResult =
children && !isEmptyChildren(children) ? children
: props.match ?
component ? React.createElement(component, props)
: render ? render(props)
: null
: null

Unterstützung neuer Syntaxen von Babel 7.23.0 (#15485, #15486, #15487, #15488 von @sosukesuzuki)

Wir unterstützen neue JS-Syntax, die von Babel 7.23.0 unterstützt wird!

Source Phase Imports

Weitere Details finden Sie unter https://github.com/tc39/proposal-source-phase-imports.

import source x from "mod";
Deferred Import Evaluation

Weitere Details finden Sie unter https://github.com/tc39/proposal-defer-import-eval.

import defer * as ns from "mod";
Optional Chaining Assignments

Weitere Details finden Sie unter https://github.com/tc39/proposal-optional-chaining-assignment.

maybeObj?.prop1 = value;

Angular

Unterstützung für die Angular Control Flow (#15606 von @DingWeizhe, @fisker)

Wir haben Unterstützung für die integrierte Control Flow in Angular 17 hinzugefügt. Bitte gebt uns Feedback, falls ihr Fehler findet.

Weitere Details zur Control Flow findet ihr im offiziellen Blog-Artikel.

https://blog.angular.io/introducing-angular-v17-4d7033312e4b

Weitere Änderungen

JavaScript

Korrektur von Kommentaren zwischen Klammern und Funktionsrumpf (#15326 von @fisker)

// Input
function function_declaration()
// this is a function
{
return 42
}

(function function_expression()
// this is a function
{
return 42
})();

// Prettier 3.0
function function_declaration() {
// this is a function
return 42;
}

(function function_expression() // this is a function
{
return 42;
})();

// Prettier 3.1
function function_declaration() {
// this is a function
return 42;
}

(function function_expression() {
// this is a function
return 42;
})();
// Input
function function_declaration()
// this is a function
{
return 42
}

export default function()
// this is a function
{
return 42
}

// Prettier 3.0
TypeError: Cannot read properties of null (reading 'range')

// Prettier 3.1
function function_declaration() {
// this is a function
return 42;
}

export default function () {
// this is a function
return 42;
}

Eindeutigkeit von unären Ausdrücken auf der linken Seite von instanceof und in (#15468 von @lucacasonato)

Es werden nun Klammern um unäre Ausdrücke auf der linken Seite von instanceof- und in-Ausdrücken gesetzt, um den unären Ausdruck auf der linken Seite von einem unären Operator, der auf den gesamten binären Ausdruck angewendet wird, zu unterscheiden.

Dies hilft, einen häufigen Fehler zu vermeiden, bei dem Benutzer eigentlich !("x" in y) schreiben möchten, aber stattdessen !"x" in y schreiben, was tatsächlich als unsinniger Ausdruck (!"x") in y geparst wird.

// Input
!"x" in y;
!("x" in y);

// Prettier 3.0
!"x" in y;
!("x" in y);

// Prettier 3.1
(!"x") in y;
!("x" in y);

Korrektur der Groß-/Kleinschreibung von Selektoren in Styled-Components-Interpolationen (#15472 von @lucasols)

// Input
const StyledComponent = styled.div`
margin-right: -4px;

${Container}.isExpanded & {
transform: rotate(-180deg);
}
`;

const StyledComponent2 = styled.div`
margin-right: -4px;

${abc}.camelCase + ${def}.camelCase & {
transform: rotate(-180deg);
}
`;

// Prettier 3.0
const StyledComponent = styled.div`
margin-right: -4px;

${Container}.isexpanded & {
transform: rotate(-180deg);
}
`;

const StyledComponent2 = styled.div`
margin-right: -4px;

${abc}.camelcase + ${def}.camelCase & {
transform: rotate(-180deg);
}
`;

// Prettier 3.1 -- same as input

Konsistente Formatierung von Zeichenketten mit Escape-Sequenzen (#15525 von @sosukesuzuki)

// Input
export const MSG_GENERIC_OPERATION_FAILURE_BODY_1 =
goog.getMsg("That's all we know");

export const MSG_GENERIC_OPERATION_FAILURE_BODY_2 =
goog.getMsg("That\'s all we know");

// Prettier 3.0
export const MSG_GENERIC_OPERATION_FAILURE_BODY_1 =
goog.getMsg("That's all we know");

export const MSG_GENERIC_OPERATION_FAILURE_BODY_2 = goog.getMsg(
"That's all we know",
);

// Prettier 3.1
export const MSG_GENERIC_OPERATION_FAILURE_BODY_1 =
goog.getMsg("That's all we know");

export const MSG_GENERIC_OPERATION_FAILURE_BODY_2 =
goog.getMsg("That's all we know");

Verbesserte Formatierung bei Zuweisungen, deren linke Seite umgebrochen werden kann (#15547 von @sosukesuzuki)

// Input
params["redirectTo"] =
`${window.location.pathname}${window.location.search}${window.location.hash}`;

// Prettier 3.0
params[
"redirectTo"
] = `${window.location.pathname}${window.location.search}${window.location.hash}`;

// Prettier 3.1
params["redirectTo"] =
`${window.location.pathname}${window.location.search}${window.location.hash}`;

TypeScript

Korrektur instabiler Kommentare nach der letzten Parameter-Eigenschaft (#15324 von @fisker)

// Input
class Class {
constructor(
private readonly paramProp: Type,
// comment
) {
}
}

// Prettier 3.0
class Class {
constructor(private readonly paramProp: Type) // comment
{}
}

// Prettier 3.0 (Second format)
class Class {
constructor(
private readonly paramProp: Type, // comment
) {}
}

// Prettier 3.1
class Class {
constructor(
private readonly paramProp: Type,
// comment
) {}
}

Unterstützung für eingebettete Formatierung in Template-Literals mit as const-Annotation (#15408 von @sosukesuzuki)

// Input
const GQL_QUERY_WITH_CONST = /* GraphQL */ `
query S { shop }
` as const;

// Prettier 3.0
const GQL_QUERY_WITH_CONST = /* GraphQL */ `
query S { shop }
` as const;

// Prettier 3.1
const GQL_QUERY_WITH_CONST = /* GraphQL */ `
query S {
shop
}
` as const;

Korrektur der Kommentarausgabe für den letzten Operanden von Union-Typen (#15409 von @sosukesuzuki)

// Input
type Foo1 = (
| "thing1" // Comment1
| "thing2" // Comment2
)[]; // Final comment1
type Foo2 = (
| "thing1" // Comment1
| "thing2" // Comment2
) & Bar; // Final comment2

// Prettier 3.0
type Foo1 = (
| "thing1" // Comment1
| "thing2"
)[]; // Comment2 // Final comment1
type Foo2 = (
| "thing1" // Comment1
| "thing2"
) & // Comment2
Bar; // Final comment2

// Prettier 3.1
type Foo1 = (
| "thing1" // Comment1
| "thing2" // Comment2
)[]; // Final comment1
type Foo2 = (
| "thing1" // Comment1
| "thing2" // Comment2
) &
Bar; // Final comment2

Beibehaltung erforderlicher Klammern um bestimmte Schlüsselwörter wie Bezeichner in Ausdrucksanweisungen von satisfies-/as-Ausdrücken (#15514 von @seiyab)

// Input
(type) satisfies never;


// Prettier 3.0
type satisfies never;


// Prettier 3.1
(type) satisfies never;

Flow

Unterstützung für as- und satisfies-Ausdrücke in Flow (#15130 von @gkz)

// Input
const x = y as T;

// Prettier 3.0
// <error: unsupported>

// Prettier 3.1
const x = y as T;

Unterstützung für Typ-Argumente in JSX-Opening-Elementen für Flow (#15429 von @SamChou19815)

// Input
<Foo<bar> />;

// Prettier 3.0
<Foo />;

// Prettier 3.1
<Foo<bar> />;

Unterstützung für Typ-Argumente nach typeof (#15466 von @sosukesuzuki)

Unterstützt Typargumente nach der typeof-Syntax, die seit Flow v0.127.0 unterstützt wird:

type Foo = typeof MyGenericClass<string, number>;

SCSS

Aufrufe von SCSS-Funktionen mit führendem Bindestrich nicht aufteilen (#15370 von @auvred)

/* Input */
div {
width: -double(-double(3));
}

/* Prettier 3.0 */
div {
width: -double(- double(3));
}

/* Prettier 3.1 */
div {
width: -double(-double(3));
}

HTML

Formatierung von menu- und marquee-Elementen korrigieren (#15334 von @fisker)

<!-- Input -->
<menu><li><button onclick="copy()">Copy</button></li>
<li><button onclick="cut()">Cut</button></li>
<li><button onclick="paste()">Paste</button></li></menu>
<marquee
direction="down"
width="250"
height="200"
behavior="alternate"
style="border:solid"><marquee behavior="alternate"> This text will bounce </marquee></marquee>

<!-- Prettier 3.0 -->
<menu
><li><button onclick="copy()">Copy</button></li>
<li><button onclick="cut()">Cut</button></li>
<li><button onclick="paste()">Paste</button></li></menu
>
<marquee
direction="down"
width="250"
height="200"
behavior="alternate"
style="border: solid"
><marquee behavior="alternate"> This text will bounce </marquee></marquee
>

<!-- Prettier 3.1 -->
<menu>
<li><button onclick="copy()">Copy</button></li>
<li><button onclick="cut()">Cut</button></li>
<li><button onclick="paste()">Paste</button></li>
</menu>
<marquee
direction="down"
width="250"
height="200"
behavior="alternate"
style="border: solid"
>
<marquee behavior="alternate">This text will bounce</marquee>
</marquee>

Markdown

Kodierung von < und > in Markdown-URLs (#15400 von @vivekjoshi556)

<!-- Input -->
[link](https://www.google.fr/()foo->bar)

<!-- Prettier 3.0 -->
[link](<https://www.google.fr/()foo->bar>)

<!-- Prettier 3.1 -->
[link](<https://www.google.fr/()foo-%3Ebar>)
<!-- Input -->
![link](<https://www.google.fr/()foo->bar>)

<!-- Prettier 3.0 -->
![link](<https://www.google.fr/()foo->bar>)

<!-- Prettier 3.1 -->
![link](<https://www.google.fr/()foo-%3Ebar>)

Zeilen nicht zwischen japanischem Kana und COMBINING KATAKANA-HIRAGANA (SEMI-)VOICED SOUND MARK umbrechen (#15411 von @tats-u)

Dieser PR behebt #15410.

Japanische (halb-)stimmhafte Kana-Zeichen können in zwei Code-Punkte aufgeteilt werden. Beispielsweise kann das folgende Hiragana-Zeichen /ka/ so dargestellt werden:

が (U+304C) → か (U+304B) + ゙ (U+3099) → が (U+304C U+3099)

Die meisten Nutzer begegnen solchen Darstellungen nur in Dateipfaden unter macOS. Einige Zeichen lassen sich jedoch nur so repräsentieren. Manche japanische Texte, die /ŋa̠/ vom üblichen /ga/ unterscheiden müssen (obwohl es heute nicht mehr häufig vorkommt), verwenden den Ausdruck "か゚" (U+304B U+309A).

nasalか゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚

Das obige Markdown wird in Prettier 3.0 so formatiert:

nasalか゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚か゚き゚く゚け
゚こ゚

Der Halbstimmton-Marker wird in eine neue Zeile umgebrochen, was inkorrekt ist. Mit diesem PR wird das Markdown nun so formatiert:

nasalか゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚か゚き゚く゚け゚こ゚か゚き゚く゚
け゚こ゚

Der Halbstimmton-Marker bleibt nun am Hiragana-Zeichen "け" haften.

API

Akzeptiert URL in prettier.{resolveConfig,resolveConfigFile,getFileInfo}() (#15332, #15354, #15360, #15364 von @fisker)

prettier.resolveConfig(), prettier.resolveConfigFile() und prettier.getFileInfo() akzeptieren nun eine URL mit file:-Protokoll oder einen URL-String, der mit file:// beginnt.

// `URL`
await prettier.resolveConfig(new URL("./path/to/file", import.meta.url));
await prettier.resolveConfigFile(new URL("./path/to/file", import.meta.url));
await prettier.getFileInfo(new URL("./path/to/file", import.meta.url));
await prettier.getFileInfo("/path/to/file", {
ignorePath: new URL("./.eslintignore", import.meta.url),
});

// URL string
await prettier.resolveConfig("file:///path/to/file");
await prettier.resolveConfigFile("file:///path/to/file");
await prettier.getFileInfo("file:///path/to/file");
await prettier.getFileInfo("/path/to/file", {
ignorePath: "file:///path/to/.eslintignore",
});

CLI

Verarbeitet nur Dateien, die von Plugins unterstützt werden (#15433 von @sosukesuzuki)

In Prettier 3.0 wurden bei der Angabe eines Verzeichnisses über die CLI nur Dateien mit standardmäßig unterstützten Erweiterungen verarbeitet.

Im folgenden Szenario sollten nicht nur foo.js, sondern auch foo.astro formatiert werden:

# Prettier 3.0 version

$ ls .
foo.js foo.astro

$ cat .prettierrc
{ "plugins": ["prettier-plugin-astro"] }

$ prettier --write .
foo.js 20ms

Mit diesem Update werden nun sowohl foo.js als auch foo.astro formatiert:

# Prettier 3.1 branch

$ prettier --write .
foo.js 20ms
foo.astro 32ms

Sie können prettier "**/*" --ignore-unknown durch prettier . ersetzen, da beide Befehle jetzt gleichwertig sind.

Zeige (unchanged)-Schlüsselwort für Barrierefreiheit in der CLI mit --write (#15467 von @ADTC)

Bisher war die einzige Unterscheidung zwischen einer geänderten und einer unveränderten Datei die graue Farbe des Dateinamens. Im folgenden Beispiel können wir a.js und b.js nicht unterscheiden, da die Farbe fehlt. Dieses Problem wurde behoben, indem das Schlüsselwort (unchanged) hinzugefügt wurde, das die Unterscheidung ohne Farbe zugänglich macht.

prettier --write .

# Prettier 3.0
a.js 0ms
b.js 0ms
c.js 0ms (cached)

# Prettier 3.1
a.js 0ms
b.js 0ms (unchanged)
c.js 0ms (unchanged) (cached)

Behebe Fehler beim Formatieren von Dateinamen mit Sonderzeichen (#15597 von @fisker)

prettier "[with-square-brackets].js" --list

# Prettier 3.0
[error] Explicitly specified file was ignored due to negative glob patterns: "[with-square-brackets].js".

# Prettier 3.1
[with-square-brackets].js