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

Prettier 1.10: Prettier誕生1周年 🎂

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

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

Prettier誕生日おめでとう!Prettierがリリースされてわずか1年で、これほど大きな普及と多くの貢献者が集まったことは驚くべきことです。この特別なリリースでは、プロジェクトの小さな振り返りを行いたいと思います。

このリリース自体も非常にエキサイティングです。Prettierは現在.vueファイルの部分サポートを実装し、内部がリファクタリングされて適切なプラグインAPIが整備され、さまざまな言語をサポートできるようになりました!

振り返り

2013年にgofmtが登場して以来、私は(@vjeux)自動フォーマットのアイデアに夢中になりました。コーディングスタイルに関する議論、手動でのコード整形、codemodツール作成の困難さなど、自動フォーマッタで解決できる問題が常に見え始めました…

昨年12月、JavaScript用プリティプリンタに2人の開発者が独立して取り組んでいたのは運命の兆しでした!Pieter VanderwerffはFlowインフラに基づいてReasonで、James LongはJavaScriptでそれぞれ構築しました。私は両プロジェクトに同じテストスイートを設定し、既存のコードベースでプリティプリンタを実行して、うまく印刷されなかったものリストを抽出することで応援役を務めました。

残念ながら休暇が終わると、二人とも本業に戻らなければなりませんでした :( 私は介入し、マネージャーを説得してこのプロジェクトにフルタイムで取り組むことにしました。Jamesはプロジェクト(Prettier)をオープンソース化しており、私はJavaScriptに詳しかったため、これを担当することに決めたのです!

このプロジェクトでうまくいった点をいくつか紹介します。

リリースノートに時間をかける

リリースノートには興味深い特性があります。内容がどんなに平凡でも頻繁に共有されるのです。誰もがソフトウェアのバージョン1.5.8がリリースされたことを知りたがります。これはプロジェクトをアピールする絶好の機会です。

Prettierのリリースでは、変更の背景にある理論的根拠を詳細に説明し、別途ブログ記事にすべき内容(これと同じです!)についても言及しました。加えて、ブログ記事を書かない言い訳を探して怠けがちな状況でも、新しいバージョンの公開は強制力として機能するのです。

明確な意思決定プロセス

スタイルルールは最も議論を呼ぶテーマでありながら、多くの決定が必要な領域です。進捗を可能にする意思決定プロセスの設計を試みました。

人々は自分のスタイル観が最善だと説得するために様々な感情的な議論を持ち出します。純粋に合理的な方法論が必要でした。たとえ好みでなくても、方法論自体には反論できないようにするためです。

私が考え出した最善策は、Facebookのコードベースで各バリアントが使用された回数をカウントすることでした。相対数値(スタイルAはスタイルBの5倍使用されている)を示すのは簡単で、説得力があります。何年も数千人によって書かれた巨大なコードベースで優勢なスタイルは、最善でなくとも大きな論争を呼ぶ可能性は低いでしょう。

すべてがこの方法で解決できるわけではありません。明確な優劣がつかない場合や、適切に印刷するアルゴリズムが自明でない場合もありました。そのような場合、最終的に単独の意思決定者(私)によるエスカレーションプロセスが重要でした。これにより、困難なコンセンサス形成なしで進捗を維持できたのです。

オープンソースを実験台として

完全なプリティプリンタは、Facebookのような大規模なコードベースに導入するにはほぼ完璧である必要があるプロジェクトの一つです。第一印象は非常に重要であり、すべてのエッジケースで正しい(無効なJavaScriptを導入したり、動作が異なるコードを生成したりしない)ものを得るのは非常に困難です。

私の当初の計画は、外部から隔離された環境で6ヶ月間一人で作業し、すべてが完璧になるまで取り組み、その後人々に採用してもらうことでした。しかし、オープンソースコミュニティの人々は同じ品質基準を持っておらず、予想よりはるかに早く使い始めたことは予期していませんでした。サイドプロジェクトで使用するリスクは、Facebookの数百万行のコードで使用する場合とは大きく異なります。

結果的に、最終的にFacebookで使用できるようになるまでのフィードバックを得ることは、プロジェクトにとって非常に有益でした。

貢献者としてのオープンソース

プロジェクトの最初の6ヶ月間、私はフルタイムで作業していましたが、コミットの半分しか書いていません。それ自体が驚くべきことです!プロジェクトのスループットが2倍になっただけでなく、地球上のすべてのエディタとの統合、バグを見つけるためのファザー、TypeScriptサポート、同じファイル内で複数言語を解析するインフラなど、私が時間を割かなかった領域に人々が取り組んでくれました。

Facebookではそれらすべてを使用しているわけではありませんが、多くのものが役立ちました。CSS-in-JSのサポートにより、テンプレートリテラル内のGraphQLフラグメントをフォーマットすることが容易になりました。多くのユーザーは、いずれ遭遇するであろう難解なバグを表面化させる優れた方法でもあり、多くの人々がそれらを修正するために協力しました。

最高なのは、6ヶ月前にフルタイムでの作業をやめた後も、プロジェクトが@azzのリーダーシップの下で継続されたことです。様々な形で助けてくれたすべての人々に感謝したいと思います。皆と共に歴史を作るのはとてもエキサイティングです!

オープンソースはプロジェクトに驚異的な成果をもたらし、Facebook(ほぼすべてのJavaScriptファイルがプリティプリントされるようになりました)と業界全体に大きな価値を提供しました。これは広範な採用からも明らかです。

ツーリング: Jestスナップショットテスト&プレイグラウンド

これらの貢献が可能だったのは、エラーの報告、コードの貢献、レビューが容易だったからです。このプロジェクトで最も影響力のあった2つのツールは、jestスナップショットテストとプレイグラウンドでした。

スナップショットテストはプリティプリンタにとって素晴らしいツールです。新しいテストの追加は非常に簡単で、フォーマットしたいコードを含むファイルをテストフォルダに作成し、jestを実行するだけです。何かを変更するたびに、多数の例がどのように異なるフォーマットになるかを確認でき、それが改善かどうかを判断できます。レビュアーにとっても、変更前後のすべての差分を確認できるので非常に便利です。私は実際の実装よりもスナップショットにより注意を払うようになりました。

プレイグラウンドは、開発環境をインストールしたり正しいブランチにいる必要なく、再現性のあるバグ報告を作成したりPrettierを試したりするのに最適な方法です。これは人々が実際に対処可能な高品質なバグレポートを提供する上で非常に価値があることが証明されました。

主な変更点

Vue単一ファイルコンポーネントのサポート (#3563) by @vjeux

Vue SFC (#2097)の需要は非常に高くなっています。今回その部分的なサポートを導入しました:すべてのHTMLはそのまま出力されますが、<script>タグと<style>タグの内容がPrettierによってフォーマットされるようになりました。

使用するには、*.vueファイルに対してprettierを実行するだけです!

PrettierプラグインAPI (#3536) by @azz

JavaScript版のPrettierが安定したことで、最近では新たな言語をPrettierに追加したいというコントリビューターが現れました。特にPythonやPHPのサポートを追加するプルリクエストがありました。私たちはprettierコアパッケージの可搬性と保守性を維持したい一方で、より多くの言語でPrettierを実行できる機会を提供したいと考えています。そのために[プラグインAPI]を導入しました!Prettierプラグインは、パーサーやプリンターをPrettierフォーマッターに提供できます。これらはファーストクラスとして扱われ、埋め込みサポート(例:Markdown内の言語のフォーマット)にも貢献できます。

プラグインの使用は非常に簡単で、npmまたはyarnでインストールし、いつも通りPrettierを実行するだけです。追加の設定は必要ありません!

現在開発中の公式プラグインは3つあります:

これら3つのプラグインはまだ活発に開発中であり、プロダクションコードを扱う準備はできていませんが、進捗に注目してください!

これらのプラグインの開発を手伝いたい方は、各リポジトリのissueリストを確認するか、自分のコードで実行してバグを報告してください!同様に、Prettierで新しい言語のプラグインを構築したいが立ち上げに助けが必要な場合は、prettierリポジトリにissueを作成して、私たちに助けを求めてください。

Prettierの組み込み言語も、プラグインAPIで表現されるようにリファクタリングされました。これにより、コアAPIの汎用性が今後も保証されます。

詳細はドキュメントをご覧ください。

これは新しく大規模な機能であるため、ドキュメントではベータラベルを付けてリリースしていることに注意してください。重大な問題は予想していませんが、次のリリースで破壊的変更を行う可能性があることを意味します。

その他の変更

TypeScript

数値セパレーターのサポート (#3580) by @azz

数値セパレーターはステージ3のECMAScript提案です。TypeScript 2.7でサポートが追加され、Prettierも数値セパレーターを保持するようになりました。

// Before
SyntaxError: ',' expected. (1:10)
> 1 | var a = 1_000_000_000;
| ^
2 | var b = 0b1101_0101_1001;
3 | var c = 0xAE_FE_2F;

// After
var a = 1_000_000_000;
var b = 0b1101_0101_1001;
var c = 0xAE_FE_2F;

Flow

Flowの型アノテーションコメントをコメントとして出力 (#3449) by @duailibe

Flowの型アノテーションコメントは、ファイルをトランスパイルせずに型チェックを行う便利な方法です。このリリース以前は、Prettierはflowパーサーを使用する際、型アノテーションをコメントとして出力しなかったため、この機能を使えませんでした。今回のリリースで、Prettierは型アノテーションがコメントかどうかを正しく検出し、/*: ... */ 形式のコメントを適切に出力するようになりました。/*:: ... */ 形式のコメントについては作業中です。

// Input
let foo: string = "a";

// Before
let foo: string = "a";

// After
let foo: string = "a";

アロー関数のパラメーター後のコメントを出力 (#3444) by @duailibe

babylonパーサーを使用している場合、Flowコメントにはコメントが移動するといったさまざまな問題がありました。このリリースではそのうちの1つが修正され、この機能のサポートに近づきました。

// Before
const run = (cmd /*: string */ /*: Promise<void> */) => {};

// After
const run = (cmd /*: string */) /*: Promise<void> */ => {};

arrowParensが"always"の場合に関数型アノテーションで括弧を出力 (#3616) by @duailibe

前回のリリースarrowParensオプションを追加しましたが、Flowの関数型アノテーションでは見落とされていました。今回のリリースで、arrowParensalwaysに設定されている場合、単一の引数の周りに括弧を付けるようになりました。

// --arrow-parens always

// Before
type SomeType = {
something: number => number
};

// After
type SomeType = {
something: (number) => number
};

JSX

JSX内のインラインdo式 (#3607) by @vjeux

"Do expressions"はstage 1のECMAScript提案であり、JSX内で特に有用ですが、余分なインデントレベルは不要なため、式コンテナ内にインライン化しました。

// Before
{
do {
// ...
}
}

// After
{do {
// ...
}}

コメント付きアロー属性の後にソフトラインを追加しないように修正 (#3641) by @duailibe

JSX属性で余分な改行が発生するマイナーな問題を修正しました。

// --print-width 13 (for demonstration)

// Before
<span
attr={
// comment
() =>
true

}
/>;

// After
<span
attr={
// comment
() =>
true
}
/>;

属性内のJSX要素を()でラップしないように修正 (#3640) by @duailibe

JSX仕様には要素を別の要素の属性として渡す隠れた機能がありますが、Prettierが括弧を追加することで構文エラーが発生していました。このリリースで修正されました。一部パーサーはこの機能を解析しますが、jsxトランスフォームはいずれも対応していません。最初に対応するのは現在ベータ版のBabel 7となる予定です。

// Before
<Foo
content=(
<div>
<div />
</div>
)
/>

// After
<Foo
content=<div>
<div />
</div>
/>

SCSS

セレクタ内のコメントをそのまま出力 (#3649) by @vjeux

残念ながらセレクタ用のCSSパーサーはコメントをサポートしていません。そのためコメントが含まれる行にセレクタが移動されるケースがありましたが、これが修正されました。

/* Before */

// Foo
.foo,
// Bar .bar {
display: block;
}

/* After */

// Foo
.foo,
// Bar
.bar {
display: block;
}

GraphQL

GraphQLパーサーを更新 (#3605) by @vjeux

GraphQL仕様が進化し、Prettierでは新たに3つの機能をサポートします:

型に文字列の説明を注釈する機能

"""
Type description
"""
type Foo {
"some description"
someProperty: String!

"""
some really
long description
"""
someOtherProperty: [String!]!
}

コンテンツがない場合の{}の省略

extend enum Site @onEnum

全タイプの拡張機能

extend input InputType {
other: Float = 1.23e4
}

Markdown

マルチパーサー内の改行をハードラインに置換 (#3611) by @ikatyang

Markdownブロッククォート内にJavaScriptを埋め込む際、ブロッククォートの>文字が削除される問題を修正しました。

<!-- before -->

> ````md
> <!-- prettier-ignore -->
> ```js
ugly ( code ) ;
```
> ````

<!-- after -->

> ````md
> <!-- prettier-ignore -->
> ```js
> ugly ( code ) ;
> ```
> ````

Markdownリンクタイトルの引用符をsingleQuoteオプションに準拠 (#3481) by @j-f1

以前は全リンクタイトルが"で引用されていましたが、singleQuoteオプションを尊重するようになりました。タイトルに'"の両方が含まれる場合は()スタイルの引用符を使用します。

<!-- --single-quote -->

<!-- Before -->

[ref]: https://prettier.io "Prettier"
[other-ref]: https://example.com "Shakespeare's \"Romeo and Juliet\" is a famous play"

<!-- after -->

[ref]: https://prettier.io 'Prettier'
[other-ref]: https://example.com (Shakespeare's "Romeo and Juliet" is a famous play)

MarkdownでaltテキストのないimageReferenceを出力 (#3643) by @duailibe

altテキストのない画像参照でPrettierがクラッシュするエッジケースを修正しました。

<!-- before -->
TypeError: doc is null

<!-- after -->
![][logo]

[logo]: https://github.com/prettier/prettier-logo/blob/master/images/prettier-logo-light.png?raw=true

リストインデントでtabWidthを尊重 (#3694) by @ikatyang

従来はリストインデントに2スペースを強制していましたが、tadWidthを考慮するようになりました。

<!-- --tab-width 4 -->

<!-- before -->
* one
* two

<!-- after -->
* one
* two

API

getSupportInfo()options フィールドを追加 (#3433) by @ikatyang

prettier.getSupportInfo().optionsでPrettierがサポートするオプションの配列を取得できるようになりました。

VCSディレクトリまでの.editorconfigのみを検索 (#3559) by @josephfrazier

同じリポジトリで2人のユーザー間でコード整形結果が異なる問題の診断が複雑になる場合がありました。Prettierが.editorconfigファイルをサポートし、~/.editorconfigまで検索していたため、意図せずコード整形方法が変わる副作用がありました。今後はプロジェクトルートディレクトリまでの設定のみを参照します。

CLI

全CLIロギングをロガー経由に統一 (#3515) by @azz

--loglevelオプションが一部ケースで反映されていませんでしたが、全CLIロギングで尊重されるようになりました。

# Before
$ prettier --loglevel silent --write test.js
test.js 91ms

# After
$ prettier --loglevel silent --write test.js

無視されたファイルはそのまま出力する (#3618) by @duailibe

無視ファイルに対するCLIの動作を修正しました。以前は.prettierignoreで無視されたファイルの場合、CLIは何も出力しませんでした。これはエディタ統合に影響していました。新しい動作は以下の通りです:

  • --writeオプション使用時:無視されたファイルの読み取り/書き込みを行わない

  • --writeオプションなし時:無視されたファイルを読み取り、そのまま出力する

エディタ統合

PostCSS拡張をgetSupportInfo()に追加 (#3454) by @ardevelop

一部のエディタ統合では、PrettierのgetSupportInfo関数を使用して全ての言語サポートを動的に取得しています。これにより*.pcssファイルのサポートが追加されました。

「コメント付きJSON」をgetSupportInfo()に追加 (#3496) by @thorn0

同様に「コメント付きJSON」も検出対象となります。


🎂