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

Prettier 2.1: 新オプション --embedded-language-formatting と JavaScript/TypeScript 新機能の紹介!

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

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

このリリースでは新たに --embedded-language-formatting オプションが追加され、JavaScript/TypeScript の新機能をサポート。さらに多くのバグ修正と改善が含まれています!

主な変更点

API

--embedded-language-formatting={auto,off} オプションの追加 (#7875 by @bakkot, #8825 by @fisker)

Prettier は、JavaScript で html という名前のタグ付きテンプレートや Markdown のコードブロックなど、別のファイル内の文字列中にフォーマット可能なコードが含まれていると判断した場合、デフォルトでそのコードのフォーマットを試みます。

この動作はコードの挙動を変える可能性があるため、望ましくない場合があります。このオプションではデフォルト動作(auto)と機能完全無効化(off)を切り替えられます。JavaScript だけでなく、Prettier が埋め込みコードを認識するすべての言語に適用されます。

// Input
html`
<p>
I am expecting this to come out exactly like it went in.
`;

// using --embedded-language-formatting=auto (or omitting this option)
html`
<p>
I am expecting this to come out exactly like it went in.
</p>
`;

// using --embedded-language-formatting=off
html`
<p>
I am expecting this to come out exactly like it went in.
`;

TypeScript

TypeScript 4.0 のサポート

ラベル付きタプル要素 (#8885 by @fisker, #8982 by @sosukesuzuki)
// Input
type Range = [start: number, end: number];

// Prettier 2.0
SyntaxError: Unexpected token, expected "," (1:20)
> 1 | type Range = [start: number, end: number];

// Prettier 2.1
type Range = [start: number, end: number];
短絡代入演算子 (#8982 by @sosukesuzuki)
// Input
a ||= b;

// Prettier 2.0
SyntaxError: Expression expected. (1:5)
> 1 | a ||= b;

// Prettier 2.1
a ||= b;
catch 節の型注釈 (#8805 by @fisker)
// Input
try {} catch (e: any) {}

// Prettier 2.0
try {
} catch (e) {}

// Prettier 2.1
try {
} catch (e: any) {}

その他の変更点

JavaScript

F# および Smart パイプライン演算子の提案をサポート (#6319 by @sosukesuzuki, @thorn0, #7979 by @sosukesuzuki)

F# スタイルのパイプライン:

// Input
promises |> await;

// Output (Prettier 2.0)
SyntaxError: Unexpected token (1:18)
> 1 | promises |> await;
| ^

// Output (Prettier 2.1)
promises |> await;

Smart パイプライン:

// Input
5 |> # * 2

// Output (Prettier 2.0)
SyntaxError: Unexpected character '#' (1:6)
> 1 | 5 |> # * 2
| ^

// Output (Prettier 2.1)
5 |> # * 2

末尾の空白が続く行末コメントの修正 (#8069 by @shisama)

コメント行に末尾の空白がある場合、コメントが行末コメントとして検出されませんでした。

// Input
var a = { /* extra whitespace --> */
b };

var a = { /* no whitespace --> */
b };

// Prettier 2.0
var a = {
/* extra whitespace --> */

b,
};

var a = {
/* no whitespace --> */ b,
};

// Prettier 2.1
var a = {
/* extra whitespace --> */ b,
};

var a = {
/* no whitespace --> */ b,
};

styled-components のテンプレートリテラル内でインジェクションされた式のパースが一貫しない問題を修正 (#8097 by @thecodrr)

// Input
const SingleConcat = styled.div`
${something()}
& > ${Child}:not(:first-child) {
margin-left:5px;
}
`

const MultiConcats = styled.div`
${something()}
& > ${Child}${Child2}:not(:first-child) {
margin-left:5px;
}
`

const SeparatedConcats = styled.div`
font-family: "${a}", "${b}";
`

// Prettier 2.0 -- same as input

// Prettier 2.1
const SingleConcat = styled.div`
${something()}
& > ${Child}:not(:first-child) {
margin-left: 5px;
}
`;

const MultiConcats = styled.div`
${something()}
& > ${Child}${Child2}:not(:first-child) {
margin-left: 5px;
}
`;

const SeparatedConcats = styled.div`
font-family: "${a}", "${b}";
`;

末尾プロパティが無視されるオブジェクト末尾カンマの問題を修正 (#8111 by @fisker)

// Input
const foo = {
// prettier-ignore
bar: "baz"
}

// Prettier 2.0
const foo = {
// prettier-ignore
bar: "baz"
};

// Prettier 2.1
const foo = {
// prettier-ignore
bar: "baz",
};

エスケープシーケンスを含むオブジェクトキーをそのまま保持 (#8160 by @fisker)

// Input
const a = {
"\u2139": 'why "\\u2139" converted to "i"?',
};

// Prettier 2.0
const a = {
: 'why "\\u2139" converted to "i"?',
};


// Prettier 2.1
const a = {
"\u2139": 'why "\\u2139" is converted to "i"?',
};

CSS-in-JS におけるマイナス記号後の余分なスペースを修正 (#8255 by @thorn0)

// Input
css`
color: var(--global--color--${props.color});
`

// Prettier 2.0
css`
color: var(--global--color-- ${props.color});
`;

// Prettier 2.1
css`
color: var(--global--color--${props.color});
`;

クラス宣言/式の extends 部分にあるコメントを修正 (#8312 by @thorn0)

// Input
class a extends a // comment
{
constructor() {}
}

// Prettier 2.0
class a extends a // comment {
constructor() {}
}

// Prettier 2.1
class a extends a { // comment
constructor() {}
}

Jest の test.each テンプレート文字列内で配列をラップしないように変更 (#8354 by @yogmel)

// Input
test.each`
a | b | c
${1} | ${[{ start: 1, end: 3 },{ start: 15, end: 20 },]} | ${[]}
`("example test", ({a, b, c}) => {})

// Prettier 2.0
test.each`
a | b | c
${1} | ${[
{ start: 1, end: 3 },
{ start: 15, end: 20 }
]} | ${[]}
`("example test", ({ a, b, c }) => {});

// Prettier 2.1
test.each`
a | b | c
${1} | ${[{ start: 1, end: 3 }, { start: 15, end: 20 }]} | ${[]}
`("example test", ({ a, b, c }) => {});

shebang を含むファイルで insertPragmarequirePragma をサポート (#8376 by @fisker)

// `--insert-pragma`
// Input
#!/usr/bin/env node
hello
.world();

// Prettier 2.0
SyntaxError: Unexpected token (3:1)
1 | /** @format */
2 |
> 3 | #!/usr/bin/env node
| ^
4 | hello
5 | .world();

// Prettier 2.1
#!/usr/bin/env node
/** @format */

hello.world();

// `--require-pragma`
// Input
#!/usr/bin/env node
/**
* @format
*/
hello
.world();

// Prettier 2.0
#!/usr/bin/env node
/**
* @format
*/
hello
.world();

// Prettier 2.1
#!/usr/bin/env node
/**
* @format
*/
hello.world();

範囲指定フォーマットのインデントを修正 (#8410 by @thorn0)

> echo -e "export default class Foo{\n/**/\n}" | prettier --range-start 16 --range-end 31 --parser babel
// Prettier 2.0
export default class Foo {
/**/
}

// Prettier 2.1
export default class Foo {
/**/
}

範囲指定フォーマットのソース要素検出を改善 (#8419 by @thorn0)

すべての文タイプが検出されていませんでした(Prettierにおける範囲指定フォーマットの仕組みはこちらで説明されています)。

// Input
for (const element of list) { /* ... */ }
// ^^^^^^^^^^^^^^^^^^^^^^ ← range

// Prettier 2.0
for (const element of list) { /* ... */ }

// Prettier 2.1
for (const element of list) {
/* ... */
}

in 演算子でのプライベートフィールドをサポート (#8431 by @sosukesuzuki)

Stage-2 プロポーザル Private Fields in in をサポート。

// Input
#prop in obj;

// Prettier 2.0
SyntaxError: Unexpected token (1:1)
> 1 | #prop in obj;
| ^
2 |

// Prettier 2.1
#prop in obj;

ES Module Attributes と JSON モジュールをサポート (#8436 by @fisker)

Stage-2 プロポーザル ES Module Attributes and JSON modules をサポート。

// Input
import foo from "foo.json" with type: "json";

// Prettier 2.0
SyntaxError: Unexpected token, expected ";" (1:28)
> 1 | import foo from "foo.json" with type: "json";
| ^

// Prettier 2.1
import foo from "foo.json" with type: "json";

record と tuple 構文をサポート (#8453 by @fisker)

Stage-2 プロポーザル JavaScript Records & Tuples Proposal をサポート。

#[]/#{} 構文のみをサポート({| |} / [| |] は未サポート)

Tuples(タプル)

// Input
#[1, 2, 3]

// Prettier 2.0
SyntaxError: Unexpected token (1:1)
> 1 | #[1, 2, 3]
| ^


// Prettier 2.1
#[1, 2, 3];

Records(レコード)

// Input
#{
a: 1,
b: 2,
c: 3,
}

// Prettier 2.0
SyntaxError: Unexpected token (1:1)
> 1 | #{
| ^
2 | a: 1,
3 | b: 2,
4 | c: 3,


// Prettier 2.1
#{
a: 1,
b: 2,
c: 3,
};

"<" の左側にある JSX 要素を括弧でラップ (#8461 by @sosukesuzuki)

// Input
(<div/>) < 5;

// Prettier 2.0
<div/> < 5;

// Prettier 2.0 second output
SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>? (1:9)
> 1 | <div /> < 5;
| ^
2 |

// Prettier 2.1
(<div />) < 5;

末尾コメントを含む二項式のインデントを修正 (#8476 by @sosukesuzuki)

// Input
a +
a + // comment
a;

// Prettier 2.0
a +
a + // comment
a;

// Prettier 2.1
a +
a + // comment
a;

バイナリ式内のコメントの不安定な動作を修正 (#8491 by @thorn0)

// Input
Math.min(
(
/* foo */
document.body.scrollHeight -
(window.scrollY + window.innerHeight)
) - devsite_footer_height,
0,
)

// Prettier 2.0 (first output)
Math.min(
/* foo */
document.body.scrollHeight -
(window.scrollY + window.innerHeight) -
devsite_footer_height,
0
);

// Prettier 2.0 (second output)
Math.min(
/* foo */
document.body.scrollHeight -
(window.scrollY + window.innerHeight) -
devsite_footer_height,
0
);

// Prettier 2.1 (first and second outputs)
Math.min(
/* foo */
document.body.scrollHeight -
(window.scrollY + window.innerHeight) -
devsite_footer_height,
0
);
// Input
const topOfDescriptionBox =
Layout.window.width + // Images are 1:1 aspect ratio, full screen width
Layout.headerHeight;

// Prettier 2.0 (first output)
const topOfDescriptionBox =
Layout.window.width + Layout.headerHeight; // Images are 1:1 aspect ratio, full screen width

// Prettier 2.0 (second output)
const topOfDescriptionBox = Layout.window.width + Layout.headerHeight; // Images are 1:1 aspect ratio, full screen width

// Prettier 2.1 (first and second outputs)
const topOfDescriptionBox =
Layout.window.width + // Images are 1:1 aspect ratio, full screen width
Layout.headerHeight;

数値キーの引用符付け/除去をサポート (#8508 by @lydell)

Prettierはオブジェクトキーが識別子の場合、引用符を除去します。今回の変更で、数値のオブジェクトキーからも引用符を除去するようになりました。

quoteProps: "consistent"を使用する場合、Prettierは数値キーに引用符を追加することもでき、これによりすべてのプロパティが引用符付きになります。

// Input
x = {
"a": null,
"1": null,
};

// Prettier 2.0
x = {
a: null,
"1": null,
};

// Prettier 2.1
x = {
a: null,
1: null,
};

Prettierが処理するのは1123.5のような「単純な」数値のみです。以下のような変換は予期せぬ結果となるため行いません:

1e2 -> "100"
0b10 -> "10"
1_000 -> "1000"
1.0 -> "1"
0.99999999999999999 -> "1"
999999999999999999999 -> "1e+21"
2n -> "2"

"1e+100" -> 1e100

(混乱を招く数値をオブジェクトキーとして使用しないでください!)

注意:Prettierが数値の引用符を除去するのは"babel"パーサーのみです。TypeScriptでは完全に安全とは言えません。

条件付きタイプの"?"後にコメントがある場合、先頭コメントを優先 (#8557 by @sosukesuzuki)

// Input
type A = B extends T
? // comment
foo
: bar;

// Prettier 2.0
type A = B extends T // comment
? foo
: bar;

// Prettier 2.1
type A = B extends T
? // comment
foo
: bar;

複数行ブロックコメントを含む三項演算子を改行 (#8592 by @sosukesuzuki)

// Input
test
? /* comment
comment
*/
foo
: bar;

// Prettier 2.0
test ? /* comment
comment
*/ foo : bar;

// Prettier 2.1
test
? /* comment
comment
*/
foo
: bar;

クラスメソッド間のコメントペアの不安定な動作を修正 (#8731 by @fisker)

// Input
class C {
ma() {} /* D */ /* E */
mb() {}
}

// Prettier 2.0
class C {
ma() {} /* E */ /* D */
mb() {}
}

// Prettier 2.0 (Second format)
class C {
ma() {} /* D */ /* E */
mb() {}
}

// Prettier 2.1
class C {
ma() {} /* D */ /* E */
mb() {}
}

重複したprettier-ignoreコメントを修正 (#8742 by @fisker)

// Input
a = <div {.../* prettier-ignore */{}}/>
a = <div {...{}/* prettier-ignore */}/>

// Prettier 2.0
a = <div {/* prettier-ignore */ .../* prettier-ignore */ {}} />;
a = <div {...{} /* prettier-ignore */ /* prettier-ignore */} />;

// Prettier 2.1
a = <div {.../* prettier-ignore */ {}} />;
a = <div {...{} /* prettier-ignore */} />;

Decimal Proposalをサポート (#8901 by @fisker)

Stage-1提案のDecimal Proposalをサポートしました。

// Input
0.3m;

// Prettier 2.0
SyntaxError: Identifier directly after number (1:4)
> 1 | 0.3m;

// Prettier 2.1
0.3m;

JSXをyieldする際に括弧を追加 (#9011 by @fisker)

v2.0.0JSXをyieldする際の不要な括弧を削除しましたが、ESLintがパース時にエラーをスローする関連issueがあるため修正しました。

// Input
function* f() {
yield <div>generator</div>
}

// Prettier 2.0
function* f() {
yield <div>generator</div>
}

// Prettier 2.1
function* f() {
yield (<div>generator</div>);
}

TypeScript

(a:b)構文で適切な構文エラーを出力するようbabel-tsパーサーを修正 (#8046 by @thorn0)

以前はこのコードはエラーなくパースされましたが、プリント時にスタックトレース付きの不親切なエラーがスローされていました。現在はパーサーが適切な構文エラーをスローします。

// Input
(a:b)

// Prettier 2.0
[error] test.ts: Error: unknown type: "TSTypeCastExpression"
[error] ... [a long stack trace here] ...

// Prettier 2.1
[error] test.ts: SyntaxError: Did not expect a type annotation here. (1:2)
[error] > 1 | (a:b)
[error] | ^
[error] 2 |

ディレクティブと解釈されないよう文字列リテラルを括弧で囲む (#8422 by @thorn0)

Prettierはステートメント位置にある文字列リテラルを括弧で囲みます。なぜなら、関数やプログラムの先頭にある場合、そのような文字列はディレクティブとして解釈され、プログラムの動作を変更する可能性があるためです。技術的には、関数やプログラムの最初の行にない文字列に対してこれを行う必要はありません。しかし、一貫性を持たせることでバグの可視化にもつながります。例としてこのTwitterスレッドを参照してください。

以前は、typescriptパーサーでこの動作が一貫して機能していませんでした。括弧で既に囲まれている文字列のみが括弧を保持していました。

// Input
f();
'use foo';
('use bar');

// Prettier 2.0
f();
"use foo";
("use bar");

// Prettier 2.1
f();
("use foo");
("use bar");

オプショナルチェイニングと非nullアサーションに対するTypeScript 3.9の破壊的変更をサポート (#8450 by @sosukesuzuki)

詳細: https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#breaking-changes

// Input
(a?.b)!.c;

// Prettier 2.0
a?.b!.c;

// Prettier 2.1
(a?.b)!.c;

Flow

関数型パラメータにnullableパラメータが含まれる場合の修正 (#8365 by @fisker)

// Input
let f: <A>(
((?A) => B),
) => B;

// Prettier 2.0
let f: <A>((?A) => B) => B;

// Prettier 2.0 (Second format)
SyntaxError: Unexpected token (1:12)
> 1 | let f: <A>((?A) => B) => B;

// Prettier 2.1
let f: <A>(((?A) => B)) => B;

Flow Enumのデフォルトエクスポート修正 (#8768 by @gkz)

Flow Enumをデフォルトエクスポートする場合、末尾のセミコロンを追加しないように修正。

// Input
export default enum B {}

// Prettier 2.0
export default enum B {};

// Prettier 2.1
export default enum B {}

CSS

at-rule末尾のコメントによるコード改行を防止 (#7009 by @evilebottnawi)

/* Input */
@at-root .foo
// .bar
{

}

/* Prettier 2.0 */
@at-root .foo
// .bar {
}

/* Prettier 2.1 */
@at-root .foo
// .bar
{
}

url()内の引用符なしコンテンツ操作の修正 (#7592 by @mattiacci)

CSS/SCSS/Lessにおける引用符なしURLコンテンツの処理を改善。根本的なパース問題は解決していませんが、PrettierがURLを変更しないことを保証します。

/* Input */
@import url(https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&display=swap);
@import url(//fonts.googleapis.com/css?family=#{ get-font-family('Roboto') }:100,300,500,700,900&display=swap);
.validUnquotedUrls{
background: url(data/+0ThisShouldNotBeLowerCased);
background: url(https://foo/A*3I8oSY6AKRMAAAAAAAAAAABkARQnAQ);
background: url(https://example.com/some/quite,long,url,with,commas.jpg);
}

/* Prettier 2.0 */
@import url(
https://fonts.googleapis.com/css?family=Roboto:100,
300,
400,
500,
700,
900&display=swap
);
@import url(
//fonts.googleapis.com/css?family=#{get-font-family("Roboto")}:100,
300,
500,
700,
900&display=swap
);
.validUnquotedUrls {
background: url(data/+0thisshouldnotbelowercased);
background: url(https://foo/A*3i8osy6akrmaaaaaaaaaaabkarqnaq);
background: url(https://example.com/some/quite, long, url, with, commas.jpg);
}


/* Prettier 2.1 */
@import url(https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&display=swap);
@import url(//fonts.googleapis.com/css?family=#{ get-font-family('Roboto') }:100,300,500,700,900&display=swap);
.validUnquotedUrls{
background: url(data/+0ThisShouldNotBeLowerCased);
background: url(https://foo/A*3I8oSY6AKRMAAAAAAAAAAABkARQnAQ);
background: url(https://example.com/some/quite,long,url,with,commas.jpg);
}

CSSグリッドライン名でエスケープされたコロンの後に誤って空白が追加される問題を修正 (#8535 by @boyenn)

/* Input */
.grid {
grid-template-rows:
[row-1-00\:00] auto;
}

/* Prettier 2.0 */
.grid {
grid-template-rows: [row-1-00\: 00] auto;
}

/* Prettier 2.1 */
.grid {
grid-template-rows: [row-1-00\:00] auto;
}

@supports selector(<custom-selector>) のサポート追加 (#8545 by @boyenn)

/* Input */
@supports selector(:focus-visible) {
button:focus {
outline: none;
}

button:focus-visible {
outline: 2px solid orange;
}
}

/* Prettier 2.0 */
@supports selector(: focus-visible) {
button:focus {
outline: none;
}

button:focus-visible {
outline: 2px solid orange;
}
}

/* Prettier 2.1 */
@supports selector(:focus-visible) {
button:focus {
outline: none;
}

button:focus-visible {
outline: 2px solid orange;
}
}

任意引数のPrettier処理を改善 (#8567, #8566 by @boyenn)

関数に任意引数を渡す際に、予期せず余分なスペースが追加されなくなりました。 インラインの数値リストが任意引数として使用される場合のコード改行も修正されました。

/* Input */
body {
test: function($list...);
foo: bar(returns-list($list)...);
background-color: rgba(50 50 50 50...);
}

/* Prettier 2.0 */
body {
test: function($list...);
foo: bar(returns-list($list) ...);
background-color: rgba(50 50 50 50..);
}

/* Prettier 2.1 */
body {
test: function($list...);
foo: bar(returns-list($list)...);
background-color: rgba(50 50 50 50...);
}

SCSS

SCSS内のコメント後に続く行の余分なインデントを修正 (#7844 by @boyenn)

以前は、SCSSマップ内のコメント後に続く行に余分なインデントが適用されていました。 この修正により、不要なインデントが適用されなくなりました。

/* Input */
$my-map: (
'foo': 1, // Foo
'bar': 2, // Bar
);

/* Prettier 2.0 */
$my-map: (
"foo": 1,
// Foo
"bar": 2,
// Bar
);

/* Prettier 2.1 */
$my-map: (
"foo": 1,
// Foo
"bar": 2,
// Bar
);

プロパティと値の間にあるインラインコメントの処理を修正 (#8366 by @fisker)

// Input
a {
color: // comment
red;
}

// Prettier 2.0
a {
color: // comment red;
}

// Prettier 2.1
a {
color: // comment
red;
}

最終セミコロンが省略された場合のファイル末尾コメント消失問題を修正 (#8675 by @fisker)

// Input
@mixin foo() {
a {
color: #f99;
}
}

@include foo() /* comment*/

// Prettier 2.0
@mixin foo() {
a {
color: #f99;
}
}

@include foo();

// Prettier 2.1
@mixin foo() {
a {
color: #f99;
}
}

@include foo(); /* comment*/

Less

:extend 擬似クラスの修正 (#8178 by @fisker)

以前はセレクタが値としてパースされていましたが、現在はセレクタとして認識されるようになりました。

// Input
.hello {
&:extend(.input[type="checkbox"]:checked ~ label)}

// Prettier 2.0
.hello {
&:extend(.input[type= "checkbox" ]: checked ~label);
}

// Prettier 2.1
.hello {
&:extend(.input[type="checkbox"]:checked ~ label);
}

/* を含むインラインコメントの修正 (#8360 by @fisker)

インラインコメントに /* が含まれている場合、他のコメントが正しく出力されない問題がありました。

// Input
@import "a";

// '/*' <-- this breaks formatting

@import 'b';
/* block */
/*no-space block*/

// Prettier 2.0
@import "a";

// '/*' <-- this breaks formatting

@import "b";

@import 'b
@import 'b';
/* bl

// Prettier 2.1
@import "a";

// '/*' <-- this breaks formatting

@import "b";
/* block */
/*no-space block*/

HTML

単一行スタイル属性の末尾セミコロンを省略 (#8013 by @bschlenk)

<!-- Input -->
<div style="margin: 0; padding: 20px"></div>
<div style="margin: 0; padding: 20px; position: relative; display: inline-block; color: blue"></div>

<!-- Prettier 2.0 -->
<div style="margin: 0; padding: 20px;"></div>
<div
style="
margin: 0;
padding: 20px;
position: relative;
display: inline-block;
color: blue;
"
></div>

<!-- Prettier 2.1 -->
<div style="margin: 0; padding: 20px"></div>
<div
style="
margin: 0;
padding: 20px;
position: relative;
display: inline-block;
color: blue;
"
></div>

HTML内の非ASCII空白文字を保持 (#8137 by @fisker)

U+00A0U+2005 などの非ASCII空白文字はHTMLでは空白と見なされないため、削除すべきではありません。

// Prettier 2.0
[...require("prettier").format("<i> \u2005 </i>", { parser: "html" })]
.slice(3, -5)
.map((c) => c.charCodeAt(0).toString(16));

// -> [ '20' ]
// `U+2005` is removed

// Prettier 2.1
[...require("prettier").format("<i> \u2005 </i>", { parser: "html" })]
.slice(3, -5)
.map((c) => c.charCodeAt(0).toString(16));

// -> [ '20', '2005', '20' ]

レガシーなHTML風コメントを含むスクリプトブロックのサポート (#8173 by @fisker, #8394 by @fisker)

以前はHTMLの <script> ブロックを「モジュール」(ECMAScript Module grammar)としてパースしていたため、<!-- で始まるHTML風コメント(別名HTML-like comments)を処理できませんでした。現在では、<script> ブロックを「スクリプト」としてパースしますが、この <script> を除きます。

  1. type="module"

  2. type="text/babel" かつ data-type="module"babel@v7.10.0で導入

<!-- Input -->
<SCRIPT>
<!--
alert("hello" + ' world!')
//--></SCRIPT>

<!-- Prettier 2.0 -->
SyntaxError: Unexpected token (2:1)
1 |
> 2 | <!--
| ^
3 | alert("hello" + ' world!')
4 | //-->

<!-- Prettier 2.1 -->
<script>
<!--
alert("hello" + " world!");
//-->
</script>

<select>をインラインブロック、<optgroup>/<option>をブロック要素として扱う (#8275 by @thorn0, #8620 by @fisker)

Prettierが selectoptionoptgroup タグ内の空白追加を安全に行えるようになりました。

<!-- Input -->
<select><option>Blue</option><option>Green</option><optgroup label="Darker"><option>Dark Blue</option><option>Dark Green</option></optgroup></select>

<!-- Prettier 2.0 -->
<select
><option>Blue</option
><option>Green</option
><optgroup label="Darker"
><option>Dark Blue</option><option>Dark Green</option></optgroup
></select
>

<!-- Prettier 2.1 -->
<select>
<option>Blue</option>
<option>Green</option>
<optgroup label="Darker">
<option>Dark Blue</option>
<option>Dark Green</option>
</optgroup>
</select>

srcset内のカンマを含むURLの修正 (#8359 by @fisker)

<!-- Input -->
<img
srcset="
_20200401_145009_szrhju_c_scale,w_200.jpg 200w,
_20200401_145009_szrhju_c_scale,w_1400.jpg 1400w"
src="_20200401_145009_szrhju_c_scale,w_1400.jpg"
>

<!-- Prettier 2.0 -->
<img
srcset="
_20200401_145009_szrhju_c_scale,
w_200.jpg 200w,
_20200401_145009_szrhju_c_scale,
w_1400.jpg 1400w
"
src="_20200401_145009_szrhju_c_scale,w_1400.jpg"
/>

<!-- Prettier 2.1 -->
<img
srcset="
_20200401_145009_szrhju_c_scale,w_200.jpg 200w,
_20200401_145009_szrhju_c_scale,w_1400.jpg 1400w
"
src="_20200401_145009_szrhju_c_scale,w_1400.jpg"
/>

<script type="text/html> のサポート (#8371 by @sosukesuzuki)

<!-- Input -->
<script type="text/html">
<div>
<p>foo</p>
</div>
</script>

<!-- Prettier 2.0 -->
<script type="text/html">
<div>
<p>foo</p>
</div>
</script>

<!-- Prettier 2.1 -->
<script type="text/html">
<div>
<p>foo</p>
</div>
</script>

動的言語指定を含むフロントマターのサポート (#8381 by @fisker)

フロントマターの動的言語検出をサポート。csslessscssmarkdown パーサーでも利用可能です。

<!-- Input -->
---my-awsome-language
title: Title
description: Description
---
<h1>
prettier</h1>

<!-- Prettier 2.0 -->
---my-awsome-language title: Title description: Description ---

<h1>
prettier
</h1>

<!-- Prettier 2.1 -->
---my-awsome-language
title: Title
description: Description
---

<h1>
prettier
</h1>

テキストのみのコンテンツ周囲の改行を保持しない (#8614 by @fisker)

以前、Prettierはインラインノード(インライン要素、テキスト、補間など)周囲の改行を常に維持していました。一般的にPrettierは可能な限り元の書式に依存しないようにしていますが、インラインノードを単一行に折りたたむことが望ましくないケースが少なくとも2つ存在します。具体的にはリスト形式のコンテンツと条件分岐構造(例:Vueのv-if/v-else)です。これらのケースを検出する適切な方法が見つからなかったため、このようなトレードオフが選択されました。しかし、テキストのみのコンテンツでは、このルールの緩和は不要であり、混乱を招く一貫性のないフォーマットにつながることが判明しました。

<!-- Input -->
<div>
Hello, world!
</div>
<div>
Hello, {{ username }}!
</div>

<!-- Prettier 2.0 -->
<div>
Hello, world!
</div>
<div>Hello, {{ username }}!</div>

<!-- Prettier 2.1 -->
<div>Hello, world!</div>
<div>Hello, {{ username }}!</div>

既知のHTMLタグを認識する (#8621 by @fisker)

<!-- Input -->
<div>before<details><summary>summary long long long long </summary>details</details>after</div>
<div>before<dialog open>dialog long long long long long long long long </dialog>after</div>
<div>before<object data="horse.wav"><param name="autoplay" value="true"/><param name="autoplay" value="true"/></object>after</div>

<!-- Prettier 2.0 -->
<div>
before<details><summary>summary long long long long </summary>details</details
>after
</div>
<div>
before<dialog open>dialog long long long long long long long long </dialog
>after
</div>
<div>
before<object data="horse.wav"
><param name="autoplay" value="true" /><param
name="autoplay"
value="true" /></object
>after
</div>

<!-- Prettier 2.1 -->
<div>
before
<details>
<summary>summary long long long long</summary>
details
</details>
after
</div>
<div>
before
<dialog open>dialog long long long long long long long long</dialog>
after
</div>
<div>
before<object data="horse.wav">
<param name="autoplay" value="true" />
<param name="autoplay" value="true" /></object
>after
</div>

最後の子要素がvoid要素である要素のフォーマットを修正 (#8643 by @ikatyang)

<!-- Input -->
<video controls width="250">
<source src="/media/examples/flower.webm"
type="video/webm">
<source src="/media/examples/flower.mp4"
type="video/mp4"
></video>text after

<!-- Prettier 2.0 -->
<video controls width="250">
<source src="/media/examples/flower.webm" type="video/webm" />
<source src="/media/examples/flower.mp4" type="video/mp4" /></video

>text after

<!-- Prettier 2.1 -->
<video controls width="250">
<source src="/media/examples/flower.webm" type="video/webm" />
<source src="/media/examples/flower.mp4" type="video/mp4" /></video
>text after

Vue

Vue SFCルートブロックのフォーマット改善 (#8023 by @sosukesuzuki, #8465 by @fisker)

言語ブロックlang属性付きのカスタムブロックを含む)すべてのフォーマットをビルトインパーサープラグインでサポートします。

<!-- Input -->
<template lang="pug">
div.text( color = "primary", disabled ="true" )
</template>
<i18n lang="json">
{
"hello": 'prettier',}
</i18n>

<!-- Prettier 2.0 -->
<template lang="pug">
div.text( color = "primary", disabled ="true" )
</template>
<i18n lang="json">
{
"hello": 'prettier',}
</i18n>

<!-- Prettier 2.1 -->
<template lang="pug">
.text(color="primary", disabled="true")
</template>
<i18n lang="json">
{
"hello": "prettier"
}
</i18n>

※この例には @prettier/plugin-pug が必要です。

カスタムブロックのパース処理を改善 (#8153 by @sosukesuzuki)

<!-- Input -->
<custom lang="javascript">
const foo = "</";
</custom>

<!-- Prettier 2.0 -->
SyntaxError: Unexpected character """ (2:19)
[error] 1 | <custom lang="javascript">
[error] > 2 | const foo = "</";
[error] | ^
[error] 3 | </custom>

<!-- Prettier 2.1 -->
<custom lang="javascript">
const foo = "</";
</custom>

大文字HTMLタグでのフォーマット崩れを修正 (#8280 by @fisker)

<!-- Input -->
<!doctype html><HTML></HTML>

<!-- Prettier 2.0 -->
<!DOCTYPE html>><HTML></HTML>

<!-- Prettier 2.1 -->
<!DOCTYPE html><HTML></HTML>

Vue SFCの1行templateにおける不自然なフォーマットを修正 (#8325 by @sosukesuzuki)

<!-- Input -->
<template><p>foo</p><div>foo</div></template>

<!-- Prettier 2.0 -->
<template
><p>foo</p>
<div>foo</div></template
>

<!-- Prettier 2.1 -->
<template>
<p>foo</p>
<div>foo</div>
</template>

Vue DOM Templateをサポート (#8326 by @sosukesuzuki)

HTMLにvueパーサーを使用する場合、テンプレートをHTMLとしてパースします。

<!-- Input -->
<!DOCTYPE html>
<html>
<body STYLE="color: #333">
<DIV id="app">
<DIV>First Line</DIV><DIV>Second Line</DIV>
</DIV>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data() {
return {}
},
});
</script>
</body>
</html>

<!-- Prettier 2.0 -->
<!DOCTYPE html>
<html>
<body STYLE="color: #333">
<DIV id="app"> <DIV>First Line</DIV><DIV>Second Line</DIV> </DIV>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data() {
return {};
},
});
</script>
</body>
</html>

<!-- Prettier 2.1 -->
<!DOCTYPE html>
<html>
<body style="color: #333">
<div id="app">
<div>First Line</div>
<div>Second Line</div>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data() {
return {};
},
});
</script>
</body>
</html>

DOMテンプレート内の大文字HTMLタグフォーマットを改善 (#8337 by @sosukesuzuki)

<!-- Input -->
<!DOCTYPE html><HTML>
<body>
<div v-if="foo === 'foo'">

</div>
<script>
new Vue({el: '#app'})
</script>
</body>
</HTML>

<!-- Prettier 2.0 -->
<!DOCTYPE html>
<HTML>
<body>
<div v-if="foo === 'foo'">

</div>
<script>
new Vue({el: '#app'})
</script>
</body>
</HTML>

<!-- Prettier 2.1 -->
<!DOCTYPE html>
<HTML>
<body>
<div v-if="foo === 'foo'"></div>
<script>
new Vue({ el: "#app" });
</script>
</body>
</HTML>

括弧付き補間のフォーマットを修正 (#8747 by @fisker)

<!-- Input -->
<template>
<span>{{(a|| b)}} {{z&&(a&&b)}}</span>
</template>

<!-- Prettier 2.0 -->
<template>
<span>{{(a|| b)}} {{z&&(a&&b)}}</span>
</template>

<!-- Prettier 2.1 -->
<template>
<span>{{ a || b }} {{ z && a && b }}</span>
</template>

名前付きスロットの省略記法の値がフォーマットされない問題を修正 (#8839 by @wenfangdu)

<!-- Input -->
<template>
<div #default="{foo:{bar:{baz}}}"></div>
</template>

<!-- Prettier 2.0 -->
<template>
<div #default="{foo:{bar:{baz}}}"></div>
</template>

<!-- Prettier 2.1 -->
<template>
<div #default="{ foo: { bar: { baz } } }"></div>
</template>

Angular

オプショナルチェイニングと算出プロパティの修正、および this の取り扱い改善 (#8253 by @thorn0, #7942 by @fiskerangular-estree-parser での修正 by @ikatyang)

<!-- Input -->
{{ a?.b[c] }}
{{ a ( this )}}

<!-- Prettier 2.0 -->
{{ (a?.b)[c] }}
{{ a ( this )}}

<!-- Prettier 2.1 -->
{{ a?.b[c] }}
{{ a(this) }}

AngularJS 1.x互換性のため、オブジェクトリテラル内パイプ周囲の括弧を保持するように修正 (#8254 by @thorn0)

<!-- Input -->
<div ng-style="{ 'color': ('#222' | darken)}"></div>

<!-- Prettier 2.0 -->
<div ng-style="{ color: '#222' | darken }"></div>

<!-- Prettier 2.1 -->
<div ng-style="{ 'color': ('#222' | darken)}"></div>

Handlebars (アルファ版)

単純テキスト以外の複雑な属性値周囲でsingleQuoteオプションを尊重するように修正 (#8375 by @dcyriller)

{{!-- Input --}}
<a href='/{{url}}'></a>
<a href="/{{url}}"></a>

<a href='url'></a>
<a href="url"></a>

{{!-- Prettier 2.0 --}}
<a href="/{{url}}"></a>
<a href="/{{url}}"></a>

<a href='url'></a>
<a href='url'></a>

{{!-- Prettier 2.1 --}}
<a href='/{{url}}'></a>
<a href='/{{url}}'></a>

<a href='url'></a>
<a href='url'></a>

要素内のクラシックコンポーネントのフォーマットを修正 (#8593 by @mikoscz)

{{!-- Input --}}
<div>
{{classic-component-with-many-properties
class="hello"
param=this.someValue
secondParam=this.someValue
thirdParam=this.someValue
}}
</div>

{{!-- Prettier 2.0 --}}
<div>
{{
classic-component-with-many-properties
class="hello"
param=this.someValue
secondParam=this.someValue
thirdParam=this.someValue
}}
</div>

{{!-- Prettier 2.1 --}}
<div>
{{classic-component-with-many-properties
class="hello"
param=this.someValue
secondParam=this.someValue
thirdParam=this.someValue
}}
</div>

バックスラッシュによるMustacheのエスケープをサポート (#8634 by @dcyriller)

{{!-- Input --}}
\{{mustache}}
\\{{mustache}}
\\\{{mustache}}

{{!-- Prettier 2.0 --}}
{{mustache}}
\{{mustache}}
\\{{mustache}}

{{!-- Prettier 2.1 --}}
\{{mustache}}
\\{{mustache}}
\\\{{mustache}}

属性内でクラス名のみをフォーマットするように修正 (#8677 by @dcyriller)

{{!-- Input --}}
<div class=' class '></div>
<div title=' other attribute '></div>

{{!-- Prettier 2.0 --}}
<div class="class"></div>
<div title="other attribute"></div>

{{!-- Prettier 2.1 --}}
<div class="class"></div>
<div title=" other attribute "></div>

GraphQL

GraphQLフラグメントディレクティブの折り返しを改善 (#7721 by @sasurau4)

# Input
fragment TodoList_list on TodoList @argumentDefinitions(
count: {type: "Int", defaultValue: 10},
) {
title
}

# Prettier 2.0
fragment TodoList_list on TodoList
@argumentDefinitions(count: { type: "Int", defaultValue: 10 }) {
title
}

# Prettier 2.1
fragment TodoList_list on TodoList
@argumentDefinitions(count: { type: "Int", defaultValue: 10 }) {
title
}

インターフェース間のコメント処理を修正 (#8006 by @fisker)

# Input
type Type1 implements
A &
# comment 1
B
# comment 2
& C {a: a}

# Prettier 2.0
type Type1 implements A & # comment 1
B & # comment 2
C {
a: a
}

# Prettier 2.0 (Second format)
type Type1 implements A & B & C { # comment 1 # comment 2
a: a
}

# Prettier 2.1
type Type1 implements A &
# comment 1
B &
# comment 2
C {
a: a
}

インターフェースが他のインターフェースを実装できるように対応 (#8007 by @fisker)

"RFC: Allow interfaces to implement other interfaces" を参照

# Input
interface Resource implements Node {
id: ID!
url: String
}

# Prettier 2.0
interface Resource {
id: ID!
url: String
}

# Prettier 2.1
interface Resource implements Node {
id: ID!
url: String
}

Markdown

remark-parse を v8 に更新 (#8140 by @saramarcondes, @fisker, @thorn0)

Prettierが使用するMarkdownパーサーremarkが長らく待たれたアップデートを実施しました(5.0.0 → 8.0.2、remarkの変更履歴参照)。これにより、特にタブでインデントされたリスト項目のパースに関連する多くのバグが修正されました。

新しいバージョンでは、仕様で定義されていない構文拡張である脚注のパースがより厳密になりました。以前のPrettierは、任意の数のスペースでインデントされた複数行の脚注をパース(および--tab-widthオプションに応じて出力)していました。新しいバージョンでは、4スペースでインデントされた複数行の脚注のみを認識します。この変更は非標準構文のため破壊的変更とは見なされませんが、この機能を使用している場合、Prettierを更新する前に、古いバージョンのPrettierで--tab-width=4を使用してファイル内の脚注を新しいバージョンと互換性のある形式にしておくことをお勧めします。

CJK文章とVariation Selectorのフォーマットを正確化 (#8511 by @ne-sachirou)

<!-- Input -->
麻󠄁羽󠄀‼️

<!-- Prettier 2.0 -->
麻 󠄁 羽 󠄀 ‼️

<!-- Prettier 2.1 -->
麻󠄁羽󠄀‼️

YAML

prettier-ignore による不安定なフォーマットを修正 (#8355 by @fisker)

# Input
# prettier-ignore
---
prettier: true
...
hello: world

# Prettier 2.0
# prettier-ignore
---
prettier: true
---
hello: world

# Prettier 2.0 (Second format)
# prettier-ignore
---
prettier: true

---
hello: world

# Prettier 2.1
# prettier-ignore
---
prettier: true
---
hello: world

コメント内の空行を保持 (#8356 by @fisker)

# Input
a:
- a: a

# - b: b

# - c: c

- d: d


b:
- a: a

# - b: b

# - c: c

# Prettier 2.0
a:
- a: a

# - b: b

# - c: c

- d: d

b:
- a: a
# - b: b
# - c: c

# Prettier 2.1
a:
- a: a

# - b: b

# - c: c

- d: d

b:
- a: a

# - b: b

# - c: c

yamlyaml-unist-parser を更新 (#8386 by @fisker, fixes in yaml-unist-parser by @ikatyang)

# Input
# --- comments ---

# Prettier 2.0
--- # --- comments ---

# Prettier 2.1
# --- comments ---

# Input
empty block scalar: >

# comment

# Prettier 2.0
empty block scalar: >

# comment

# Prettier 2.1
SyntaxError: Block scalars with more-indented leading empty lines must use an explicit indentation indicator (1:21)
> 1 | empty block scalar: >
| ^
> 2 |
| ^^
> 3 | # comment
| ^^^^^^^^^^^

YAML インライン拡張構文のエラーを修正 (#8888 by @fisker, @evilebottnawi, fixes in yaml-unist-parser by @ikatyang)

# Input
foo:
<<: &anchor
K1: "One"
K2: "Two"

bar:
<<: *anchor
K3: "Three"

# Prettier 2.0
SyntaxError: Merge nodes can only have Alias nodes as values (2:2)
1 | foo:
> 2 | <<: &anchor
| ^^^^^^^^^^^
> 3 | K1: "One"
| ^^^^^^^^^^^^
> 4 | K2: "Two"
| ^^^^^^^^^^^^
> 5 |
| ^
6 | bar:
7 | <<: *anchor
8 | K3: "Three"

# Prettier 2.1
foo:
<<: &anchor
K1: "One"
K2: "Two"

bar:
<<: *anchor
K3: "Three"

API

プラグインのパーサーを parser オプションに追加 (#8390 by @thorn0)

プラグインが言語を定義する場合、その言語に対して指定されたパーサーが parser オプションの有効な値のリストに自動的に追加されるようになりました。これは、利用可能なパーサーのリストが必要なエディター統合やその他のアプリケーションに役立つ可能性があります。

npm install --save-dev --save-exact prettier @prettier/plugin-php
const hasPhpParser = prettier
.getSupportInfo()
.options.find((option) => option.name === "parser")
.choices.map((choice) => choice.value)
.includes("php"); // false in Prettier 2.0, true in Prettier 2.1

prettier.getFileInfo() を修正 (#8548, #8551, #8585 by @fisker)

  • {resolveConfig: true} を渡す場合、inferredParser は設定ファイルから解決されたパーサーであるべきですが、以前のバージョンでは組み込みパーサーでサポートされるファイルに対して誤った結果を返す可能性がありました。

  • {resolveConfig: true}{ignorePath: "a/file/in/different/dir"} を渡す場合、inferredParser の結果が正しくない可能性がありました。

  • 指定された filePath が無視される場合、inferredParser は常に null になりました。

$ echo {"parser":"flow"}>.prettierrc
$ node -p "require('prettier').getFileInfo.sync('./foo.js', {resolveConfig: true})"

# Prettier 2.0
# { ignored: false, inferredParser: 'babel' }

# Prettier 2.1
# { ignored: false, inferredParser: 'flow' }
$ echo ignored.js>>.prettierignore
$ node -p "require('prettier').getFileInfo.sync('./ignored.js')"

# Prettier 2.0
# { ignored: true, inferredParser: 'babel' }

# Prettier 2.1
# { ignored: true, inferredParser: null }

深いディレクトリ内のファイルに対する editorConfig の解決を修正 (#8591 by @fisker)

以前のバージョンでは、深いディレクトリ(プロジェクトルートから深さが9以上)にあるファイルの .editorconfig を見つけることができませんでした(#5705 参照)。

.cjs および .json5 設定ファイルのサポート (#8890, #8957 by @fisker)

新しい形式の設定ファイルが追加されました:

  • .prettierrc.json5

  • .prettierrc.cjs

  • prettier.config.cjs

BOM付きファイルでの範囲フォーマットの誤りを修正 (#8936 by @fisker)

以前のバージョンでは、ファイルにBOMがある場合、実際の範囲が誤って計算されていました。

const text = "\uFEFF" + "foo = 1.0000;bar = 1.0000;";
// ^^^^^^^^^^^^^ Range
const result = require("prettier")
.format(text, {
parser: "babel",
rangeStart: 1,
rangeEnd: 13,
})
// Visualize BOM
.replace("\uFEFF", "<<BOM>>")
// Visualize EOL
.replace("\n", "<<EOL>>");

console.log(result);

// Prettier 2.0
// -> <<BOM>>foo = 1.0;<<EOL>>bar = 1.0;
// ^^^^^^^^^ This part should not be formatted

// Prettier 2.1
// -> <<BOM>>foo = 1.0;bar = 1.0000;

CLI

CJKや絵文字を含むファイル名が正しく無視されない問題を修正 (#8098 by @fisker)

// Prettier 2.0
$ echo "dir" > .prettierignore
$ prettier **/*.js -l
dir/😁.js
dir/中文.js
not-ignored.js

// Prettier 2.1
$ echo "dir" > .prettierignore
$ prettier **/*.js -l
not-ignored.js

--file-info.prettierrc--no-config を尊重するようになりました (#8586, #8830 by @fisker)

$ echo {"parser":"ninja"}>.prettierrc

# Prettier 2.0
$ prettier --file-info file.js
# { "ignored": false, "inferredParser": "babel" }
$ prettier --file-info file.js --no-config
# { "ignored": false, "inferredParser": "babel" }

# Prettier 2.1
$ prettier --file-info file.js
# { "ignored": false, "inferredParser": "ninja" }
$ prettier --file-info file.js --no-config
# { "ignored": false, "inferredParser": "babel" }

--ignore-unknown(エイリアス -u)フラグを追加 (#8829 by @fisker)

# Prettier 2.0
npx prettier * --check
Checking formatting...
foo.unknown[error] No parser could be inferred for file: foo.unknown
All matched files use Prettier code style!

# Prettier 2.1
npx prettier * --check --ignore-unknown
Checking formatting...
All matched files use Prettier code style!

--write オプションのエイリアスとして -w を追加 (#8833 by @fisker)

# Prettier 2.0
$ prettier index.js -w
[warn] Ignored unknown option -w. Did you mean -_?
"use strict";

module.exports = require("./src/index");

# Prettier 2.1
$ prettier index.js -w
index.js 30ms

未知のオプションに対して -_ を提案しないようにしました (#8934 by @fisker)

# Prettier 2.0
$ prettier foo.js -a
[warn] Ignored unknown option -a. Did you mean -_?

# Prettier 2.1
$ prettier foo.js -a
[warn] Ignored unknown option -a. Did you mean -c?