Zum Hauptinhalt springen

Prettier 3.7: Verbesserte Formatierungskonsistenz und neue Plugin-Funktionen!

· 28 Min. Lesezeit
Inoffizielle Beta-Übersetzung

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

Wir freuen uns, Prettier 3.7 ankündigen zu können! Dieser Release konzentriert sich auf die Verbesserung der TypeScript- und Flow-Erfahrung, insbesondere durch die Vereinheitlichung der Formatierung von Klassen und Schnittstellen für mehr Konsistenz und Vorhersehbarkeit. Außerdem möchten wir Ihre Meinung zu der geplanten Änderung zur Behebung der inkonsistenten Logik beim Drucken der öffnenden Klammer von Klassen- und Schnittstellenkörpern einholen.

Zusätzlich haben wir viele Fehler behoben, Unterstützung für neue Funktionen in Angular 21 und GraphQL 16.12 hinzugefügt sowie Front-Matter-Unterstützung für Handlebars implementiert.

Für Plugin-Entwickler haben wir neue APIs eingeführt, die Ihnen mehr Kontrolle über den Kommentar-Anhang und die Behandlung ignorierter Knoten geben.

Wenn 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. Vielen Dank für Ihre fortwährende Unterstützung!

Höhepunkte

TypeScript

Behebung der inkonsistenten Formatierung zwischen Klassen und Schnittstellen (#18094, #18091, #18215 von @fisker)

In diesem Release lag unser Fokus stark auf der Verbesserung der Konsistenz zwischen der Formatierung von Klassen und Schnittstellen. Bisher wurden diese ähnlichen Konstrukte recht unterschiedlich formatiert, was zu visuellen Inkonsistenzen führte. Wir haben ihre Formatierungsregeln angeglichen, um ein vorhersehbareres und saubereres Ergebnis zu erzielen.

Die zusätzliche Einrückung für Typparameter in Klassen wurde entfernt
// Input
interface MarkDef<
M extends string | Mark = Mark,
ES extends ExprRef | SignalRef = ExprRef | SignalRef,
>
extends A, B {}

declare class MarkDef<
M extends string | Mark = Mark,
ES extends ExprRef | SignalRef = ExprRef | SignalRef,
>
implements A, B {}

// Prettier 3.6
interface MarkDef<
M extends string | Mark = Mark,
ES extends ExprRef | SignalRef = ExprRef | SignalRef,
> extends A,
B {}

declare class MarkDef<
M extends string | Mark = Mark,
ES extends ExprRef | SignalRef = ExprRef | SignalRef,
>
implements A, B {}

// Prettier 3.7
interface MarkDef<
M extends string | Mark = Mark,
ES extends ExprRef | SignalRef = ExprRef | SignalRef,
>
extends A, B {}

declare class MarkDef<
M extends string | Mark = Mark,
ES extends ExprRef | SignalRef = ExprRef | SignalRef,
>
implements A, B {}
Anpassung der Vererbungsdarstellung von Schnittstellen an Klassen
// Input
export interface AreaConfig<ES extends ExprRef | SignalRef>
extends MarkConfig<ES>, PointOverlayMixins<ES>, LineOverlayMixins<ES> {}

export class AreaConfig<ES extends ExprRef | SignalRef>
implements MarkConfig<ES>, PointOverlayMixins<ES>, LineOverlayMixins<ES> {}

// Prettier 3.6
export interface AreaConfig<ES extends ExprRef | SignalRef>
extends MarkConfig<ES>,
PointOverlayMixins<ES>,
LineOverlayMixins<ES> {}

export class AreaConfig<ES extends ExprRef | SignalRef>
implements MarkConfig<ES>, PointOverlayMixins<ES>, LineOverlayMixins<ES> {}

// Prettier 3.7
export interface AreaConfig<ES extends ExprRef | SignalRef>
extends MarkConfig<ES>, PointOverlayMixins<ES>, LineOverlayMixins<ES> {}

export class AreaConfig<ES extends ExprRef | SignalRef>
implements MarkConfig<ES>, PointOverlayMixins<ES>, LineOverlayMixins<ES> {}
Vereinheitlichung der Darstellung einzelner Vererbungen mit Superklassen
// Input
class ExtendsLongOneWithGenerics
extends
Bar<
SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType,
ToBreakLineToBreakLineToBreakLine,
> {}
class ExtendsLongOneWithGenerics
implements
Bar<
SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType,
ToBreakLineToBreakLineToBreakLine,
> {}
interface ExtendsLongOneWithGenerics
extends
Bar<
SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType,
ToBreakLineToBreakLineToBreakLine,
> {}

// Prettier 3.6
class ExtendsLongOneWithGenerics extends Bar<
SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType,
ToBreakLineToBreakLineToBreakLine
> {}
class ExtendsLongOneWithGenerics
implements
Bar<
SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType,
ToBreakLineToBreakLineToBreakLine
> {}
interface ExtendsLongOneWithGenerics
extends Bar<
SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType,
ToBreakLineToBreakLineToBreakLine
> {}

// Prettier 3.7
class ExtendsLongOneWithGenerics extends Bar<
SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType,
ToBreakLineToBreakLineToBreakLine
> {}
class ExtendsLongOneWithGenerics implements Bar<
SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType,
ToBreakLineToBreakLineToBreakLine
> {}
interface ExtendsLongOneWithGenerics extends Bar<
SomeLongTypeSomeLongTypeSomeLongTypeSomeLongType,
ToBreakLineToBreakLineToBreakLine
> {}
Inkonsistente Logik beim Drucken der öffnenden Klammer von Klassen- und Schnittstellenkörpern

In Prettier v2.3 haben wir begonnen, die öffnende { des Klassenkörpers in einer neuen Zeile auszugeben, wenn die Klasse mehrere Vererbungen hat, um die visuelle Trennung zwischen Klassenkopf und -körper zu verbessern.

// Prettier 2.2
class loooooooooooooooooooong
extends looooooooooooooooooong
implements loooooooooooooooooooong {
property: string;
}

// Prettier 2.3
class loooooooooooooooooooong
extends looooooooooooooooooong
implements loooooooooooooooooooong
{
property: string;
}

Allerdings sind nicht alle mit dieser Änderung zufrieden.

Teilen Sie uns Ihre Meinung zur Anwendung dieser Änderung auf Schnittstellen mit, indem Sie einen Kommentar zu diesem Issue hinterlassen.

Falls Sie eine bessere Lösung für dieses Problem haben, diskutieren wir diese gerne mit Ihnen.

Sofern keine bessere Lösung gefunden wird, werden wir die Darstellung des Schnittstellenkörpers in Prettier v4 an die von Klassenkörpern angleichen.

// Input
declare class loooooooooooooooooooong
implements looooooooooooooooooong, loooooooooooooooooooong {
property: string;
}

interface loooooooooooooooooooong
extends looooooooooooooooooong, loooooooooooooooooooong {
property: string;
}

// Prettier 3.7
declare class loooooooooooooooooooong
implements looooooooooooooooooong, loooooooooooooooooooong
{
property: string;
}

interface loooooooooooooooooooong
extends looooooooooooooooooong, loooooooooooooooooooong { // <-- This
property: string;
}

Diese Änderungen betreffen auch die Flow-Syntax

Weitere Änderungen

JavaScript

Ermöglichen des Umbruchs von Import-Attributen in mehrere Zeilen (#17329 von @fisker)

// Input
import syntaxImportAssertions from "@babel/plugin-syntax-import-assertions" with {
BABEL_8_BREAKING: "false",
USE_ESM: "true", IS_STANDALONE: "false" };

// Prettier 3.6
import syntaxImportAssertions from "@babel/plugin-syntax-import-assertions" with { BABEL_8_BREAKING: "false", USE_ESM: "true", IS_STANDALONE: "false" };

// Prettier 3.7
import syntaxImportAssertions from "@babel/plugin-syntax-import-assertions" with {
BABEL_8_BREAKING: "false",
USE_ESM: "true",
IS_STANDALONE: "false",
};

Unterstützung für den "Discard Bindings"-Vorschlag hinzugefügt (#17708 von @fisker)

Der Stage-2-Vorschlag "Discard Bindings" wird nun über Babel unterstützt. Beachten Sie bitte auch unsere Richtlinie zu nicht standardisierter Syntax, bevor Sie diese vorgeschlagene Syntaxfunktion mit Prettier verwenden.

const [void] = x;

const {x:void} = x;

Behebung inkonsistenter Kommentarformatierung (#17723 von @fisker)

// Input
if (
true
// This is a really complicated part of the condition, so we need a big ol'
// comment here to explain it.
&& flibble.blibble.blobble?.bloo
) {
doThings();
}

// Prettier 3.6 (--parser=typescript --experimental-operator-position=start)
if (
true
&& // This is a really complicated part of the condition, so we need a big ol'
// comment here to explain it.
flibble.blibble.blobble?.bloo
) {
doThings();
}

// Prettier 3.6 (--parser=babel --experimental-operator-position=start)
if (
true
// This is a really complicated part of the condition, so we need a big ol'
// comment here to explain it.
&& flibble.blibble.blobble?.bloo
) {
doThings();
}

// Prettier 3.7
if (
true
// This is a really complicated part of the condition, so we need a big ol'
// comment here to explain it.
&& flibble.blibble.blobble?.bloo
) {
doThings();
}

Unterstützung zusätzlicher Playwright-Testfunktionen hinzugefügt (#17876 von @BPScott)

Prettier verhindert bereits Änderungen an der Einrückung von Testfunktionen, wenn .skip hinzugefügt wird. Jetzt behandelt es auch die Playwright-Funktionen test.fixme, test.describe.skip und test.describe.fixme ähnlich wie test.skip.

// Input
test.fixme("does something really long and complicated so I have to write a very long name for the test", () => {
// code
});

test.describe.skip("does something really long and complicated so I have to write a very long name for the test", () => {
// code
});

test.describe.fixme("does something really long and complicated so I have to write a very long name for the test", () => {
// code
});

// Prettier 3.6
test.fixme(
"does something really long and complicated so I have to write a very long name for the test",
() => {
// code
},
);

test.describe.skip(
"does something really long and complicated so I have to write a very long name for the test",
() => {
// code
},
);

test.describe.fixme(
"does something really long and complicated so I have to write a very long name for the test",
() => {
// code
},
);

// Prettier 3.7
test.fixme("does something really long and complicated so I have to write a very long name for the test", () => {
// code
});

test.describe
.skip("does something really long and complicated so I have to write a very long name for the test", () => {
// code
});

test.describe
.fixme("does something really long and complicated so I have to write a very long name for the test", () => {
// code
});

Vermeidung von Zeilenumbrüchen in {import,require.resolve,require.resolve.paths,import.meta.resolve}() mit langen Modulnamen (#17882, #17908 von @kovsu & @fisker)

// Input
const a = require("./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module");
const b = require.resolve("./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module");
const c = require.resolve.paths("./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module");

const d = await import("./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module")
const e = import.meta.resolve("./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module");

// Prettier 3.6
const a = require("./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module");
const b = require.resolve(
"./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module",
);
const c = require.resolve.paths(
"./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module",
);

const d = await import(
"./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module"
);
const e = import.meta.resolve(
"./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module",
);

// Prettier 3.7
const a = require("./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module");
const b =
require.resolve("./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module");
const c = require.resolve
.paths("./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module");

const d =
await import("./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module");
const e = import.meta
.resolve("./a/long/long/long/long/long/long/long/long/long/long/long/path/to/module");

Verbesserte Kommentarverarbeitung innerhalb von if-Anweisungen (#17998 von @fisker)

// Input
if (foo) // comment
{
doThing();
} else // comment for else
{
doSomethingElse();
}

// Prettier 3.6
if (foo) {
// comment
doThing();
} // comment for else
else {
doSomethingElse();
}

// Prettier 3.7
if (foo) // comment
{
doThing();
} else // comment for else
{
doSomethingElse();
}

Verbesserte Behandlung von require()-Aufrufen mit Kommentaren (#18037 von @fisker)

// Input
require(
// Comment
"foo"
);

// Prettier 3.6
require(// Comment
"foo");

// Prettier 3.7
require(
// Comment
"foo",
);

Entfernung der Einrückung in logischen Ausdrücken innerhalb von Boolean()-Aufrufen (#18087 von @kovsu)

Reduziert Diff-Änderungen bei Umkehrung von Bedingungen oder Wechsel zwischen !! und Boolean().

// Input
const foo = Boolean(
a_long_long_condition ||
a_long_long_long_condition ||
a_long_long_long_condition
);
const bar = !!(
a_long_long_condition ||
a_long_long_long_condition ||
a_long_long_long_condition
);

// Prettier 3.6
const foo = Boolean(
a_long_long_condition ||
a_long_long_long_condition ||
a_long_long_long_condition,
);
const bar = !!(
a_long_long_condition ||
a_long_long_long_condition ||
a_long_long_long_condition
);

// Prettier 3.7
const foo = Boolean(
a_long_long_condition ||
a_long_long_long_condition ||
a_long_long_long_condition
);
const bar = !!(
a_long_long_condition ||
a_long_long_long_condition ||
a_long_long_long_condition
);

Korrektur der Kommentarverarbeitung für for-Anweisungen (#18099 von @fisker, @sosukesuzuki)

// Input
for (x of y)
// Comment
bar();

// Prettier 3.6
// Comment
for (x of y) bar();

// Prettier 3.7
for (x of y)
// Comment
bar();

Verbesserte Kommentarformatierung um leere Anweisungen (#18108 von @fisker)

// Input
for (
index = 0;
doSomething(foo[index]) !== bar && doSomething(foo[index]) !== baz;
index ++
) /* No op */;

// Prettier 3.6
for (
index = 0;
doSomething(foo[index]) !== bar && doSomething(foo[index]) !== baz;
index++ /* No op */
);

// Prettier 3.7
for (
index = 0;
doSomething(foo[index]) !== bar && doSomething(foo[index]) !== baz;
index++
) /* No op */ ;

Konsistente Kommentarformatierung zwischen Klassenmethoden und Objektmethoden (#18147 von @fisker)

// Input
class x {
method() // Class method
{
return 1
}
}

const object = {
method() // Object method
{
return 1
}
}

// Prettier 3.6
class x {
method() { // Class method
return 1;
}
}

const object = {
method() {
// Object method
return 1;
},
};

// Prettier 3.7
class x {
method() {
// class method
return 1;
}
}

const object = {
method() {
// object method
return 1;
},
};

Fehlende Klammern bei bitweisen Operatoren ergänzt (#18163 von @fs0414)

// Input
1 << (bit % 8);
1 >> (bit - 8);

// Prettier 3.6
1 << bit % 8;
1 >> (bit - 8);

// Prettier 3.7
1 << (bit % 8);
1 >> (bit - 8);

Konsistente Zeilenumbrüche für Array-Literale (#18172 von @Dunqing, @fisker)

// Input
assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides___(-1, -1), [1]);
assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(-1, -1), [1, 2]);

// Prettier 3.6
assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides___(-1, -1), [
1,
]);
assert.deepStrictEqual(
linesCollection.getViewLinesIndentGuides(-1, -1),
[1, 2],
);

// Prettier 3.7
assert.deepStrictEqual(
linesCollection.getViewLinesIndentGuides___(-1, -1),
[1],
);
assert.deepStrictEqual(
linesCollection.getViewLinesIndentGuides(-1, -1),
[1, 2],
);

Konsistente Formatierung logischer Ausdrücke (#18205 von @fisker)

// Input
fn(
a &&
a_long_long_long_long_long_long_long_long_long_long_long_long_long_condition
? a
: b
);

new Fn(
a &&
a_long_long_long_long_long_long_long_long_long_long_long_long_long_condition
? a
: b
);

// Prettier 3.6
fn(
a &&
a_long_long_long_long_long_long_long_long_long_long_long_long_long_condition
? a
: b,
);

new Fn(
a &&
a_long_long_long_long_long_long_long_long_long_long_long_long_long_condition
? a
: b,
);

// Prettier 3.7
fn(
a &&
a_long_long_long_long_long_long_long_long_long_long_long_long_long_condition
? a
: b,
);

new Fn(
a &&
a_long_long_long_long_long_long_long_long_long_long_long_long_long_condition
? a
: b,
);

Einheitliche Formatierung zwischen CallExpression und NewExpression (#18206 von @fisker)

// Input
TelemetryTrustedValue(
instance.capabilities.get(
TerminalCapability?.PromptTypeDetection
)?.promptType
)

new TelemetryTrustedValue(
instance.capabilities.get(
TerminalCapability?.PromptTypeDetection
)?.promptType
)

// Prettier 3.6
TelemetryTrustedValue(
instance.capabilities.get(TerminalCapability?.PromptTypeDetection)
?.promptType,
);

new TelemetryTrustedValue(
instance.capabilities.get(
TerminalCapability?.PromptTypeDetection,
)?.promptType,
);

// Prettier 3.7
TelemetryTrustedValue(
instance.capabilities.get(TerminalCapability?.PromptTypeDetection)
?.promptType,
);

new TelemetryTrustedValue(
instance.capabilities.get(TerminalCapability?.PromptTypeDetection)
?.promptType,
)

Überflüssige Klammern um JSX-Elemente entfernt (#18243 von @fisker)

// Input
new A(
<div>
<div></div>
</div>
)

// Prettier 3.6
new A(
(
<div>
<div></div>
</div>
),
);

// Prettier 3.7
new A(
<div>
<div></div>
</div>,
);

Verbesserte Formatierung von logischen Ausdrücken als Aufrufziel von new-Ausdrücken (#18245 von @fisker)

// Input
a = new (
a_long_long_long_long_condition || a_long_long_long_long_condition || a_long_long_long_long_condition
)();

// Prettier 3.6
a = new (a_long_long_long_long_condition ||
a_long_long_long_long_condition ||
a_long_long_long_long_condition)();

// Prettier 3.7
a = new (
a_long_long_long_long_condition ||
a_long_long_long_long_condition ||
a_long_long_long_long_condition
)();

Entferne leere Zeile in for-Anweisungen ohne "update"-Teil (#18300 von @fisker)

// Input
for ( let i = 0, j = 0, len = allMatches.length, lenJ = selections.length;i < len;) {}

// Prettier 3.6
for (
let i = 0, j = 0, len = allMatches.length, lenJ = selections.length;
i < len;

) {}

// Prettier 3.7
for (
let i = 0, j = 0, len = allMatches.length, lenJ = selections.length;
i < len;
) {}

Verbesserte Formatierung von Superklassen (#18325 von @fisker)

// Input
class EnsureNoDisposablesAreLeakedInTestSuiteSuite extends eslint.Rule.RuleModule {};

// Prettier 3.6
class EnsureNoDisposablesAreLeakedInTestSuiteSuite extends eslint.Rule
.RuleModule {}

// Prettier 3.7
class EnsureNoDisposablesAreLeakedInTestSuiteSuite
extends eslint.Rule.RuleModule {}

TypeScript

Korrigiere falsche Positionierung von Kommentaren nach Pfeilfunktionen (#17421 von @o-m12a, @t-mangoe)

// Input
export const test = (): any => /* first line
second line
*/
null;

// Prettier 3.6
export const test = (): any /* first line
second line
*/ => null;

// Prettier 3.6 (Second format)
SyntaxError: Unexpected token (1:22)
> 1 | export const test = (): any /* first line
| ^
2 | second line
3 | */ => null;
4 |

// Prettier 3.7
export const test = (): any =>
/* first line
second line
*/
null;

Füge fehlende Klammern bei Pfeilfunktionen in Instanziierungsausdrücken hinzu (#17724 von @fisker)

// Input
void (<_T extends never>() => {})<never>;

// Prettier 3.6
void <_T extends never>() => {}<never>;

// Prettier 3.7
void (<_T extends never>() => {})<never>;

Korrigiere Formatierung von TSMappedType (#17785 von @fisker)

// Input (--parser=babel-ts)
export type A = B extends { C?: { [D in infer E]?: F } } ? G : H

// Prettier 3.6
TypeError: Cannot read properties of undefined (reading 'startsWith')

// Prettier 3.7
export type A = B extends { C?: { [D in infer E]?: F } } ? G : H;

Drucke trailing comma in TSImportType-Optionen (#17798 von @fisker)

Trailing commas in Import-Type-Attributen waren vor TypeScript v5.9 nicht erlaubt, nun wurde der Fehler behoben.

// Input
type A = import("foo", {
with:{
type:'json',
} // <- Should be a comma here
})

// Prettier 3.6
type A = import("foo", {
with: {
type: "json",
} // <- Should be a comma here
});

// Prettier 3.7
type A = import("foo", {
with: {
type: "json",
}, // <- Should be a comma here
});

Verbesserte Behandlung von Kommentaren in CommonJS require()-Aufrufen (#18035 von @fisker)

// Input
import foo = require(
// Comment
"foo"
);

// Prettier 3.6
import foo = require(// Comment
"foo");

// Prettier 3.7
import foo = require(
// Comment
"foo"
);

Zeilenumbruch nach = in Typparametern (#18043 von @fisker)

// Input
export type OuterType2<
LongerLongerLongerLongerInnerType = LongerLongerLongerLongerLongerLongerLongerLongerOtherType
> = { a: 1 };

// Prettier 3.6
export type OuterType2<
LongerLongerLongerLongerInnerType = LongerLongerLongerLongerLongerLongerLongerLongerOtherType,
> = { a: 1 };

// Prettier 3.7
export type OuterType2<
LongerLongerLongerLongerInnerType =
LongerLongerLongerLongerLongerLongerLongerLongerOtherType,
> = { a: 1 };

Entferne unerwartete Leerzeilen vor Union-Typen (#18109 von @jspereiramoura, @fisker)

// Input
type SuperLongTypeNameLoremIpsumLoremIpsumBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla =
Fooo1000 | Baz2000 | BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
type A = // comment
Fooo1000 | Baz2000 | BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;

// Prettier 3.6
type SuperLongTypeNameLoremIpsumLoremIpsumBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla =

| Fooo1000
| Baz2000
| BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
type A = // comment

| Fooo1000
| Baz2000
| BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;

// Prettier 3.7
type SuperLongTypeNameLoremIpsumLoremIpsumBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla =
| Fooo1000
| Baz2000
| BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
type A = // comment
| Fooo1000
| Baz2000
| BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;

Diese Änderung betrifft ebenfalls die Flow-Syntax

Korrigiere inkonsistente Kommentarformatierung zwischen typescript und flow-Parser (#18110 von @fisker)

// Input
interface A {
a: // Comment
B;
b: // Comment
| Fooo1000
| Baz2000
| BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
c: // Comment
& Fooo1000
& Baz2000
& BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
}

// Prettier 3.6 (--parser=typescript)
interface A {
a: // Comment
B;
b: // Comment
| Fooo1000
| Baz2000
| BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
c: // Comment
Fooo1000 &
Baz2000 &
BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
}

// Prettier 3.6 (--parser=flow)
interface A {
a: B; // Comment
b: // Comment
| Fooo1000
| Baz2000
| BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
c: Fooo1000 & // Comment
Baz2000 &
BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
}

// Prettier 3.7 (Same output for `--parser=typescript` and `--parser=flow`)
interface A {
a: B; // Comment
b: // Comment
| Fooo1000
| Baz2000
| BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
c: // Comment
Fooo1000 &
Baz2000 &
BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
}

Füge fehlendes Semikolon vor Call-Signaturen hinzu (#18118 von @fisker)

// Input
interface A {
foo;
<T>(): T;
}
type B = {
foo;
<T>(): T;
}

// Prettier 3.6 (--no-semi, first format)
interface A {
foo
<T>(): T
}
type B = {
foo
<T>(): T
}

// Prettier 3.6 (--no-semi, second format)
interface A {
foo<T>(): T
}
type B = {
foo<T>(): T
}

// Prettier 3.7
interface A {
foo;
<T>(): T
}
type B = {
foo;
<T>(): T
}

Korrigiere inkonsistente Formatierung von as const zwischen Flow- und TypeScript-Parsern (#18161 von @fisker)

// Input
1 as /* comment */ const;

// Prettier 3.6 (--parser=typescript)
1 as /* comment */ const;

// Prettier 3.6 (--parser=flow)
1 /* comment */ as const;

// Prettier 3.7 (Same output for `--parser=typescript` and `--parser=flow`)
1 /* comment */ as const;

Korrigiere Kommentarpositionierung um as/satisfies-Ausdrücke (#18162 von @fisker)

// Input
1 as /*
comment
*/
const;

// Prettier 3.6 (First format)
1 /*
comment
*/ as const;

// Prettier 3.6 (Second format)
SyntaxError: Unexpected keyword or identifier. (3:4)
1 | 1 /*
2 | comment
> 3 | */ as const;
| ^
4 |

// Prettier 3.7
1 as const /*
comment
*/;

Korrektur falsch ausgerichteter Union-Typen (#18165 von @fisker)

// Input
interface I {
elements: // comment
| [string, ExpressionNode, ExpressionNode]
| [string, ExpressionNode, ExpressionNode, ObjectExpression]
}

// Prettier 3.6
interface I {
elements: // comment
| [string, ExpressionNode, ExpressionNode]
| [string, ExpressionNode, ExpressionNode, ObjectExpression];
}

// Prettier 3.7
interface I {
elements: // comment
| [string, ExpressionNode, ExpressionNode]
| [string, ExpressionNode, ExpressionNode, ObjectExpression];
}

Entfernung überflüssiger Leerzeilen in Union-Typen (#18197 von @Dunqing)

// Input
type SuperLongTypeNameLoremIpsumLoremIpsumBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla =
Fooo1000 | Baz2000 | BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;

// Prettier 3.6
type SuperLongTypeNameLoremIpsumLoremIpsumBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla =

| Fooo1000
| Baz2000
| BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;

// Prettier 3.7
type SuperLongTypeNameLoremIpsumLoremIpsumBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla =
| Fooo1000
| Baz2000
| BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;

Flow

Grundlegende Unterstützung für "match"-Syntax hinzugefügt (#17681 von @fisker)

// Input
const e = match (a) {
1 => true,
'foo' => false,
2 => {obj: 'literal'},
};

// Prettier 3.6
SyntaxError: Unexpected token `{`, expected the token `;` (1:21)
> 1 | const e = match (a) {
| ^
2 | 1 => true,
3 | 'foo' => false,
4 | 2 => {obj: 'literal'},

// Prettier 3.7
const e = match (a) {
1 => true,
"foo" => false,
2 => { obj: "literal" },
};

Unterstützung für Opaque-Typen mit Unter- und Obergrenze hinzugefügt (#17792 von @SamChou19815)

// Input
opaque type Counter super empty extends Box<T> = Container<T>;
opaque type Counter super Box<T> = Container<T>;
declare opaque type Counter super empty extends Box<T>;
declare opaque type Counter super Box<T>;

// Prettier 3.6
SyntaxError: Unexpected identifier, expected the token `=` (1:21)

// Prettier 3.7
opaque type Counter super empty extends Box<T> = Container<T>;
opaque type Counter super Box<T> = Container<T>;
declare opaque type Counter super empty extends Box<T>;
declare opaque type Counter super Box<T>;

CSS

Behandlung von Attributselektoren mit Case-Sensitive- und Uppercase-Case-Insensitive-Flags (#17841, #17865 von @kovsu)

/* Input */
[type=a s],
[type=a S],
[type=a I] {
list-style-type: lower-alpha;
}

/* Prettier 3.6 */
[type="a s"],
[type="a S"],
[type="a I"] {
list-style-type: lower-alpha;
}

/* Prettier 3.7 */
[type="a" s],
[type="a" S],
[type="a" I] {
list-style-type: lower-alpha;
}

Behebung von Abstürzen bei der Formatierung spezieller Custom Properties (#17899 von @fisker)

/* Input */
:root {
--l: , #000;
}

/* Prettier 3.6 */
TypeError: Cannot read properties of undefined (reading 'value')

/* Prettier 3.7 */
:root {
--l: , #000;
}

Korrektur falsch konvertierter Selektoren in CSS-Modulen (#17929 von @kovsu)

/* Input */
:export {
nest: {
myColor: blue;
}
myColor: red;
}

/* Prettier 3.6 */
:export {
nest: {
mycolor: blue;
}
myColor: red;
}

/* Prettier 3.7 */
:export {
nest: {
myColor: blue;
}
myColor: red;
}

Korrektur der Formatierung von CSS-Selektoren mit // (#17938 von @kovsu)

/* Input */
a[href="http://example.com"] {
color: red;
}

/* Prettier 3.6 */
a[href="http://example.com"]
{
color: red;
}

/* Prettier 3.7 */
a[href="http://example.com"] {
color: red;
}

Entfernung unerwünschter Leerzeichen zwischen Schriftgröße und Zeilenhöhe (#18114 von @kovsu)

/* Input */
a {
font: var(--size)/1;
}

/* Prettier 3.6 */
a {
font: var(--size) / 1;
}

/* Prettier 3.7 */
a {
font: var(--size)/1;
}

Behebung übermäßiger Einrückung bei kommagetrennten CSS-Werten nach Blockkommentaren (#18228 von @seiyab)

/* Input */
.foo {
background-image:
linear-gradient(to top, blue, red 100%),
/* texture */
repeating-linear-gradient(90deg, pink, yellow 20px, green 20px, pink 40px),
repeating-linear-gradient(90deg, pink, yellow 20px, green 20px, pink 40px);
}

/* Prettier 3.6 */
.foo {
background-image:
linear-gradient(to top, blue, red 100%),
/* texture */
repeating-linear-gradient(90deg, pink, yellow 20px, green 20px, pink 40px),
repeating-linear-gradient(90deg, pink, yellow 20px, green 20px, pink 40px);
}

/* Prettier 3.7 */
.foo {
background-image:
linear-gradient(to top, blue, red 100%),
/* texture */
repeating-linear-gradient(90deg, pink, yellow 20px, green 20px, pink 40px),
repeating-linear-gradient(90deg, pink, yellow 20px, green 20px, pink 40px);
}

SCSS

Behebung von Klammerabstandsproblemen in Mixin-Argumenten (#17836 von @kovsu)

// Input
.foo {
@include bar('A (B)');
}

// Prettier 3.6
.foo {
@include bar('A( B)');
}

// Prettier 3.7
.foo {
@include bar('A (B)');
}

Korrektur der Formatierung von durch Leerzeichen getrennten Werten (#17903 von @kovsu)

// Input
.foo {
@include transition(min-height ($spacer/2) ease-in-out);
}

// Prettier 3.6
.foo {
@include transition(min-height($spacer/2) ease-in-out);
}

// Prettier 3.7
.foo {
@include transition(min-height ($spacer/2) ease-in-out);
}

Less

Korrektur falsch konvertierter Variablennamen (#17820 von @kovsu)

// Input
@fooBackground:line-gradient(#f00);

a {
background: @fooBackground;
}

// Prettier 3.6
@foobackground:line-gradient (#f00);

a {
background: @fooBackground;
}


// Prettier 3.7
@fooBackground: line-gradient(#f00);

a {
background: @fooBackground;
}

Kompakte Darstellung von Property-/Variablen-Zugriffen beibehalten (#17983 von @kovsu)

// Input
.average(@x, @y) {
@result: ((@x + @y) / 2);
}

div {
padding: .average(16px, 50px) [ @result ];
}

// Prettier 3.6
.average(@x, @y) {
@result: ((@x + @y) / 2);
}

div {
padding: .average(16px, 50px) [ @result];
}

// Prettier 3.7
.average(@x, @y) {
@result: ((@x + @y) / 2);
}

div {
padding: .average(16px, 50px)[@result];
}

HTML

Formatierung des allow-Attributs für iframe-Elemente unterstützt (#17879 von @kovsu)

<!-- Input -->
<iframe allow="layout-animations 'none'; unoptimized-images 'none'; oversized-images 'none'; sync-script 'none'; sync-xhr 'none'; unsized-media 'none';"></iframe>

<!-- Prettier 3.6 -->
<iframe allow="layout-animations 'none'; unoptimized-images 'none'; oversized-images 'none'; sync-script 'none'; sync-xhr 'none'; unsized-media 'none';"></iframe>

<!-- Prettier 3.7 -->
<iframe
allow="
layout-animations 'none';
unoptimized-images 'none';
oversized-images 'none';
sync-script 'none';
sync-xhr 'none';
unsized-media 'none';
"
></iframe>

Formatierung von Inline-Event-Handlern (#17909 von @kovsu)

<!-- Input -->
<button
type="button"
onclick="console .log( 'Hello, this is my old-fashioned event handler!')"
>Press me</button>

<!-- Prettier 3.6 -->
<button
type="button"
onclick="console .log( 'Hello, this is my old-fashioned event handler!')"
>
Press me
</button>

<!-- Prettier 3.7 -->
<button
type="button"
onclick="console.log('Hello, this is my old-fashioned event handler!')"
>
Press me
</button>

Angular

Unterstützung für Angular 21 (#17722, #18294 von @fisker)

Angular 20.1 führte Unterstützung für neue Zuweisungsoperatoren ein. Angular 21 führte Unterstützung für reguläre Ausdrücke ein.

<!-- Input -->
<b (click)="
a ??= b">{{ /\d+/g}}</b>

<!-- Prettier 3.6 -->
<b
(click)="
a ??= b"
>{{ /\d+/g}}</b
>

<!-- Prettier 3.7 -->
<b (click)="a ??= b">{{ /\d+/g }}</b>

Behebt das Duplizieren von Kommentaren in Interpolationen (#17862 von @fisker)

<!-- Input -->
{{a() // comment}}

<!-- Prettier 3.6 -->
{{ a(// comment) // comment }}

<!-- Prettier 3.7 -->
{{
a() // comment
}}

Behebt die Formatierung der "Non-Null Assertion" (#18047 von @fisker)

<!-- Input -->
{{ foo?.bar!.baz }}

<!-- Prettier 3.6 -->
{{ (foo?.bar)!.baz }}

<!-- Prettier 3.7 -->
{{ foo?.bar!.baz }}

Ember / Handlebars

Fügt Unterstützung für Front Matter in Handlebars hinzu (#17781 von @Codezilluh)

Front Matter kann jetzt in Handlebars verwendet werden.

---
title: My page title
keywords:
- word
- other word
---

<h1>{{title}}</h1>
<ul>
{{#each keywords}}
<li>{{this}}</li>
{{/each}}
</ul>

Bewahrt die else if-Syntax für benutzerdefinierte Helfer (#17856 von @kovsu)

{{! Input }}
{{#animated-if this.foo}}
foo content
{{else if (this.bar)}}
bar content
{{/animated-if}}

{{! Prettier 3.6 }}
{{#animated-if this.foo}}
foo content
{{else}}{{#if (this.bar)}}
bar content
{{/if}}{{/animated-if}}

{{! Prettier 3.7 }}
{{#animated-if this.foo}}
foo content
{{else if (this.bar)}}
bar content
{{/animated-if}}

Entfernt überflüssige Leerzeilen in <style>-Tags (#18065 von @kovsu, @fisker)

{{! Input }}
<style>
#foo {
color: red;
}
</style>

{{! Prettier 3.6 (--html-whitespace-sensitivity=ignore) }}
<style>

#foo {
color: red;
}

</style>

{{! Prettier 3.7 (--html-whitespace-sensitivity=ignore) }}
<style>
#foo {
color: red;
}
</style>

Erzwingt keinen Zeilenumbruch von Elementen bei --html-whitespace-sensitivity=ignore (#18133 von @fisker)

{{! Input }}
<div> </div>

{{! Prettier 3.6 (--html-whitespace-ensitivity=ignore) }}
<div>
</div>

{{! Prettier 3.7 (--html-whitespace-ensitivity=ignore) }}
<div></div>

GraphQL

Unterstützt "ausführbare Beschreibungen" (#18214 von @fisker)

# Input
"Description"
query {
node {
id
}
}

# Prettier 3.6
SyntaxError: Syntax Error: Unexpected description, descriptions are supported only on type definitions. (1:1)
> 1 | "Description"
| ^
2 | query {
3 | node {
4 | id

# Prettier 3.7
"Description"
query {
node {
id
}
}

Markdown

Verbessert die Emoji-Größenmessung (#17813 von @seiyab)

Diese Änderung verbessert die Tabellenausrichtung in allen Sprachen.

<!-- Input -->
| | |
| :-: | :-: |
| ✔ | ✘ |
| ✘ | ✔ |
| ✔ | ✘ |

<!-- Input -->
| | |
| :-: | :-: |
| ✔ | ✘ |
| ✘ | ✔ |
| ✔ | ✘ |


<!-- Prettier 3.7 -->
| | |
| :-: | :-: |
| ✔ | ✘ |
| ✘ | ✔ |
| ✔ | ✘ |

Ermittelt den TOML-Parser für Front Matter (#17965 von @kovsu)

TOML Front Matter kann von dem entsprechenden Plugin verarbeitet werden, falls vorhanden. Funktioniert auch für HTML- und CSS-Dateien.

Behebt die Formatierung von starkem Fokus (#18010 von @yin1999)

Dies ist eine ergänzende Korrektur für #17143, bei dem der ursprüngliche Pull Request nicht bestimmen konnte, ob die Inhalte auf der linken und rechten Seite beide Wörter waren.

<!-- Input -->
1***2***3
1**_2_**3

<!-- Prettier 3.6 -->
1**_2_**3
1**_2_**3

<!-- Prettier 3.7 -->
1***2***3
1***2***3

MDX

Behebt das Parsing von import und export (#17996 von @kovsu & @fisker)

{/* Input */}
- import is a word in lists
- export is a word in lists, too!

{/* Prettier 3.6 */}
- import is a word in list
s
- export is a word in lists, too
!

{/* Prettier 3.7 */}
- import is a word in lists
- export is a word in lists, too!

YAML

Bewahrt eine Leerzeile zwischen Map und Kommentar (#17843 von @kovsu)

# Input
only: issues

# Comment

# Prettier 3.6
only: issues
# Comment

# Prettier 3.7
only: issues

# Comment

Explizites Dokument-Endemarker beibehalten (#18296 by @fisker)

# Input
a: a
---
b: b
...
c: c
...
---
d: d

# Prettier 3.6
a: a
---
b: b
---
c: c
---
d: d

# Prettier 3.7
a: a
---
b: b
...
c: c
...
---
d: d

Expliziten Schlüsselstil für Flow-Mapping-Schlüssel mit nachfolgenden Kommentaren verwenden (#18324 by @kovsu, @fisker)

# Input
{ "foo" # comment
:bar }

# Prettier 3.6
{ "foo": bar } # comment

# Prettier 3.7
{ ? "foo" # comment
: bar }

API

plugin.parser.preprocess() erlaubt nun Rückgabe eines Promise (#17679 by @fisker)

Entspricht dem Verhalten von plugin.printer.preprocess(), das ebenfalls ein Promise zurückgeben darf.

Wir empfehlen weiterhin, asynchrone Arbeiten in plugin.parser.parse() zu verlagern, das bereits ein Promise zurückgeben kann. Die Unterstützung für plugin.parser.preprocess() könnte in Zukunft entfernt werden.

AstPath#call() erlaubt nun Zugriff auf Eigenschaften von nullish-Properties (#17860 by @fisker)

Bisher musste man sicherstellen, dass ein Kindknoten existiert, bevor man auf möglicherweise nicht vorhandene Knoten prüfte.

const isFoo = path.call(() => path.node?.type === "Foo", "foo", "bar");
// Uncaught TypeError: Cannot read properties of undefined (reading 'bar')

Man musste beispielsweise:

const isFoo =
path.node.foo?.bar &&
path.call(() => path.node?.type === "Foo", "foo", "bar");

Seit Prettier 3.7 verursacht der Zugriff auf Eigenschaften von nullish-Properties keine Fehler mehr.

Vorgängerknoten an plugin.printer.canAttachComment() übergeben (#18055 by @fisker)

Dies verhindert das Anhängen von Kommentaren an bestimmte Kindknoten eines Knotens.

Beispiel: Im JavaScript-Code const object = {property}; erscheint der Identifier-Knoten (property) im AST sowohl als Property.key als auch Property.value. Offensichtlich kann er nur einmal ausgegeben werden. Wird der Kommentar an das nicht druckbare Kind angehängt, geht er verloren.

Plugins können dies nun vermeiden, indem sie canAttachComment wie folgt implementieren:

export const canAttachComment = (node, [parent]) =>
!(
parent?.type === "Property" &&
parent.shorthand &&
parent.key === node &&
parent.key !== parent.value
);

export const print = (path, options, print) => {
const { node } = path;
switch (node.type) {
case "Property":
if (node.shorthand) {
return print("value");
}
// ...
}
};

Unterstützung für plugin.printer.printPrettierIgnored() hinzugefügt (#18070 by @fisker)

Für Knoten mit prettier-ignore-Kommentar gibt Prettier den Text des Knotens direkt aus. Dies kann jedoch Probleme verursachen, z.B. wenn der Knoten geklammert werden muss oder ein führendes Semikolon benötigt, um ASI-Probleme im --no-semi-Modus zu vermeiden.

Seit Prettier 3.7 können Plugins eine printPrettierIgnored()-Funktion zum Drucker hinzufügen, um den Druckprozess für prettier-ignore-markierte Knoten anzupassen. Diese Funktion verwendet dieselbe Signatur wie plugin.printer.print().

Plugins können nun einen estree-Printer bereitstellen (#18072 by @fisker)

Bisher musste ein Plugin, das einen estree-Drucker mit abweichender Ausgabe bereitstellen wollte, sowohl parsers als auch printers anbieten. Prettier 3.7 ermöglicht Plugins, die ausschließlich einen estree-Drucker bereitstellen.

CLI

Vermeiden der Erstellung des node_modules/.cache/-Verzeichnisses, wenn --cache nicht aktiviert ist (#18124 by @chiawendt)

Das Ausführen von prettier . ohne --cache erzeugt nun kein leeres node_modules/.cache/-Verzeichnis mehr.