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

Prettier 3.6: 実験的な高速CLIと新しいOXC/Hermesプラグインの登場!

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

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

今回のリリースでは、皆様にお伝えしたい重要な機能追加がいくつか含まれています。

まず、新たに実験的な高性能CLIを機能フラグ(--experimental-cli)の背後で提供します。このCLIはこれまでprettier@nextでのみ利用可能でしたが、フラグを指定するだけで有効化できるようになりました。ぜひお試しいただき、フィードバックをお寄せください!内部実装に興味がある方は、FabioによるPrettier CLIのパフォーマンス徹底解説をご覧ください。

さらに、2つの新しい公式プラグインをリリースします: @prettier/plugin-oxc@prettier/plugin-hermes。これらのプラグインはPrettierコアとは別に提供されます。

この素晴らしいリリースを実現してくれたすべての方々に心からの感謝を捧げます: 新CLI開発に貢献した @fabiospampinato, @43081j, @pralkarz と、OXC開発者の @boshen, @overlookmotel をはじめとするOXCコントリビューターの皆様、Metaの Flow および Hermes チームの皆様。皆様の素晴らしい貢献に感謝します!

これらの新機能が皆様の開発体験をどのように向上させるか、楽しみにしています。Happy formatting!

主な変更点

CLI

実験的CLIのサポート (#17151, #17396 by @fisker)

既にご存知の方や使用経験があるかもしれませんが、パフォーマンス改善版CLIがPrettier 3.6から安定版v4をインストールせずに利用可能になりました。

# Run CLI with `--experimental-cli`
prettier . --check --experimental-cli

# Or use environment variable `PRETTIER_EXPERIMENTAL_CLI=1`
PRETTIER_EXPERIMENTAL_CLI=1 prettier . --check

JavaScript

新公式プラグイン @prettier/plugin-oxc の追加 (#17472, #17483 by @fisker)

@prettier/plugin-oxcOXC(Rust製の高速JavaScript/TypeScriptパーサー)を基盤としています。

このプラグインには oxc(JavaScript構文)と oxc-ts(TypeScript構文)の2つの新パーサーが含まれています。使用方法は以下の通りです:

  1. プラグインをインストール

    yarn add --dev prettier @prettier/plugin-oxc
  2. 以下の設定を .prettierrc ファイルに追加

    plugins:
    - "@prettier/plugin-oxc"

パッケージサイズの制限のため、このプラグインは prettier パッケージには含まれていません。別途インストールする必要があります。

詳細は パッケージホームページ をご確認ください。

OXCチーム(@boshen, @overlookmotel およびその他のコントリビューターの皆様)に深く感謝します。

Flow

新しい公式プラグイン @prettier/plugin-hermes の追加 (#17520 by @fisker)

@prettier/plugin-hermesHermes JS Engine に基づいています。

このプラグインには新しいパーサー hermes (Flow構文) が含まれています。このプラグインを使用するには:

  1. プラグインをインストールする

    yarn add --dev prettier @prettier/plugin-hermes
  2. 以下の内容を .prettierrc ファイルに追加する

    plugins:
    - "@prettier/plugin-hermes"

パッケージサイズの制限のため、このプラグインは prettier パッケージには含まれていません。別途インストールする必要があります。

v4ではFlow構文サポートのデフォルトパーサーとして採用予定です。v4では babel-flow パーサーも削除されますので、ぜひお試しください。

詳細については、パッケージのホームページをご覧ください。

Hermesチームに深く感謝いたします。

その他の変更

JavaScript

ReturnStatement および ExpressionStatement 内の SequenceExpression に括弧を追加 (#17085 by @TYKevin)

// Input
function a() {
return ( a, b)
}

(a(), b());

// Prettier 3.5
function a() {
return a, b;
}

a(), b();

// Prettier 3.6
function a() {
return (a, b);
}

(a(), b());

クラスプロパティキー内の AssignmentExpression に括弧を追加 (#17145 by @fisker)

以前はオブジェクトキー内の AssignmentExpression には括弧を追加していましたが、クラスプロパティキー内では追加していませんでした。この不整合を指摘してくれた Biome に感謝します。

// Input
a = {
[(x = "key")]: 1,
}

class A {
[(x = "property")] = 1;
[(x = "method")]() {}
}

// Prettier 3.5
a = {
[(x = "key")]: 1,
};

class A {
[x = "property"] = 1;
[(x = "method")]() {}
}

// Prettier 3.6
a = {
[(x = "key")]: 1,
};

class A {
[(x = "property")] = 1;
[(x = "method")]() {}
}

オプショナルチェーンのメンバー式における数値に括弧を追加 (#17190 by @fisker)

Prettier 3.6より前では、オブジェクトが数値であるメンバー式のフォーマットに不整合がありました。

babel パーサー(および他のBabelベースのパーサー)を使用する場合、数値は括弧なしで出力され、typescript パーサー(および他のESTreeパーサー)を使用する場合、括弧付きで出力されていました。

技術的には括弧は不要ですが、1?.toString() のように出力した後でユーザーが ?. の不要に気付いた場合、1.toString()SyntaxError を発生させるため単純に疑問符を削除できません。このため、常に括弧を付けることにしました。

// Input
(1)?.toString();
(1.5)?.toString();

// Prettier 3.5 (--parser=babel)
1?.toString();
1.5?.toString();

// Prettier 3.5 (--parser=typescript)
(1)?.toString();
(1.5)?.toString();

// Prettier 3.6
(1)?.toString();
(1.5)?.toString();

実験的な Records & Tuples のサポートを削除 (#17363 by @fisker)

ES提案 JavaScript Records & Tuples Proposal は撤回されました。

CSSの単語と埋め込み式の間のスペースを維持 (#17398 by @sosukesuzuki)

// Input
const Heading = styled.h1`
font-size: var(--font-size-h${level});
`;

// Prettier 3.5
const Heading = styled.h1`
font-size: var(--font-size-h ${level});
`;

// Prettier 3.6
const Heading = styled.h1`
font-size: var(--font-size-h${level});
`;

一貫性のない代入フォーマットを修正 (#17469 by @fisker)

// Input
didScheduleRenderPhaseUpdateDuringThisPassFoo = didScheduleRenderPhaseUpdate = true

// Prettier 3.5 (--parser=babel)
didScheduleRenderPhaseUpdateDuringThisPassFoo =
didScheduleRenderPhaseUpdate = true;

// Prettier 3.5 (--parser=typescript)
didScheduleRenderPhaseUpdateDuringThisPassFoo = didScheduleRenderPhaseUpdate =
true;

// Prettier 3.6
didScheduleRenderPhaseUpdateDuringThisPassFoo =
didScheduleRenderPhaseUpdate = true;

一貫性のないメンバーチェーンフォーマットを修正 (#17470 by @fisker)

// Input
s.get(u)?.trigger({ triggerKind: y.SignatureHelpTriggerKind.InvokeFooBarBaz123 });

// Prettier 3.5 (--parser=babel)
s.get(u)?.trigger({
triggerKind: y.SignatureHelpTriggerKind.InvokeFooBarBaz123,
});

// Prettier 3.5 (--parser=typescript)
s
.get(u)
?.trigger({ triggerKind: y.SignatureHelpTriggerKind.InvokeFooBarBaz123 });

// Prettier 3.6
s.get(u)?.trigger({
triggerKind: y.SignatureHelpTriggerKind.InvokeFooBarBaz123,
});

計算プロパティキーとしてのオプショナルチェイニングを修正 (#17486 by @fisker)

// Input
const a = { [y?.z]() {} };
class A { [y?.z]() {} };

// Prettier 3.5
const a = { [y?.z]?() {} };
class A {
[y?.z]?() {}
}

// Prettier 3.6
const a = { [y?.z]() {} };
class A {
[y?.z]() {}
}

acornおよびmeriyahパーサーでの型キャストコメントをサポート (#17491, #17566 by @ArnaudBarre, #17600 by #fisker)

この機能は以前はBabelパーサーでのみサポートされていました。

// Input
/** @type {MyType} */ (x).foo;

// Prettier 3.5 (--parser=acorn|meriyah)
/** @type {MyType} */ x.foo;

// Prettier 3.6
/** @type {MyType} */ (x).foo;

タグ付きテンプレートリテラル内のコメントフォーマットの不安定さを修正 (#17510 by @fisker)

// Input
foo
// Comment
`x`

// Prettier 3.5 (First format)
foo// Comment
`x`;

// Prettier 3.5 (Second format)
foo // Comment
`x`;

// Prettier 3.6
foo // Comment
`x`;

オプショナルメソッド呼び出し内のJSXの一貫性を改善 (#17616 by @seiyab)

// Input
<SuspendyTree>
<div style={{ height: 200, overflow: "scroll" }}>
{Array(20)
.fill()
?.map((_, i) => (
<h2 key={i}>{i + 1}</h2>
))}
</div>
</SuspendyTree>;

// Prettier 3.5 (ESTree based parsers like espree and typescript)
<SuspendyTree>
<div style={{ height: 200, overflow: "scroll" }}>
{Array(20)
.fill()
?.map((_, i) => <h2 key={i}>{i + 1}</h2>)}
</div>
</SuspendyTree>;

// Prettier 3.5 (babel and babel-ts parser)
<SuspendyTree>
<div style={{ height: 200, overflow: "scroll" }}>
{Array(20)
.fill()
?.map((_, i) => (
<h2 key={i}>{i + 1}</h2>
))}
</div>
</SuspendyTree>;

// Prettier 3.6 (parsers of both types)
<SuspendyTree>
<div style={{ height: 200, overflow: "scroll" }}>
{Array(20)
.fill()
?.map((_, i) => (
<h2 key={i}>{i + 1}</h2>
))}
</div>
</SuspendyTree>;

TypeScript

TSImportTypeでのインポートタイプ属性をサポート (#16881 by @fisker)

// Input
type A = import("foo", {with: {type: "json"}})

// Prettier 3.5
type A = import("foo")

// Prettier 3.6
type A = import("foo", { with: { type: "json" } });

論理式と交差型内のコメントを修正 (#17193 by @fisker)

// Input
export type ErrorLike =
SerializedProps<Error> &
// cause is a new addition to Error that is not yet available in all runtimes. We have added
// it to try and pinpoint additional reasoning for failures such as Node's fetch.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause
{ cause?: unknown };

// Prettier 3.5
export type ErrorLike =
SerializedProps<Error> & // cause is a new addition to Error that is not yet available in all runtimes. We have added
// it to try and pinpoint additional reasoning for failures such as Node's fetch.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause
{ cause?: unknown };

// Prettier 3.5 (second format)
export type ErrorLike =
SerializedProps<Error> & // it to try and pinpoint additional reasoning for failures such as Node's fetch. // cause is a new addition to Error that is not yet available in all runtimes. We have added
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause
{ cause?: unknown };

// Prettier 3.6
export type ErrorLike = SerializedProps<Error> &
// cause is a new addition to Error that is not yet available in all runtimes. We have added
// it to try and pinpoint additional reasoning for failures such as Node's fetch.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause
{ cause?: unknown };

マップ型での改行検出を改善 (#17498 by @fisker)

// Input
type A = { readonly
[A in B]: T}

// Prettier 3.5
type A = {
readonly [A in B]: T;
};

// Prettier 3.6
type A = { readonly [A in B]: T };

prettier-ignoreされたインデックスシグネチャ後の余分なセミコロンを出力しない (#17538 by @sosukesuzuki)

// Input
type foo = {
// prettier-ignore
[key: string]: bar;
};

// Prettier 3.5
type foo = {
// prettier-ignore
[key: string]: bar;;
};

// Prettier 3.6
type foo = {
// prettier-ignore
[key: string]: bar;
};

Flow

ConditionalTypeAnnotation内の欠落した括弧を修正 (#17196 by @fisker)

// Input
type T<U> = 'a' | ('b' extends U ? 'c' : empty);
type T<U> = 'a' & ('b' extends U ? 'c' : empty);

// Prettier 3.5
type T<U> = "a" | "b" extends U ? "c" : empty;
type T<U> = "a" & "b" extends U ? "c" : empty;

// Prettier 3.6
type T<U> = "a" | ("b" extends U ? "c" : empty);
type T<U> = "a" & ("b" extends U ? "c" : empty);

JSON

コメントのみを含むJSONCファイルのフォーマットを許可 (#17269 by @fisker)

// Input
// Comment

// Prettier 3.5
SyntaxError: Unexpected token (1:11)
> 1 | // Comment
| ^

// Prettier 3.6
// Comment

括弧付き式を禁止 (#17598 by @fisker)

// Input
[1, (2)]

// Prettier 3.5
[1, 2]

// Prettier 3.6
SyntaxError: 'ParenthesizedExpression' is not allowed in JSON. (1:5)
> 1 | [1, (2)]
| ^^^

CSS

Tailwindの@utilityディレクティブをサポート (#17362 by @sosukesuzuki)

この変更によりTailwind CSS V4の@utilityディレクティブがサポートされます。

/* Input */
@utility tab-* {
tab-size: --value(--tab-size-*);
}

/* Prettier 3.5 */
@utility tab-* {
tab-size: --value(--tab-size- *);
}

/* Prettier 3.6 */
@utility tab-* {
tab-size: --value(--tab-size-*);
}

:has 擬似クラス呼び出しの余分なインデントを削除 (#17541 by @sosukesuzuki)

/* Input */
li:has(
path[d="M544,272H480V150.627L523.314,107.314A16,16,0,0,0,500.686,84.687L457.373,128H415a127.00381,127.00381,0,1,0-254,0H118.627L75.314,84.687A16,16,0,1,0,52.686,107.314L96,150.627V272H32a16,16,0,0,0,0,32H96v24a174.98856,174.98856,0,0,0,30.484,98.889L68.687,484.686a15.99972,15.99972,0,1,0,22.627,22.627l55.616-55.616A175.45165,175.45165,0,0,0,272,504h32a175.45165,175.45165,0,0,0,125.07-52.303l55.616,55.616a15.99972,15.99972,0,0,0,22.627-22.627l-57.797-57.797A174.98856,174.98856,0,0,0,480,328V304h64a16,16,0,0,0,0-32ZM288,32.01263A95.99568,95.99568,0,0,1,383,128H193A95.99568,95.99568,0,0,1,288,32.01263ZM448,328c0,79.401-64.598,144-144,144V236a12.00052,12.00052,0,0,0-12-12h-8a12.00052,12.00052,0,0,0-12,12V472c-79.402,0-144-64.599-144-144V160H448Z"]
) {
display: none;
}

/* Prettier 3.5 */
li:has(
path[d="M544,272H480V150.627L523.314,107.314A16,16,0,0,0,500.686,84.687L457.373,128H415a127.00381,127.00381,0,1,0-254,0H118.627L75.314,84.687A16,16,0,1,0,52.686,107.314L96,150.627V272H32a16,16,0,0,0,0,32H96v24a174.98856,174.98856,0,0,0,30.484,98.889L68.687,484.686a15.99972,15.99972,0,1,0,22.627,22.627l55.616-55.616A175.45165,175.45165,0,0,0,272,504h32a175.45165,175.45165,0,0,0,125.07-52.303l55.616,55.616a15.99972,15.99972,0,0,0,22.627-22.627l-57.797-57.797A174.98856,174.98856,0,0,0,480,328V304h64a16,16,0,0,0,0-32ZM288,32.01263A95.99568,95.99568,0,0,1,383,128H193A95.99568,95.99568,0,0,1,288,32.01263ZM448,328c0,79.401-64.598,144-144,144V236a12.00052,12.00052,0,0,0-12-12h-8a12.00052,12.00052,0,0,0-12,12V472c-79.402,0-144-64.599-144-144V160H448Z"]
) {
display: none;
}

/* Prettier 3.6 */
li:has(
path[d="M544,272H480V150.627L523.314,107.314A16,16,0,0,0,500.686,84.687L457.373,128H415a127.00381,127.00381,0,1,0-254,0H118.627L75.314,84.687A16,16,0,1,0,52.686,107.314L96,150.627V272H32a16,16,0,0,0,0,32H96v24a174.98856,174.98856,0,0,0,30.484,98.889L68.687,484.686a15.99972,15.99972,0,1,0,22.627,22.627l55.616-55.616A175.45165,175.45165,0,0,0,272,504h32a175.45165,175.45165,0,0,0,125.07-52.303l55.616,55.616a15.99972,15.99972,0,0,0,22.627-22.627l-57.797-57.797A174.98856,174.98856,0,0,0,480,328V304h64a16,16,0,0,0,0-32ZM288,32.01263A95.99568,95.99568,0,0,1,383,128H193A95.99568,95.99568,0,0,1,288,32.01263ZM448,328c0,79.401-64.598,144-144,144V236a12.00052,12.00052,0,0,0-12-12h-8a12.00052,12.00052,0,0,0-12,12V472c-79.402,0-144-64.599-144-144V160H448Z"]
) {
display: none;
}

Less

関数引数が誤って小文字化される問題を修正 (#17502 by @fisker)

// Input
.what {
.make-modifier(1A, "1a.png");
.make-modifier(AA, "1a.png");
}

// Prettier 3.5
.what {
.make-modifier(1a, "1a.png");
.make-modifier(AA, "1a.png");
}

// Prettier 3.6
.what {
.make-modifier(1A, "1a.png");
.make-modifier(AA, "1a.png");
}

HTML

タグ名がオブジェクトプロトタイププロパティの場合のフォーマットを修正 (#17501 by @fisker)

<!-- Input -->
<constructor>
text
</constructor>

<!-- Prettier 3.5 -->
TypeError: Vn(...).startsWith is not a function

<!-- Prettier 3.6 -->
<constructor> text </constructor>

Angular

Angular 19.2で導入された TemplateLiteral をサポート (#17238 by @fisker)

Angular 19.2でTemplateLiteralのサポートが追加されました

<!-- Input -->
<div>{{ `Hello, ${
getName('world')}` }}</div>

<!-- Prettier 3.5 -->
<div>
{{ `Hello, ${
getName('world')}` }}
</div>

<!-- Prettier 3.6 -->
<div>{{ `Hello, ${getName("world")}` }}</div>

Angularの@for制御フローでtrackの後に余分なコロンが付く問題を修正 (#17280 by @claudio-herger)

// Input
@for (item of items; let i = $index; let count = $count; track block) {}

// Prettier 3.5
@for (item of items; let i = $index; let count = $count; track: block) {}

// Prettier 3.6
@for (item of items; let i = $index; let count = $count; track block) {}

Angular 20をサポート (#17534 by @fisker)

// Input
{{
( (a in (b)))
}}
{{
( (tag ` a ${ b } \u0063 `))
}}
{{
( (` a ${ b } \u0063 `))
}}
{{ void(1 + 2) }}

// Prettier 3.5
The new syntax is not correctly recognized.

// Prettier 3.6
{{ a in b }}
{{ tag` a ${b} \u0063 ` }}
{{ ` a ${b} \u0063 ` }}
{{ void (1 + 2) }}

MJML

<mj-style>タグ内のCSSフォーマットを有効化 (#17338 by @iryusa)

<!-- Input -->
<mj-style>
.hello {
color: blue;
border: 1px solid blue;
font-size:12px;
} p { font-size: 14px; }
</mj-style>

<!-- Prettier 3.5 -->
<mj-style>
.hello { color: blue; border: 1px solid blue; font-size:12px; } p { font-size:
14px; }
</mj-style>

<!-- Prettier 3.6 -->
<mj-style>
.hello {
color: blue;
border: 1px solid blue;
font-size: 12px;
}
p {
font-size: 14px;
}
</mj-style>

<mj-style><mj-raw>の解析を修正 (#17400 by @fisker)

<!-- Input -->
<mj-style>
a::before {
content: "</p>";
}
</mj-style>

<!-- Prettier 3.5 -->
SyntaxError: Unexpected closing tag "p".

<!-- Prettier 3.6 -->
Correctly parsed as CSS.

Markdown

ブロッククォート内の連続するMarkdown構文を修正 (#16596 by @fiji-flo)

<!-- Input -->
> `x`
> `y`

> _x_
> _y_

> [foo](http://foo)
> [bar](http://bar)

> `this` behaves
> `correctly`

<!-- Prettier 3.5 -->
> `x` > `y`

> _x_ > _y_

> [foo](http://foo) > [bar](http://bar)

> `this` behaves `correctly`

<!-- Prettier 3.6 -->
> `x` `y`

> _x_ _y_

> [foo](http://foo) [bar](http://bar)

> `this` behaves `correctly`

リスト内で予期せぬ改行が挿入されるMarkdownの問題を修正 (#16637 by @byplayer)

<!-- Input -->
- Level 1
- Level 1-1

- Level 2

<!-- Prettier 3.5 -->
- Level 1

- Level 1-1

- Level 2


<!-- Prettier 3.6 -->
- Level 1
- Level 1-1

- Level 2

強い強調構文を修正 (#17143 by @fiji-flo)

ほとんどのMarkdown実装では1**_2_**3をサポートしていないため、1***2***3を使用するよう変更しました。

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

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

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

YAML

空のマップやシーケンスの前に改行を追加しないように修正 (#16074 by @BapRx)

# Input
---
myDict: {}
# comment
myList: []
# comment

# Prettier 3.5
---
myDict:
{}
# comment
myList:
[]
# comment

# Prettier 3.6
---
myDict: {}
# comment
myList: []
# comment

API

pluginsオプションでURLを受け入れるよう変更 (#17166 by @fisker)

pluginsオプションが、全てのパブリックAPIでfile:プロトコル付きのURLまたはfile:で始まるURL文字列を受け入れるようになりました。

// `URL`
await prettier.check("foo", {
parser: "my-cool-parser",
plugins: [new URL("./path/to/plugin.js", import.meta.url)],
});
await prettier.format("foo", {
parser: "my-cool-parser",
plugins: [new URL("./path/to/plugin.js", import.meta.url)],
});
await prettier.formatWithCursor("foo", {
parser: "my-cool-parser",
cursorOffset: 2,
plugins: [new URL("./path/to/plugin.js", import.meta.url)],
});
await prettier.getFileInfo("/path/to/file", {
plugins: [new URL("./path/to/plugin.js", import.meta.url)],
});
await prettier.getSupportInfo({
plugins: [new URL("./path/to/plugin.js", import.meta.url)],
});

// URL string
await prettier.check("foo", {
parser: "my-cool-parser",
plugins: ["file:///path/to/plugin.js"],
});
await prettier.format("foo", {
parser: "my-cool-parser",
plugins: ["file:///path/to/plugin.js"],
});
await prettier.formatWithCursor("foo", {
parser: "my-cool-parser",
cursorOffset: 2,
plugins: ["file:///path/to/plugin.js"],
});
await prettier.getFileInfo("/path/to/file", {
plugins: ["file:///path/to/plugin.js"],
});
await prettier.getSupportInfo({
plugins: ["file:///path/to/plugin.js"],
});

resolveConfigでカスタム設定ファイルとしてURLを受け入れるよう変更 (#17167 by @fisker)

prettier.resolveConfig() が、file:プロトコル付きのURL または file:で始まるURL文字列をカスタム設定ファイルの場所として受け入れるようになりました。

// `URL`
await prettier.resolveConfig("path/to/file", {
config: new URL("/path/to/prettier-config-file", import.meta.url),
});

// URL string
await prettier.resolveConfig("path/to/file", {
config: "file:///path/to/prettier-config-file",
});

*.fragファイルをJavaScriptファイルとして解釈しないように変更 (#17178 by @fisker)

これまで*.fragファイルはJavaScriptファイルとして解釈されていましたが、.frag拡張子はGLSL(OpenGL Shading Language)でも使用されます。PrettierがJavaScriptファイルとしてフォーマットしようとするとエラーが発生していました。

Prettier 3.6以降、*.start.frag, *.end.frag, start.frag, end.frag以外の*.fragファイルはJavaScriptファイルとして扱われなくなりました。

上記パターンに該当しないJavaScriptファイルを.frag拡張子で使用している場合は、overrides設定を使用してください。

export default {
overrides: {
files: "**/*.frag",
options: {
parser: "babel",
},
},
};

languages APIにisSupported関数を追加 (#17331 by @JounQin, #17490 by @fisker)

これまでカスタムプラグイン向けのlanguages APIは、ファイルのベースネームや拡張子に基づいてパーサを推論することしかサポートしていませんでした。

Prettier 3.6ではisSupported: (options: { filepath: string }) => boolean関数を追加し、プラグインがフルパスに基づいてファイルをサポートするかどうかをチェックできるようになりました(例:特定ディレクトリ内のファイル)。

注記

Prettierはfilepathがディスク上に存在することを保証できません。
API経由(例:prettier.format())で使用する場合、有効なパスかどうかも保証できません。

isSupportedが提供されない場合、従来と同じ動作になります。

export const languages = [
{
name: "foo",
parsers: ["foo"],
isSupported: ({ filepath }) => filepath.includes(".foo"),
},
];

mjmlパーサを追加 (#17339 by @fisker)

以前のバージョンでもhtmlパーサでMJMLをサポートしていましたが、MJML固有のフォーマットを区別するために新しいmjmlパーサが追加されました。

--check-ignore-pragmaでファイルを無視する機能を追加 (#17344 by @wnayes)

ファイル先頭に@noformatまたは@noprettierの「プラグマ」コメントを追加することで、個別ファイルのフォーマットを無効化できるようになりました。

この機能を有効にするには、新しいオプション--check-ignore-pragma(設定ファイルやAPIではcheckIgnorePragma)を使用してください。

言語プラグインはこの機能のサポートを実装できます。JavaScript(TypeScript)、CSS、HTML、JSON、Markdown(MDX)、YAML、GraphQLを含むほとんどのビルトインパーサーがこの機能をサポートするように更新されました。

/**
* @noformat
*/

export default matrix(
1, 0, 0,
0, 1, 0,
0, 0, 1
);

prettier.getFileInfo()のプラグイン読み込みを修正 (#17548 by @fisker)

以前のバージョンでは、prettier.getFileInfo().prettierrcからparser設定のみを読み取り、プラグインのlanguagesからパーサを推論するためにプラグインをロードしていませんでした。Prettier 3.6でこの問題を修正しました。

// prettier-plugin-foo
export const languages = [
{
parsers: ["foo"],
extensions: [".foo"],
},
];
# .prettierrc
plugins:
- prettier-plugin-foo
prettier --file-info file.foo

# Prettier 3.5
{ "ignored": false, "inferredParser": null }

# Prettier 3.6
{ "ignored": false, "inferredParser": "foo" }

プラグインによる組み込みパーサーのオーバーライドを推論時に許可 (#17549 by @fisker)

以前はファイルのパーサーを推論する際、組み込みプラグインが先にチェックされていたため、.jsのようなファイルに対してプラグインがパーサーをオーバーライドできませんでした。

// prettier-plugin-foo
export const languages = [
{
parsers: ["foo"],
extensions: [".js"],
},
];
// prettier.config.js
import * as prettierPluginFoo from "prettier-plugin-foo";

export default {
plugins: [prettierPluginFoo],
};
prettier --file-info file.js

# Prettier 3.5
{ "ignored": false, "inferredParser": "babel" }

# Prettier 3.6
{ "ignored": false, "inferredParser": "foo" }

CLI

--config--no-configの同時使用を禁止 (#12221 by @Balastrong)

$ prettier --config=.prettierrc --no-config .
[error] Cannot use --no-config and --config together.

--cache-strategy=content時にファイルの更新時刻を無視 (#17438 by @fisker)

以前のバージョンでは、--cache-strategy=content使用時にファイル内容が変更されていなくても更新時刻が変わると再フォーマットされていましたが、Prettier 3.6でこの問題を修正しました。

フォーマット不可能なファイルに対する結果メッセージを修正 (#17505 by @fisker)

touch unknown
prettier --check unknown

# Prettier 3.5
Checking formatting...
unknown
[error] No parser could be inferred for file "</path/to/unknown>".
All matched files use Prettier code style!

# Prettier 3.6
Checking formatting...
unknown
[error] No parser could be inferred for file "</path/to/unknown>".
Error occurred when checking code style in the above file.

パーサー推論失敗時のexitCodeを修正 (#17505 by @fisker)

touch unknown
prettier --check unknown > /dev/null;echo $?

# Prettier 3.5
[error] No parser could be inferred for file "</path/to/unknown>".
0

# Prettier 3.6
[error] No parser could be inferred for file "</path/to/unknown>".
2

その他の変更

cursorOffsetを使用した埋め込みフォーマットを修正 (#17254 by @fisker)

<!-- Input (--cursor-offset=1) -->
# Angular note

```typescript
import {Component} from '@angular/core';

@Component({
selector: 'app-root',
standalone: true,
imports: [],
template: `
<h1>

{{ title }}</h1>
`,
styleUrls: ['./app.component.css'],
})
export class AppComponent {
title = 'default';
}
```

<!-- Prettier 3.5 -->
Error: There are too many 'cursor' in doc.

<!-- Prettier 3.6 -->
# Angular note

```typescript
import { Component } from "@angular/core";

@Component({
selector: "app-root",
standalone: true,
imports: [],
template: `
<h1>
{{ title }}
</h1>
`,
styleUrls: ["./app.component.css"],
})
export class AppComponent {
title = "default";
}
```