JS プラグインの theme() が DEFAULT 値を返すように修正
Tailwind CSS の JavaScript プラグイン内で theme() を呼び出した際、接頭辞が重なる CSS カスタムプロパティ(例: --color-foo と --color-foo-bar)が存在すると、内部的な曖昧解消オブジェクトが返ってしまい、生成される CSS が破壊的になる問題を解消しました。今回の PR では、同様のケースで DEFAULT キーを自動的に展開し、期待通りの文字列を返すように変更しています。
背景
theme() 関数はプラグイン開発者がテーマ値を取得するための中心的な API ですが、CSS カスタムプロパティ名だけでは「foo」が単独キーか「foo-bar」のサブキーかを判別できません。この判別失敗により、theme('colors.foo') が { DEFAULT: 'red', bar: 'blue', __CSS_VALUES__: {...} } のような合成オブジェクトを返し、プラグインが期待する文字列ではなくオブジェクトが渡されました。その結果、addUtilities で生成された CSS に -d-e-f-a-u-l-t という不要なプロパティ名が混入し、__CSS_VALUES__ が漏出するという具体的な破壊が発生していました。
この曖昧さは、既に CSS 内部で使用される theme() 関数(#19097)では DEFAULT キーの展開で修正されていましたが、JS プラグインが直接呼び出す createThemeFn の実装には同様のロジックが欠如していたため、プラグイン側で同様の不具合が残っていました。
技術的な変更
packages/tailwindcss/src/compat/plugin-functions.ts の createThemeFn 内に、取得した CSS 値がオブジェクトでかつ DEFAULT プロパティを持つ場合にその DEFAULT 値を返す条件分岐を追加しました。
@@ -100,6 +100,23 @@ export function createThemeFn(
// If `--color-foo` and `--color-foo-bar` are both defined, `colors.foo`
// produces a synthetic object:
//
// ```ts
// { DEFAULT: 'red', bar: 'blue', __CSS_VALUES__: { DEFAULT: 0, bar: 0 } }
// ```
+ // Prefer `DEFAULT` instead of exposing the object to plugin code.
+ if (
+ cssValue !== null &&
+ typeof cssValue === 'object' &&
+ !Array.isArray(cssValue) &&
+ 'DEFAULT' in cssValue
+ ) {
+ return cssValue.DEFAULT
+ }
このロジックは CSS から取得した値 が null でなく、オブジェクトであり配列でなく、DEFAULT キーが存在する場合にのみ適用されます。既存の cssValue ?? configValue の戻り値ロジックはそのまま残すことで、従来の挙動や設定ファイルからの値優先順位に影響を与えません。
同時に packages/tailwindcss/src/compat/plugin-api.test.ts に回帰テストが追加され、theme('colors.foo') が正しく red を返すことを自動的に検証します。テストは run ヘルパーでプラグイン実行をシミュレートし、インラインスナップショットで期待出力を確認しています。
設計判断
今回の修正は 既存 API の拡張 という方針で行われました。theme() 関数自体のシグネチャや呼び出し方法は変更せず、内部で返却する値だけを調整することで、プラグイン側のコードに対する破壊的変更を回避しています。DEFAULT キーの検出はシンプルな型チェックとプロパティ存在確認で実装され、余計な依存関係やパフォーマンスコストを導入しない設計です。
また、後方互換性 を重視し、theme('colors.foo') がオブジェクトを期待している既存プラグインがあった場合でも、DEFAULT キーが存在しない限り元のオブジェクトが返ります。これにより、今回の変更は安全にデプロイでき、既存エコシステムへの影響を最小限に抑えています。
まとめ
theme() が CSS カスタムプロパティの接頭辞衝突で返す内部オブジェクトを DEFAULT 値に自動変換 することで、JS プラグイン内でのテーマ取得が正しく行えるようになり、破損した CSS の生成を防止しました。この実装は既存 API と互換性を保ちつつ、先行の CSS 対応修正と同様の挙動をプラグイン側にも提供する設計判断のもと実装されています。