# 機能設計書 42-後方互換フック（applyCompatibilityHooks）

## 概要

本ドキュメントは、Tailwind CSS v3のプラグイン・設定ファイルとの後方互換性を提供する `applyCompatibilityHooks` 関数の設計を記述する。`@plugin` および `@config` ディレクティブによるJavaScriptプラグイン・設定の読み込みを処理し、v3エコシステムとの互換性を確保する。

### 本機能の処理概要

applyCompatibilityHooksは、Tailwind CSS v4のコンパイルパイプラインにおいて、v3互換のJSプラグインおよび設定ファイルを統合するための中核的な後方互換レイヤーである。

**業務上の目的・背景**：Tailwind CSS v4はCSSファーストの設計に移行したが、v3で構築された膨大なプラグインエコシステムとの互換性を維持する必要がある。本機能は `@plugin` および `@config` ディレクティブを通じてJSプラグインとv3形式の設定ファイルを読み込み、v4のDesignSystemに統合する橋渡し役を担う。

**機能の利用シーン**：CSSファイル内で `@plugin "プラグインパス"` や `@config "設定ファイルパス"` ディレクティブが使用された場合、コンパイルパイプラインの `parseCss` フェーズで自動的に呼び出される。また、`theme()` 関数でドット記法のパスが使用された場合にも、後方互換のテーマ解決機能がアクティブ化される。

**主要な処理内容**：
1. ASTを走査して `@plugin` と `@config` ディレクティブを収集・削除する
2. レガシーユーティリティ（bg-gradient-to-*, flex-grow, flex-shrink等）を登録する
3. `resolveThemeValue` をドット記法対応版にオーバーライドする
4. JSモジュール（プラグイン・設定ファイル）を非同期でロードする
5. 設定ファイルの解決・マージ（resolveConfig）を実行する
6. プラグインAPIを構築し、各プラグインのhandler関数を実行する
7. テーマ設定の適用、スクリーン設定、コンテナ互換、ダークモード設定を処理する

**関連システム・外部連携**：`loadModule` 関数を通じてNode.jsのモジュールシステムと連携し、外部JSファイルをロードする。

**権限による制御**：特になし。ディレクティブの有無により自動的に有効化される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | レイアウト | 主機能 | globals.cssのv3形式の@import 'tailwindcss/base'等を処理する |

## 機能種別

データ連携 / 後方互換処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| designSystem | DesignSystem | Yes | 統合対象のデザインシステム | 有効なDesignSystemインスタンス |
| base | string | Yes | モジュール解決のベースパス | 空文字列可 |
| ast | AstNode[] | Yes | 処理対象のAST配列 | 有効なASTノード配列 |
| loadModule | Function | Yes | JSモジュールのローダー関数 | path, base, resourceHintを受け取りPromiseを返す |
| sources | Array | Yes | ソースファイルパスの配列 | base, pattern, negatedを持つオブジェクトの配列 |

### 入力データソース

- CSSファイル内の `@plugin` ディレクティブ（プラグインパスとオプション）
- CSSファイル内の `@config` ディレクティブ（設定ファイルパス）
- Node.jsモジュールシステムからロードされるJSプラグイン・設定ファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| features | Features | 使用された機能のビットフラグ（Features.JsPluginCompat等） |

### 出力先

- DesignSystemオブジェクトに対するサイドエフェクト（ユーティリティ・バリアント・テーマの登録）
- ASTへの直接変更（@pluginと@configの削除、プラグインが追加するノード）
- sourcesへの直接変更（contentファイルの追加）

## 処理フロー

### 処理シーケンス

```
1. AST走査・ディレクティブ収集
   ├─ @pluginディレクティブの検出・オプション解析・ASTから削除
   └─ @configディレクティブの検出・ASTから削除

2. レガシーユーティリティ登録
   └─ registerLegacyUtilities(designSystem)

3. resolveThemeValueオーバーライド
   └─ ドット記法パスの場合はフル互換モードにアップグレード

4. プラグイン/設定が無い場合は早期リターン (Features.None)

5. JSモジュールの非同期ロード
   ├─ configPathsからloadModuleで設定ファイルをロード
   └─ pluginPathsからloadModuleでプラグインをロード

6. upgradeToFullPluginSupport実行
   ├─ resolveConfig: 設定ファイルのマージ・解決
   ├─ buildPluginApi: プラグインAPIの構築
   ├─ resolveThemeValue: フル互換版への更新
   ├─ plugin.handler(api): 各プラグインの実行
   ├─ applyConfigToTheme: テーマ設定の適用
   ├─ applyKeyframesToTheme: キーフレームの適用
   ├─ registerThemeVariantOverrides: テーマバリアントの上書き
   ├─ registerScreensConfig: スクリーン設定の登録
   ├─ registerContainerCompat: コンテナ互換の登録
   ├─ prefix設定の適用
   ├─ important設定の適用
   └─ blocklist/contentの適用
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[AST走査: @plugin/@config収集]
    B --> C[registerLegacyUtilities]
    C --> D[resolveThemeValue オーバーライド]
    D --> E{@plugin/@configが存在?}
    E -->|No| F[Features.None を返却]
    E -->|Yes| G[JSモジュール非同期ロード]
    G --> H[upgradeToFullPluginSupport]
    H --> I[resolveConfig: 設定マージ]
    I --> J[buildPluginApi: API構築]
    J --> K[各プラグインhandler実行]
    K --> L[applyConfigToTheme]
    L --> M[テーマバリアント/スクリーン/コンテナ登録]
    M --> N[prefix/important/blocklist適用]
    N --> O[features を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-42-01 | @pluginネスト禁止 | @pluginディレクティブはトップレベルでのみ使用可能 | @plugin検出時にctx.parent !== nullの場合エラー |
| BR-42-02 | @pluginパス必須 | @pluginにはパスが指定されている必要がある | パスが空の場合エラー |
| BR-42-03 | @configネスト禁止 | @configディレクティブはトップレベルでのみ使用可能 | @config検出時にctx.parent !== nullの場合エラー |
| BR-42-04 | @configボディ禁止 | @configディレクティブにはボディを持てない | node.nodes.length > 0の場合エラー |
| BR-42-05 | プラグインオプション | @pluginオプションはフラットな宣言リストのみ対応 | オブジェクト値は非対応、エラーを投げる |
| BR-42-06 | オプション値の型変換 | プラグインオプションのCSS値をnull/true/false/number/stringに自動変換 | @pluginのbody内の宣言に対して |
| BR-42-07 | prefix検証 | プレフィックスは小文字ASCII文字(a-z)のみ | IS_VALID_PREFIX正規表現による検証 |
| BR-42-08 | CSS優先 | CSSで設定されたprefixやimportantはJS設定で上書きしない | 既にdesignSystem側に設定がある場合 |
| BR-42-09 | referenceモード | @reference内のプラグインはreferenceMode=trueで実行される | ctx.context.referenceがtrueの場合 |

### 計算ロジック

設定マージの優先順位：
1. compat config（デフォルトテーマ値）
2. ユーザープラグイン設定
3. ユーザーconfig設定
4. ダークモードプラグイン（最後に挿入）

## データベース操作仕様

該当なし（メモリ上のオブジェクト操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | @pluginがネストされている | エラーメッセージを投げる |
| - | Error | @pluginのパスが空 | エラーメッセージを投げる |
| - | Error | @configがネストされている | エラーメッセージを投げる |
| - | Error | @configにボディがある | エラーメッセージを投げる |
| - | Error | プラグインオプションにオブジェクト値 | エラーメッセージを投げる |
| - | Error | withOptionsでないプラグインにオプション指定 | エラーメッセージを投げる |
| - | Error | 無効なprefix | エラーメッセージを投げる |

### リトライ仕様

リトライ不要。モジュールロード失敗時はPromiseがrejectされ、上位の呼び出し元に伝播する。

## トランザクション仕様

該当なし

## パフォーマンス要件

- JSモジュールのロードは並列実行される（Promise.all）
- プラグインが存在しない場合は早期リターンでオーバーヘッドを最小化
- ドット記法のtheme解決は遅延アップグレードパターンで必要時のみフル互換モードに切り替え

## セキュリティ考慮事項

- `loadModule` 関数を通じて外部JSファイルを動的にロードする。信頼されたモジュールのみを読み込むべきである
- プラグインオプションの値はCSS宣言からパースされるため、型変換が行われる

## 備考

- `upgradeToFullPluginSupport` は再入可能な関数であり、初回呼び出し時にresolveThemeValueが完全互換版に置き換えられる
- compat configは `createCompatConfig` でv3のデフォルトテーマ値をv4のテーマ名前空間にマッピングする
- ダークモードプラグインは常にresolvedConfigの最後に追加される

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.ts | `packages/tailwindcss/src/compat/config/types.ts` | UserConfig/ResolvedConfigの型定義。darkMode/prefix/blocklist/important/plugins/contentの各フィールド |
| 1-2 | plugin-api.ts | `packages/tailwindcss/src/compat/plugin-api.ts` | Plugin/PluginWithConfig/PluginWithOptions/PluginAPI型の定義（22-89行目）。CssPluginOptions型（617行目） |

**読解のコツ**: TypeScriptのinterface mergingが多用されている。types.tsではUserConfigとResolvedConfigが複数回宣言されており、最終的にマージされる。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | apply-compat-hooks.ts | `packages/tailwindcss/src/compat/apply-compat-hooks.ts` | applyCompatibilityHooks関数（21-215行目）。メインのエントリーポイント |

**主要処理フロー**:
1. **42-52行目**: pluginPathsとconfigPathsの初期化
2. **54-145行目**: ASTウォークで@plugin/@configを収集
3. **147行目**: registerLegacyUtilities呼び出し
4. **155-171行目**: resolveThemeValueの遅延オーバーライド
5. **175行目**: プラグイン/設定が無い場合の早期リターン
6. **177-203行目**: JSモジュールの並列ロード（Promise.all）
7. **205-213行目**: upgradeToFullPluginSupport呼び出し

#### Step 3: @pluginオプション解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | apply-compat-hooks.ts | `packages/tailwindcss/src/compat/apply-compat-hooks.ts` | @pluginのbody解析（69-120行目）。CSS宣言値のプリミティブ型パース |

**主要処理フロー**:
- **84-107行目**: 宣言値をnull/true/false/number/string/配列に変換
- **109行目**: 値が1つの場合はスカラー、複数の場合は配列としてオプションに格納

#### Step 4: upgradeToFullPluginSupportを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | apply-compat-hooks.ts | `packages/tailwindcss/src/compat/apply-compat-hooks.ts` | upgradeToFullPluginSupport関数（217-423行目） |

**主要処理フロー**:
- **246-266行目**: プラグイン設定の正規化（withOptions対応）
- **270-278行目**: resolveConfigの2回呼び出し（全体設定 + ユーザー設定）
- **291-295行目**: buildPluginApiでプラグインAPIを構築
- **305-337行目**: resolveThemeValueのフル互換版への置き換え
- **339-350行目**: 各プラグインのhandler実行
- **355-360行目**: テーマ/スクリーン/コンテナの後処理
- **363-378行目**: prefix設定の適用と検証
- **382-384行目**: important設定の適用

### プログラム呼び出し階層図

```
applyCompatibilityHooks()
    │
    ├─ walk(ast) [AST走査: @plugin/@config収集]
    │
    ├─ registerLegacyUtilities(designSystem)
    │
    ├─ resolveThemeValue オーバーライド (遅延)
    │      └─ upgradeToFullPluginSupport() [必要時]
    │
    ├─ loadModule() [JSモジュールロード x N]
    │
    └─ upgradeToFullPluginSupport()
           ├─ resolveConfig(designSystem, files)
           │      ├─ extractConfigs() [再帰的設定抽出]
           │      └─ mergeTheme() [テーママージ]
           │
           ├─ buildPluginApi()
           │
           ├─ plugin.handler(api) [各プラグイン実行]
           │
           ├─ applyConfigToTheme()
           ├─ applyKeyframesToTheme()
           ├─ registerThemeVariantOverrides()
           ├─ registerScreensConfig()
           └─ registerContainerCompat()
```

### データフロー図

```
[入力]                       [処理]                           [出力]

CSS AST ─────────────▶ @plugin/@config収集 ────▶ pluginPaths/configPaths
                              │
loadModule() ◀───────────────┘
    │
    ▼
JS Plugin/Config ───▶ resolveConfig() ──────▶ ResolvedConfig
                              │
                              ▼
                      buildPluginApi() ──────▶ PluginAPI
                              │
                              ▼
                      handler(api) ──────────▶ DesignSystem変更
                              │                (ユーティリティ/バリアント追加)
                              ▼
                      applyConfigToTheme() ──▶ Theme変更
                      registerScreensConfig() ▶ Variants変更
                      registerContainerCompat()▶ Utilities変更
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| apply-compat-hooks.ts | `packages/tailwindcss/src/compat/apply-compat-hooks.ts` | ソース | メインの後方互換フック処理 |
| plugin-api.ts | `packages/tailwindcss/src/compat/plugin-api.ts` | ソース | プラグインAPI（buildPluginApi）の構築 |
| resolve-config.ts | `packages/tailwindcss/src/compat/config/resolve-config.ts` | ソース | 設定ファイルの解決・マージ |
| types.ts | `packages/tailwindcss/src/compat/config/types.ts` | ソース | UserConfig/ResolvedConfig型定義 |
| create-compat-config.ts | `packages/tailwindcss/src/compat/config/create-compat-config.ts` | ソース | v3互換デフォルト設定の生成 |
| deep-merge.ts | `packages/tailwindcss/src/compat/config/deep-merge.ts` | ソース | 設定オブジェクトのディープマージ |
| apply-config-to-theme.ts | `packages/tailwindcss/src/compat/apply-config-to-theme.ts` | ソース | JS設定のテーマ適用 |
| apply-keyframes-to-theme.ts | `packages/tailwindcss/src/compat/apply-keyframes-to-theme.ts` | ソース | キーフレームのテーマ適用 |
| legacy-utilities.ts | `packages/tailwindcss/src/compat/legacy-utilities.ts` | ソース | レガシーユーティリティ登録 |
| dark-mode.ts | `packages/tailwindcss/src/compat/dark-mode.ts` | ソース | ダークモードプラグイン |
| screens-config.ts | `packages/tailwindcss/src/compat/screens-config.ts` | ソース | スクリーン設定の互換登録 |
| container.ts | `packages/tailwindcss/src/compat/container.ts` | ソース | コンテナプラグイン互換 |
| theme-variants.ts | `packages/tailwindcss/src/compat/theme-variants.ts` | ソース | テーマバリアントの上書き登録 |
| plugin-functions.ts | `packages/tailwindcss/src/compat/plugin-functions.ts` | ソース | createThemeFn等のプラグイン用ユーティリティ |
| index.ts | `packages/tailwindcss/src/index.ts` | ソース | parseCss内でのapplyCompatibilityHooks呼び出し（614-620行目） |
