Prettier 3.7: フォーマットの一貫性向上と新しいプラグイン機能!
このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →
Prettier 3.7のリリースを発表できることを嬉しく思います!今回のリリースでは、TypeScriptとFlowの体験を磨くことに焦点を当て、特にクラスとインターフェースのフォーマットをより一貫性があり予測可能なものに調整しました。また、クラスとインターフェースのボディ開始ブレース({)の出力ロジックの不整合を修正する今後の変更について、皆様のご意見をお聞かせください。
さらに、多数のバグ修正に加え、Angular 21とGraphQL 16.12の新機能サポートを追加し、HandlebarsでFront Matterのサポートを実装しました。
プラグイン開発者向けには、コメントのアタッチメントや無視されたノードの処理をより細かく制御できる新しいAPIを追加しています。
Prettierを評価いただき、私たちの活動をサポートしていただける方は、OpenCollectiveから直接スポンサーになるか、依存プロジェクトをスポンサーすることをご検討ください。引き続きのご支援に感謝いたします!
主な変更点
TypeScript
クラスとインターフェース間の出力不整合を修正 (#18094, #18091, #18215 by @fisker)
このリリースでは、クラスとインターフェースのフォーマット間の一貫性向上に注力しました。以前は、これらの類似した構造が大きく異なる形式で出力され、視覚的な不整合が生じていました。予測可能でクリーンな出力を実現するため、フォーマットルールを統一しました。
クラスの型パラメータに不要なインデントがなくなります
// 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 {}
インターフェースの継承出力をクラスに合わせて調整
// 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> {}
単一継承の出力をスーパークラスと統一
// 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
> {}
クラスとインターフェースのボディ開始ブレース出力ロジックの不整合
Prettier v2.3では、クラスのヘッダーとボディの視覚的な分離を改善するため、クラスが複数の継承を持つ場合にクラスボディの開始ブレース{を改行して出力するよう変更しました。
// Prettier 2.2
class loooooooooooooooooooong
extends looooooooooooooooooong
implements loooooooooooooooooooong {
property: string;
}
// Prettier 2.3
class loooooooooooooooooooong
extends looooooooooooooooooong
implements loooooooooooooooooooong
{
property: string;
}
しかし、この変更を好まない方もいらっしゃいます。
この変更をインターフェースにも適用することについて、こちらのissueにコメントでご意見をお聞かせください。
この問題に対するより良い解決策をお持ちでしたら、ぜひご提案ください。
より良い解決策が提案されない限り、Prettier v4ではインターフェースボディの出力をクラスボディの出力形式に統一する予定です。
// 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;
}
これらの変更はFlow構文にも影響します
その他の変更
JavaScript
import属性の複数行分割を許可 (#17329 by @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",
};
"Discard Bindings"提案のサポートを追加 (#17708 by @fisker)
Stage 2提案の"Discard Bindings"がBabel経由でサポートされました。Prettierでこの提案構文を使用する前に、非標準構文に関する方針もご確認ください。
const [void] = x;
const {x:void} = x;
コメントフォーマットの不整合を修正 (#17723 by @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();
}
追加のPlaywrightテスト関数をサポート (#17876 by @BPScott)
Prettierはすでに、テスト関数に.skipを追加した場合にインデントの変更を避けています。今回、Playwrightの関数test.fixme、test.describe.skip、test.describe.fixmeについても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
});
長いモジュール名を持つ{import,require.resolve,require.resolve.paths,import.meta.resolve}()の改行を回避 (#17882, #17908 by @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");
if文内のコメント処理を改善 (#17998 by @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();
}
コメント付きrequire()呼び出しを改善 (#18037 by @fisker)
// Input
require(
// Comment
"foo"
);
// Prettier 3.6
require(// Comment
"foo");
// Prettier 3.7
require(
// Comment
"foo",
);
Boolean()呼び出し内の論理式におけるインデントを削除 (#18087 by @kovsu)
条件を反対の値に変更する場合や、!!と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
);
for文のコメント処理を修正 (#18099 by @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();
空の文周辺のコメント出力を改善 (#18108 by @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 */ ;
クラスメソッドとオブジェクトメソッド間のコメント出力の不整合を修正 (#18147 by @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;
},
};
ビット演算子の不足している括弧を追加 (#18163 by @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);
配列リテラルの不整合な改行を修正 (#18172 by @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],
);
論理式の出力の不整合を修正 (#18205 by @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,
);
CallExpressionとNewExpression間の出力の不整合を修正 (#18206 by @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,
)
JSX要素周囲の冗長な括弧を削除 (#18243 by @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>,
);
new式の呼び出し元としての論理式のフォーマットを改善 (#18245 by @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
)();
"update"なしのfor文における空行を削除 (#18300 by @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;
) {}
スーパークラスのフォーマットを改善 (#18325 by @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
アロー関数後のコメント位置誤りを修正 (#17421 by @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;
インスタンス化式内のアロー関数に不足していた括弧を追加 (#17724 by @fisker)
// Input
void (<_T extends never>() => {})<never>;
// Prettier 3.6
void <_T extends never>() => {}<never>;
// Prettier 3.7
void (<_T extends never>() => {})<never>;
TSMappedTypeのフォーマットを修正 (#17785 by @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;
TSImportTypeオプションで末尾カンマを出力 (#17798 by @fisker)
TypeScript v5.9以前では、import type属性での末尾カンマは許可されていませんでしたが、現在このバグは修正されています。
// 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
});
コメント付きCommonJSモジュールrequire()の処理を改善 (#18035 by @fisker)
// Input
import foo = require(
// Comment
"foo"
);
// Prettier 3.6
import foo = require(// Comment
"foo");
// Prettier 3.7
import foo = require(
// Comment
"foo"
);
型パラメータの=後の改行処理 (#18043 by @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 };
ユニオン型前の予期せぬ空行を削除 (#18109 by @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;
この変更はFlow構文にも影響します
typescriptパーサーとflowパーサー間のコメント出力の不整合を修正 (#18110 by @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;
}
コールシグネチャ前のセミコロン不足を修正 (#18118 by @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
}
flowパーサーとtypescriptパーサー間のas const出力不整合を修正 (#18161 by @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;
as/satisfies式周囲のコメント位置を修正 (#18162 by @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
*/;
ずれたユニオン型の修正 (#18165 by @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];
}
ユニオン型の不要な空行を削除 (#18197 by @Dunqing)
// Input
type SuperLongTypeNameLoremIpsumLoremIpsumBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla =
Fooo1000 | Baz2000 | BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
// Prettier 3.6
type SuperLongTypeNameLoremIpsumLoremIpsumBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla =
| Fooo1000
| Baz2000
| BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
// Prettier 3.7
type SuperLongTypeNameLoremIpsumLoremIpsumBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla =
| Fooo1000
| Baz2000
| BarLoooooooooooooooooooooooooooooooooooooooooooooooooLong;
Flow
"match"構文の基本サポートを追加 (#17681 by @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" },
};
上限下限付きopaque型のサポートを追加 (#17792 by @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
大文字小文字を区別する属性セレクターと大文字小文字を区別しないフラグの対応 (#17841, #17865 by @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;
}
特殊なカスタムプロパティのフォーマット時のクラッシュを修正 (#17899 by @fisker)
/* Input */
:root {
--l: , #000;
}
/* Prettier 3.6 */
TypeError: Cannot read properties of undefined (reading 'value')
/* Prettier 3.7 */
:root {
--l: , #000;
}
CSSモジュール内でセレクターが誤って小文字化される問題を修正 (#17929 by @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;
}
//を含むCSSセレクターのフォーマットを修正 (#17938 by @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;
}
フォントサイズとライン高さの間の不要なスペースを削除 (#18114 by @kovsu)
/* Input */
a {
font: var(--size)/1;
}
/* Prettier 3.6 */
a {
font: var(--size) / 1;
}
/* Prettier 3.7 */
a {
font: var(--size)/1;
}
ブロックコメント後のCSSカンマ区切り値の不要なインデントを修正 (#18228 by @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
mixin引数のかっこ周りのスペース問題を修正 (#17836 by @kovsu)
// Input
.foo {
@include bar('A (B)');
}
// Prettier 3.6
.foo {
@include bar('A( B)');
}
// Prettier 3.7
.foo {
@include bar('A (B)');
}
スペース区切り値のフォーマットを修正 (#17903 by @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
変数名が誤って小文字化される問題を修正 (#17820 by @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;
}
プロパティ/変数アクセサーの間隔をコンパクトに維持 (#17983 by @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
iframe要素のallow属性フォーマットをサポート (#17879 by @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>
インラインイベントハンドラーのフォーマット (#17909 by @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
Angular 21 のサポート (#17722, #18294 by @fisker)
Angular 20.1 で新しい代入演算子のサポートが追加されました。 Angular 21 では正規表現のサポートが追加されています。
<!-- 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>
補間内でコメントが重複する問題を修正 (#17862 by @fisker)
<!-- Input -->
{{a() // comment}}
<!-- Prettier 3.6 -->
{{ a(// comment) // comment }}
<!-- Prettier 3.7 -->
{{
a() // comment
}}
「非 null アサーション」のフォーマットを修正 (#18047 by @fisker)
<!-- Input -->
{{ foo?.bar!.baz }}
<!-- Prettier 3.6 -->
{{ (foo?.bar)!.baz }}
<!-- Prettier 3.7 -->
{{ foo?.bar!.baz }}
Ember / Handlebars
Handlebars に Front Matter サポートを追加 (#17781 by @Codezilluh)
Handlebars で Front Matter が使用可能になりました。
---
title: My page title
keywords:
- word
- other word
---
<h1>{{title}}</h1>
<ul>
{{#each keywords}}
<li>{{this}}</li>
{{/each}}
</ul>
カスタムヘルパーでの else if 構文を維持 (#17856 by @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}}
<style> タグ内の余分な空白行を削除 (#18065 by @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>
--html-whitespace-sensitivity=ignore 時に要素の強制改行を停止 (#18133 by @fisker)
{{! Input }}
<div> </div>
{{! Prettier 3.6 (--html-whitespace-ensitivity=ignore) }}
<div>
</div>
{{! Prettier 3.7 (--html-whitespace-ensitivity=ignore) }}
<div></div>
GraphQL
「実行可能な説明文」をサポート (#18214 by @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
絵文字のサイズ計測を改善 (#17813 by @seiyab)
この変更により、全言語でテーブルの配置が改善されます。
<!-- Input -->
| | |
| :-: | :-: |
| ✔ | ✘ |
| ✘ | ✔ |
| ✔ | ✘ |
<!-- Input -->
| | |
| :-: | :-: |
| ✔ | ✘ |
| ✘ | ✔ |
| ✔ | ✘ |
<!-- Prettier 3.7 -->
| | |
| :-: | :-: |
| ✔ | ✘ |
| ✘ | ✔ |
| ✔ | ✘ |
Front Matter の TOML パーサー推論 (#17965 by @kovsu)
TOML Front Matter は適切なプラグインがあれば処理可能です。 HTML ファイルや CSS ファイルでも動作します。
強い強調のフォーマットを修正 (#18010 by @yin1999)
これは #17143 に対する補足修正で、元の PR では左右の内容が両方とも単語かどうかを判定できませんでした。
<!-- 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
import と export のパースを修正 (#17996 by @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
マップとコメント間の空行を維持 (#17843 by @kovsu)
# Input
only: issues
# Comment
# Prettier 3.6
only: issues
# Comment
# Prettier 3.7
only: issues
# Comment
明示的なドキュメント終了マーカーを維持 (#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
末尾コメント付きflow-mappingキーに明示的なキースタイルを使用 (#18324 by @kovsu, @fisker)
# Input
{ "foo" # comment
:bar }
# Prettier 3.6
{ "foo": bar } # comment
# Prettier 3.7
{ ? "foo" # comment
: bar }
API
plugin.parser.preprocess()がPromiseを返せるように (#17679 by @fisker)
plugin.printer.preprocess()と同様に、Promiseを返せるようになりました。
非同期処理はPromiseを返すことができるplugin.parser.parse()に移行することを推奨します。将来plugin.parser.preprocess()のサポートを削除する可能性があります。
AstPath#call()がnullishプロパティへのアクセスを許可 (#17860 by @fisker)
以前は、存在しない可能性のある子ノードをチェックする際、まずノードの存在を確認する必要がありました。
const isFoo = path.call(() => path.node?.type === "Foo", "foo", "bar");
// Uncaught TypeError: Cannot read properties of undefined (reading 'bar')
次のように記述する必要がありました:
const isFoo =
path.node.foo?.bar &&
path.call(() => path.node?.type === "Foo", "foo", "bar");
Prettier 3.7以降、nullishプロパティへのアクセスでエラーが発生しなくなりました。
plugin.printer.canAttachComment()に祖先ノードを渡すように (#18055 by @fisker)
これによりノードの特定の子要素へのコメント付加を防止します。
例:JavaScriptコードconst object = {property};では、Identifierノード(property)がAST内でProperty.keyとProperty.valueの両方として存在しますが、実際には一度しか出力されません。コメントが出力不可の子要素に付加されると、コメントが失われる可能性があります。
プラグインは次のようなcanAttachCommentを追加することでこれを回避できます:
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");
}
// ...
}
};
plugin.printer.printPrettierIgnored()のサポートを追加 (#18070 by @fisker)
prettier-ignoreコメントが付いたノードでは、Prettierはノードのテキストを直接出力します。しかしこの方法では問題が発生する可能性があります。例えば、ノードを括弧で囲む必要がある場合や、--no-semiモードでASI(Automatic Semicolon Insertion)問題を防ぐために先頭セミコロンを出力する必要がある場合などです。
Prettier 3.7以降、プラグインはプリンターにprintPrettierIgnored()関数を追加することで、prettier-ignoreされたノードの出力処理をカスタマイズできます。この関数はplugin.printer.print()と完全に同じシグネチャを使用します。
プラグインがestreeプリンターを提供できるようにする (#18072 by @fisker)
以前は、組み込みプリンターとは異なるコードを出力するestreeプリンターを持つプラグインを作成する場合、プラグイン開発者はparsersとprintersの両方を提供する必要がありました。Prettier 3.7では、estreeプリンターのみを提供するプラグインの作成が可能になりました。
CLI
--cacheが有効でない場合にnode_modules/.cache/ディレクトリが作成されないように (#18124 by @chiawendt)
--cacheオプションなしでprettier .を実行しても、空のnode_modules/.cache/ディレクトリが作成されなくなりました。
