styled-componentsのTemplate LiteralsのみをFormat化する`styled-formatter`について

2024-12-24

今回は、私が開発したstyled-formatterというツールについて、その開発背景と実装概要をご紹介します。

このツールは、コードフォーマッタ「Biome」を利用した際に発生したstyled-componentsのTemplate Literals(テンプレートリテラル)のフォーマットがされない問題を解決するために作成しました。

https://github.com/biomejs/biome/issues/4182

Biomeについて

Biomeは、JavaScriptおよびTypeScriptのコードフォーマッタとして非常に優れたツールで、パフォーマンスに優れており、大規模なコードベースでも迅速にフォーマットを実行できます。 これにより、開発者は待ち時間を最小限に抑えつつ、コードの整形を行うことができます。

styled-componentsのTemplate Literalsと併用時の課題

Biomeの優れた点にもかかわらず、styled-componentsを使用する際にTemplate Literals部分のフォーマットに課題が生じました。 styled-componentsは、Biomeでは以下のような問題が発生しました。

import styled from "styled-components";

const Button = styled.button`
color: red;
background: blue;
`;

上記のコードでは、プロパティのインデントが揃っておらず、見た目が整っていません。 このような不整合は、コードの可読性やチーム全体でのコードスタイルの一貫性に悪影響を及ぼします。Biomeは主にJavaScriptやTypeScriptの構文にフォーカスしているため、CSSの整形に関しては期待通りの結果が得られないことが判明しました。 その結果ファイルによってはインデントをtabで行っていたり、スペースで行っていたりと自由な状態になってしまっていました。

Prettierを利用することでTemplate Literals部分をフォーマット化することも可能ですが、その場合に既存のJavaScript/TypeScript行も変更されてしまい、Biomeと競合してしまいます。 そのため下記の黄色の下線の箇所のみFormatしてくれるFomatterが必要になりました。

styled-fomatter-targets

styled-formatterの作成

この課題を解決するために、styled-componentsのTemplate Literals部分のみを対象にフォーマットを行うツール「styled-formatter」を開発しました。このツールは、Biomeでは対応が難しかった部分を補完し、styled-componentsを使用したコードベースの可読性と一貫性を向上させることを目的としています。

実装のポイント

styled-formatterの実装において、以下のポイントに注力しました。

  1. コード解析と抽出
    @babel/parser@babel/traverseを使用して、コード内のstyled-componentsのTagged Template Literalsを正確に検出・抽出します。これにより、フォーマット対象を限定し、他の部分に影響を与えずに処理を行うことが可能になります。

  2. プレースホルダーの活用
    テンプレートリテラル内の動的な式(${...})やコメントを一時的にプレースホルダーに置き換えることで、PrettierによるCSSのフォーマットが他の部分に干渉しないようにします。このアプローチにより、純粋なCSS部分のみを効率的に整形できます。

  3. Prettierによるフォーマット
    prettierを使用して、プレースホルダー化されたCSS部分を整形します。インデントの種類(スペースやタブ)や幅をオプションとして柔軟に設定できるようにし、プロジェクトのコーディングスタイルに合わせたフォーマットが可能です。

  4. プレースホルダーの復元
    フォーマット後のコードに対して、元の式やコメントをプレースホルダーから復元します。これにより、動的な部分はそのまま残しつつ、CSS部分のみが整形された状態を実現します。

  5. エラーハンドリング
    フォーマット中にエラーが発生した場合でも、元のコードをそのまま返すようにし、開発者の作業が中断されないように配慮しています。また、エラーメッセージをコンソールに出力することで、問題の特定と修正を容易にしています。

使用方法

styled-formatterをプロジェクトに導入する手順は以下の通りです:

  1. インストール

    npm install --save-dev styled-formatter
    
  2. 使用例

    styled-formatter "src/**/*.tsx" --fix
    

    このコードを実行すると、styled-componentsのテンプレートリテラル部分が以下のように整形されます。

    import styled from "styled-components";
    
    const Button = styled.button`
      color: red;
      background: blue;
    `;
    

    Optionは自動で修正をかける --fix の他にIndentの種類やSpaceの個数を変更する--indent <type or number>が設定可能です。

まとめ

styled-formatterは、Biomeの優れたコードフォーマット機能を活用しつつ、styled-componentsのTemplate Literals部分に特化したフォーマットを実現するツールです。これにより、styled-componentsを使用するプロジェクトでも、一貫性のある美しいコードスタイルを維持することが可能になります。

将来的にはBiome側で対応する方法がされ次第使わなくなる想定ではおり、実際のプロジェクトの運用では定期的にフォーマット外のものがないことをチェックしています。

またstyled-componentsのTemplate Literalsの書き方も簡単で便利な部分も多いが、Style ObjectsのようなTypeScriptが認識しやすい形で実装を進めるのも余計にありな感じもしました。

import styled from "styled-components";

const Button = styled.button({
  color: 'red',
  background: 'blue',
});

このツールが使わなくても良い未来が来たらよいなと思っています。

GitHubリポジトリ: https://github.com/yudppp/styled-formatter
npmパッケージ: https://www.npmjs.com/package/styled-formatter