メインコンテンツへスキップ

Prettier 3.2: JSONCとAngularのICU式をサポート

· 1分で読める
非公式ベータ版翻訳

このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →

今回のリリースでは、JSONCパーサーの追加、AngularのICU式のサポート、多くのバグ修正など新機能が含まれています。

Prettier 3.1でリリースされた--experimental-ternariesオプションについて、引き続きフィードバックを募集しています。三項演算子の不思議なケースをお読みいただき、Googleフォームからご意見をお寄せください。

また、Fabio SpampinatoによるPrettier CLIパフォーマンス徹底解説も併せてお読みください。この高速化されたCLIはバージョン4.0としてリリース予定です。

Prettierを評価いただき、私たちの活動を支援したい場合は、OpenCollectiveを通じた直接のスポンサーシップや、typescript-eslintremarkBabelなど当プロジェクトが依存するプロジェクトのスポンサーをご検討ください。皆様の継続的なご支援に感謝申し上げます。

主な変更点

JSON

新規jsoncパーサーの追加 (#15831 by @fisker)

従来、.jsoncファイルのパーサーはjsonと推測されていましたが、末尾のカンマを保持したい場合、回避策として{parser: "json5", quoteProps: "preserve", singleQuote: false}というハック的な設定が必要でした。

新たに追加されたjsoncパーサー:

  • オブジェクトキーは常にクォートする

  • 文字列はダブルクォートで囲む

  • trailingCommaオプションを尊重

Angular

Angular ICU式のフォーマット対応 (#15777 by @sosukesuzuki)

AngularのICU式であるpluralselectの2種類をサポート

<span i18n>
Updated:
{minutes, plural,
=0 {just now}
=1 {one minute ago}
other {{{minutes}} minutes ago}
}
</span>

<span i18n>
The author is {gender, select, male {male} female {female} other {other}}
</span>

その他の変更

JavaScript

テンプレート補間での改行導入回避 (#15209 by @bakkot)

次のようなテンプレート文字列において:

`this is a long message which contains an interpolation: ${format(data)} <- like this`;

既に改行が存在する場合やネストされた関数などで不可避な場合を除き、式のフォーマット時に改行を追加しないように変更。従来はテンプレート内の補間が「十分に複雑」と判断されると改行が導入される可能性がありました:

`this is a long message which contains an interpolation: ${format(
data,
)} <- like this`;

今後はそのまま維持されます

${...}内に既に改行が存在する場合は通常通りフォーマット

空行を含むメソッドチェーンの非冪等なフォーマットを修正 (#15522 by @seiyab)

// Input
Foo.a()

.b();

// Prettier 3.1 (first format)
Foo.a()
.b();

// Prettier 3.1 (second format)
Foo.a().b();


// Prettier 3.2
Foo.a()

.b();

関数呼び出し内の三項演算子のフォーマットを修正 (#15677 by @fisker)

// Input
stopDirectory = await (useCache
? memoizedFindProjectRoot
: findProjectRootWithoutCache)(path.dirname(path.resolve(filePath)));

// Prettier 3.1
stopDirectory = await (useCache
? memoizedFindProjectRoot
: findProjectRootWithoutCache)(path.dirname(path.resolve(filePath)));

// Prettier 3.2
stopDirectory = await (
useCache ? memoizedFindProjectRoot : findProjectRootWithoutCache
)(path.dirname(path.resolve(filePath)));

オプショナルチェイニングの不整合を修正 (#15806 by @fisker)

typescriptmeriyahまたはbabel以外のESTreeパーサー使用時にのみ発生

// Input
function someFunctionName() {
return isEqual(a.map(([t, _]) => t?.id), b.map(([t, _]) => t?.id));
return isEqual(a?.map(([t, _]) => t?.id), b?.map(([t, _]) => t?.id));
}
theValue = Object.entries(someLongObjectName).filter(
([listingId]) => someListToCompareToHere.includes(listingId),
);
theValue = Object.entries(someLongObjectName).filter(
([listingId]) => someListToCompareToHere?.includes(listingId),
);

// Prettier 3.1
function someFunctionName() {
return isEqual(
a.map(([t, _]) => t?.id),
b.map(([t, _]) => t?.id),
);
return isEqual(a?.map(([t, _]) => t?.id), b?.map(([t, _]) => t?.id));
}
theValue = Object.entries(someLongObjectName).filter(([listingId]) =>
someListToCompareToHere.includes(listingId),
);
theValue = Object.entries(someLongObjectName).filter(
([listingId]) => someListToCompareToHere?.includes(listingId),
);

// Prettier 3.2
function someFunctionName() {
return isEqual(
a.map(([t, _]) => t?.id),
b.map(([t, _]) => t?.id),
);
return isEqual(
a?.map(([t, _]) => t?.id),
b?.map(([t, _]) => t?.id),
);
}
theValue = Object.entries(someLongObjectName).filter(([listingId]) =>
someListToCompareToHere.includes(listingId),
);
theValue = Object.entries(someLongObjectName).filter(([listingId]) =>
someListToCompareToHere?.includes(listingId),
);

if内のコメント処理を修正 (#15826 by @fisker)

// Input
if (foo) for (i = 2; i > 0; i--) console.log(i); // comment 1
else bar();

for (;;){
if (foo) continue; // comment 2
else bar();
}

// Prettier 3.1
Error: Comment "comment 2" was not printed. Please report this error!

// Prettier 3.2
if (foo)
for (i = 2; i > 0; i--) console.log(i); // comment 1
else bar();

for (;;) {
if (foo)
continue; // comment 2
else bar();
}

TypeScript

条件付き型エイリアスのレイアウトを改善 (#15811 by @seiyab)

// Input
type FallbackFlags<F extends Flags | undefined> =
Equals<NonNullableFlag<F>["flags"], {}> extends true
? Dict<any>
: NonNullableFlag<F>["flags"];

// Prettier 3.1
type FallbackFlags<F extends Flags | undefined> = Equals<
NonNullableFlag<F>["flags"],
{}
> extends true
? Dict<any>
: NonNullableFlag<F>["flags"];

// Prettier 3.2
type FallbackFlags<F extends Flags | undefined> =
Equals<NonNullableFlag<F>["flags"], {}> extends true
? Dict<any>
: NonNullableFlag<F>["flags"];

HTML

prettier-ignoreで無視された閉じていない要素のフォーマットを修正 (#15748 by @fisker)

<!-- Input -->
<!-- prettier-ignore -->
<h1>
Hello <span>world!

<!-- Prettier 3.1 -->
<!-- prettier-ignore -->
<h1>

<!-- Prettier 3.2 -->
<!-- prettier-ignore -->
<h1>
Hello <span>world!

Angular

prettier-ignoreで無視されたAngular制御フローブロックを修正 (#15827 by @fisker)

<!-- Input -->
<!-- prettier-ignore -->
@if (condition) {
Foo
} @else {
Other
}

<!-- Prettier 3.1 -->
<!-- prettier-ignore -->
@if (condition) {
Foo
}
} @else {
Other
}

<!-- Prettier 3.2 -->
<!-- prettier-ignore -->
@if (condition) {
Foo
}
@else {
Other
}

forブロックの第3式におけるtrackへのコロン追加を回避 (#15887 by @sosukesuzuki)

<!-- Input -->
@for (item of items; let i = $index; track block) {}

<!-- Prettier 3.1 -->
@for (item of items; let i = $index; track: block) {}

<!-- Prettier 3.2 -->
@for (item of items; let i = $index; track block) {}

Ember / Handlebars

パスリテラルセグメントを保持 (#15605 by @maxpowa)

リテラルセグメントを含むHandlebarsファイルがフォーマットによりリテラルセグメントが展開され、結果として構文エラーが発生する問題を修正します。

<!-- Input -->
{{input.[funky<api!response]}}
{{input.[this one has spaces]}}
{{input.[anotherone].[0]}}

<!-- Prettier 3.1 -->
{{input.funky<api!response}}
{{input.this one has spaces}}
{{input.anotherone.0}}

<!-- Prettier 3.2 -->
{{input.[funky<api!response]}}
{{input.[this one has spaces]}}
{{input.anotherone.[0]}}

GraphQL

GraphQLユニオン型のフォーマットを改善 (#15870 by @ArchitGajjar)

# Input
union SearchResult = Conference| Festival | Concert | Venue | Conference| Festival | Concert | Venue

# Prettier 3.1
union SearchResult =
Conference
| Festival
| Concert
| Venue
| Conference
| Festival
| Concert
| Venue

# Prettier 3.2
union SearchResult =
| Conference
| Festival
| Concert
| Venue
| Conference
| Festival
| Concert
| Venue

API

設定ファイルでの絶対パスをプラグインとしてサポート (#15666 by @fisker)

// prettier.config.cjs
module.exports = {
plugins: [
// posix style
"/path/to/plugin.js",
// Windows style
"D:\\\\path\\to\\plugin.js",
// Use `require.resolve`
require.resolve("my-awesome-prettier-plugin"),
],
};

getFileInfoおよびgetSupportInfoの型定義を修正 (#15854 by @auvred)

const plugin: Plugin = {};

prettier.getFileInfo("./file.ext", {
plugins: [plugin],
});

prettier.getSupportInfo({ plugins: [plugin], showDeprecated: true });

その他の変更

cursorOffsetがrangeStart/rangeEndと互換性がないというドキュメントの誤りを修正 (#15750 by @ExplodingCabbage)

cursorOffsetオプションは実際には@ds300の作業により5年以上前からrangeStart/rangeEndと互換性がありましたが、Prettierのドキュメント(CLIの--helpテキストを含む)では誤って互換性がないと記載されていました。現在ドキュメントは修正済みです。