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

Prettier 3.1: 新しい実験的三項演算子フォーマットとAngular制御フロー構文のサポート!

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

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

このリリースでは、入れ子になった三項演算子へのインデントを復活させるとともに、深くネストされた条件分岐でもスケールする新しい「curious ternary」フォーマットを試すための--experimental-ternariesフラグを追加しました。この実験的フォーマットが今年後半にデフォルト動作となる前に、皆様のフィードバックをお待ちしています!

また、Angular v17の制御フロー構文のサポートを追加しました。構文の詳細については、公式のAngularリリース記事をご覧ください。

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

主な変更点

JavaScript

入れ子になった三項演算子へのインデントを復活 (#9559 by @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);

新しい実験的三項演算子フォーマット: 三項演算子の不思議なケース (#13183 by @rattrayalex)

これは--experimental-ternariesフラグの背後に実装されています。

複数行にわたる三項演算子において、?を2行目の先頭ではなく1行目の末尾に移動するなど、いくつかの関連する変更を加えました。

一見奇妙に見えるかもしれませんが、ベータテストでは、数時間使用した後、開発者がネストされた三項演算子の可読性と有用性が大幅に向上したと感じることが示されています。

このPRは、高評価のIssueの一つを、提案された解決策が再導入する問題を伴わずに解決します。

詳細については、三項演算子の不思議なケースをご覧ください。

// "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

Babel 7.23.0でサポートされた新しい構文をサポート (#15485, #15486, #15487, #15488 by @sosukesuzuki)

Babel 7.23.0でサポートされた新しいJS構文をサポートします!

Source Phase Imports

詳細は https://github.com/tc39/proposal-source-phase-imports をご覧ください。

import source x from "mod";
Deferred Import Evaluation

詳細は https://github.com/tc39/proposal-defer-import-eval をご覧ください。

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

詳細は https://github.com/tc39/proposal-optional-chaining-assignment をご覧ください。

maybeObj?.prop1 = value;

Angular

Angular制御フローのサポート (#15606 by @DingWeizhe, @fisker)

Angular 17の組み込み制御フローをサポートしました。バグを見つけた場合はフィードバックをお願いします。

制御フローの詳細については、公式ブログのこちらの記事をご確認ください。

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

その他の変更

JavaScript

括弧と関数本体の間のコメントを修正 (#15326 by @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;
}

instanceofとinの左辺にある単項式の曖昧さを解消 (#15468 by @lucacasonato)

instanceofおよびin式の左辺にある単項式の周囲に括弧を追加し、 左辺の単項式と二項式全体に適用される単項式の曖昧さを解消しました。

これにより、!("x" in y)と書く意図で誤って!"x" in yと記述する 一般的なミス(実際には(!"x") in yと解釈される)を防ぐのに役立ちます。

// 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);

styled componentsの補間におけるセレクタ名の大文字小文字を修正 (#15472 by @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

エスケープを含む文字列のフォーマットを一貫化 (#15525 by @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");

左辺が改行可能な代入式のフォーマットを改善 (#15547 by @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

最後のパラメータプロパティの後のコメントの不安定性を修正 (#15324 by @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
) {}
}

as constでアノテートされたテンプレートリテラル内の埋め込みフォーマットをサポート (#15408 by @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;

ユニオン型の最後のオペランドのコメント出力を修正 (#15409 by @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

satisfies/as式の文脈における特定のキーワード識別子周辺の必須括弧を維持 (#15514 by @seiyab)

// Input
(type) satisfies never;


// Prettier 3.0
type satisfies never;


// Prettier 3.1
(type) satisfies never;

Flow

Flowにおけるasおよびsatisfies式をサポート (#15130 by @gkz)

// Input
const x = y as T;

// Prettier 3.0
// <error: unsupported>

// Prettier 3.1
const x = y as T;

Flow用JSX開始要素の型引数をサポート (#15429 by @SamChou19815)

// Input
<Foo<bar> />;

// Prettier 3.0
<Foo />;

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

typeof後の型引数をサポート (#15466 by @sosukesuzuki)

Flow v0.127.0以降でサポートされているtypeof後の型引数構文をサポート:

type Foo = typeof MyGenericClass<string, number>;

SCSS

先頭ダッシュ付きSCSS関数呼び出しの分割をしないように修正 (#15370 by @auvred)

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

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

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

HTML

<!-- 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

Markdown URL 内の < および > のエンコード処理 (#15400 by @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>)

日本語仮名と結合カタカナ・ひらがな (半)濁点の間での改行を防止 (#15411 by @tats-u)

この PR は #15410 を修正します。

日本語の(半)濁音仮名文字は2つのコードポイントに分割される場合があります。例えば、以下のひらがな「か」は次のように表現できます:

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

ほとんどのユーザーはmacOSのファイルパス以外でこのような表現を使用したり遭遇することはありませんが、この方法でしか表現できない文字が存在します。例えば、一般的な/ga/と区別する必要がある/ŋa̠/を表すために、日本語テキストでは"か゚" (U+304B U+309A)という表現が使用されることがあります(最近では使用されないことも少なくありませんが)。

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

上記MarkdownはPrettier 3.0では次のようにフォーマットされていました:

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

半濁点が次の行に移動してしまいますが、これは正しい挙動ではありません。

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

このPRにより、元のMarkdownは次のようにフォーマットされるようになりました:

API

prettier.{resolveConfig,resolveConfigFile,getFileInfo}()URL を受け入れるようになりました (#15332, #15354, #15360, #15364 by @fisker)

prettier.resolveConfig()prettier.resolveConfigFile()prettier.getFileInfo()file: プロトコルを持つURL または file:// で始まるURL文字列を受け付けるようになりました。

// `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

プラグインでのみサポートされるファイルを処理するように (#15433 by @sosukesuzuki)

Prettier 3.0では、CLIからディレクトリを指定した場合、デフォルトでサポートされている拡張子のファイルのみが処理されていました。

以下のシナリオでは、foo.js だけでなく foo.astro もフォーマットされるべきです:

# Prettier 3.0 version

$ ls .
foo.js foo.astro

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

$ prettier --write .
foo.js 20ms

この更新により、foo.jsfoo.astro の両方がフォーマットされるようになります:

# Prettier 3.1 branch

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

prettier "**/*" --ignore-unknownprettier . と同等になったため、置き換えが可能になりました。

CLIの--writeでアクセシビリティのため(unchanged)キーワードを表示 (#15467 by @ADTC)

以前は、変更されたファイルと変更されていないファイルの唯一の違いはファイル名のグレー表示でした。下記の例では色が表示されないためa.jsb.jsの区別がつきませんでした。この問題は(unchanged)キーワードを追加することで修正され、色に頼らずとも区別が可能になりました。

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)

特殊文字を含むファイル名のフォーマット時のエラーを修正 (#15597 by @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