`tailwindcss canonicalize` サブコマンドの追加
Tailwind CSS CLIに新しい canonicalize サブコマンドが追加され、クラス候補リストの正規化・統合・ソートをコマンドラインから実行できるようになりました。
背景
Tailwind CSS のクラスには、py-3 p-1 px-3 のように冗長・競合する指定が混在しやすいという課題があります。py-3 と p-1 と px-3 を同時に指定した場合、実際に適用されるのは p-3 のみですが、これを自動的に解決する CLI ツールが存在していませんでした。canonicalize サブコマンドはこの問題をコマンドラインレベルで解決するために導入されました。
技術的な変更
コマンドの入出力
canonicalize サブコマンドは、クラス候補のリストを正規化・統合・ソートして出力します。入力はコマンドライン引数とstdinの両方に対応しており、テストコードから動作を確認できます。
// 引数渡し: 'py-3 p-1 px-3' → 'p-3' に正規化
let result = await runCommandLine({
argv: ['--css', css, 'py-3 p-1 px-3'],
stdinIsTTY: true,
stdoutIsTTY: false,
})
// => { exitCode: 0, stdout: 'p-3', stderr: '' }
// stdin渡し: 複数行を一括処理
let result = await runCommandLine({
argv: ['--css', css],
stdin: '[display:_flex_] py-3 p-1 px-3\nmt-2 mr-2 mb-2 ml-2 focus:hover:p-3 hover:p-1 py-3\n',
stdinIsTTY: false,
stdoutIsTTY: false,
})
stdinが TTY でない場合は各行をクラスグループとして扱い、複数グループを一括処理できます。--css オプションを省略した場合は @import 'tailwindcss' をデフォルトのエントリポイントとしてフォールバックします。
コマンド実装の構成
packages/@tailwindcss-cli/src/commands/canonicalize/index.ts に実装された runCommandLine 関数が中核です。__unstable__loadDesignSystem を使って CSS エントリファイルからデザインシステムをロードし、segment や compare などのユーティリティを活用してクラスの解析・整列を行います。出力フォーマットは OutputFormat 型として 'text' / 'json' / 'jsonl' の3種類に対応しており、--format オプションで切り替えられます。
export type OutputFormat = 'text' | 'json' | 'jsonl'
export interface CandidateGroupResult {
input: string
output: string
changed: boolean
}
各グループの処理結果は CandidateGroupResult として構造化されており、changed フラグにより変換の有無を追跡できます。
エントリポイントへの統合
packages/@tailwindcss-cli/src/index.ts が大幅に改修され、サブコマンド対応のルーティング構造が導入されました。
変更前:
// サブコマンド非対応。引数があればエラーとしてヘルプを表示
if (command) {
help({
invalid: command,
usage: ['tailwindcss [options]'],
options: { ...build.options(), ...sharedOptions },
})
process.exit(1)
}
変更後:
import * as canonicalize from './commands/canonicalize'
function rootHelp({ invalid }: { invalid?: string } = {}) {
help({
invalid,
usage: [buildUsage('tailwindcss'), buildUsage('tailwindcss build'), canonicalize.usage()],
commands: {
build: 'Build your CSS',
canonicalize: 'Canonicalize candidate lists',
},
options: { ...build.options(), ...sharedOptions },
})
}
ルートの help 関数に commands プロパティが追加され、利用可能なサブコマンド一覧をヘルプメッセージに表示できるようになっています。
help 関数のリファクタリング
packages/@tailwindcss-cli/src/commands/help/index.ts に render オプションが追加されました。
export function help({
render = true,
invalid,
usage,
options,
}: {
render?: boolean
// ...
}) {
let width = process.stdout.columns ?? 80 // nullishフォールバックを追加
let lines: string[] = []
let writeLine = render ? println : (value = '') => void lines.push(value)
// ...
}
render = false のとき、println の代わりに lines 配列への push が行われます。これにより、ヘルプテキストを実際に出力せず文字列として取得することが可能になり、canonicalize コマンドなどからヘルプ内容をプログラム的に利用できるようになっています。また、process.stdout.columns が undefined を返す環境(非TTY)での width を 80 にフォールバックする修正も含まれています。
タイポ修正
normalizeWindowsSeperators という関数名のタイポ(Seperators → Separators)が packages/@tailwindcss-cli/src/utils/test-helpers.ts で修正され、参照箇所も一括更新されています。
設計判断
__unstable__loadDesignSystem を利用することで、CSS エントリファイルから実際のデザインシステムを動的に読み込む設計が採用されました。これにより、カスタムテーマやプラグインを含む任意の Tailwind 設定に対して正規化を実行できます。--css 省略時のフォールバックとして @import 'tailwindcss' を使う設計は、ゼロコンフィグでの利用を可能にしつつ、カスタム設定への対応も維持するトレードオフの結果です。
stdin からの複数行入力対応は、シェルパイプラインとの親和性を高めるための判断です。jsonl 形式の出力対応とあわせて、他ツールとの連携(エディタ拡張、リンター統合など)を想定した設計となっています。
help 関数への render オプション追加は、テスト容易性と再利用性の向上を目的とした小さな設計改善です。副作用(標準出力への書き込み)をオプションで無効化できる構造は、CLIツールの実装パターンとして堅実な判断といえます。
まとめ
tailwindcss canonicalize の追加は、クラス名の冗長性解消をツールチェーンに組み込む第一歩です。__unstable__ APIの利用やサブコマンド体系の整備など、今後の拡張を見据えた基盤整備の側面も持つ変更といえます。