# 機能設計書 1-CSS入力のコンパイル（compile）

## 概要

本ドキュメントは、Tailwind CSSのメインエントリーポイントである`compile`関数の機能設計書である。CSS文字列を入力として受け取り、Tailwind CSSのディレクティブを解析・変換して最終的なCSSを出力するコンパイルパイプライン全体を定義する。

### 本機能の処理概要

**業務上の目的・背景**：Tailwind CSSはユーティリティファーストのCSSフレームワークであり、開発者がHTML/JSXのclass属性に記述したユーティリティクラス名を実際のCSSに変換する必要がある。`compile`関数はこの変換プロセスの最上位エントリーポイントであり、CSSファイルに記述された`@import`、`@theme`、`@tailwind utilities`、`@custom-variant`、`@utility`、`@source`等のディレクティブを処理し、DesignSystemを構築した上で、候補クラスからユーティリティCSSを生成するパイプラインを提供する。

**機能の利用シーン**：PostCSSプラグイン、Viteプラグイン、CLIツール等のビルドツール統合からのエントリーポイントとして利用される。開発者がCSSファイルに`@import 'tailwindcss'`と記述した際に、ビルドプロセスの中でこの関数が呼び出され、最終的なCSSが生成される。

**主要な処理内容**：
1. CSS文字列をパースしてAST（抽象構文木）に変換する
2. `@import`ディレクティブを解決して外部スタイルシートをインライン展開する
3. `@theme`ディレクティブからテーマ変数を収集してThemeオブジェクトを構築する
4. `@tailwind utilities`の位置を記録し、ユーティリティCSS挿入ポイントを確保する
5. `@custom-variant`および`@utility`によるカスタム定義を登録する
6. `@source`ディレクティブからスキャン対象パスを収集する
7. DesignSystemを構築し、バリアント・ユーティリティ・テーマを統合する
8. `@apply`、CSS関数（`theme()`等）、`@variant`の置換処理を実行する
9. 候補クラス集合を受け取り、ユーティリティCSSノードを生成するbuild関数を返す
10. AST最適化を実行し、最終的なCSS文字列を出力する

**関連システム・外部連携**：ファイルシステム（`loadStylesheet`コールバックによるスタイルシート読み込み）、Node.jsモジュールシステム（`loadModule`コールバックによるプラグイン・設定ファイル読み込み）と連携する。

**権限による制御**：特になし。ビルドツールから呼び出される関数であり、権限制御は上位レイヤーで管理される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | トップページ | 主画面 | index.cssの@import 'tailwindcss'により、Tailwind CSSのコンパイルパイプラインが実行される |
| 3 | レイアウト | 主画面 | globals.cssの@import 'tailwindcss'により、Tailwind CSSのコンパイルパイプラインが実行される |
| 5 | レイアウト | 主画面 | globals.cssのv3互換ディレクティブにより、Tailwind CSSのコンパイルパイプラインが実行される |

## 機能種別

データ変換処理（CSS文字列 -> AST -> 最適化済みCSS文字列）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| css | string | Yes | 入力CSS文字列。Tailwind CSSのディレクティブを含む | UTF-8エンコーディング。BOM付きの場合は自動除去 |
| opts.base | string | No | ベースディレクトリパス。ファイル解決の基準 | デフォルトは空文字列 |
| opts.from | string | No | 入力CSSファイルのパス。ソースマップ生成に使用 | ファイルパス文字列 |
| opts.polyfills | Polyfills | No | ポリフィル設定。AtProperty/ColorMixの有効化フラグ | ビットフラグ（Polyfills.AtProperty, Polyfills.ColorMix） |
| opts.loadModule | Function | No | JSモジュール読み込みコールバック | 未指定時はエラーをスロー |
| opts.loadStylesheet | Function | No | スタイルシート読み込みコールバック | 未指定時はエラーをスロー |

### 入力データソース

- ビルドツール（PostCSS/Vite/Webpack/CLI）が読み込んだCSSファイルの内容が文字列として渡される
- `loadModule`コールバック経由でJSプラグイン・設定ファイルが読み込まれる
- `loadStylesheet`コールバック経由で`@import`されたスタイルシートが読み込まれる

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| sources | Array<{base, pattern, negated}> | スキャン対象のソースパス情報 |
| root | null \| 'none' \| {base, pattern} | ルートソース設定 |
| features | Features | 使用された機能フラグ（AtApply, AtImport等） |
| build | (candidates: string[]) => string | 候補クラスからCSS文字列を生成する関数 |
| buildSourceMap | () => DecodedSourceMap | ソースマップ生成関数 |

### 出力先

- build関数の戻り値としてCSS文字列が返される
- buildSourceMap関数の戻り値としてソースマップ情報が返される
- 呼び出し元のビルドツールがファイル出力を担当する

## 処理フロー

### 処理シーケンス

```
1. CSS文字列のパース
   └─ CSS.parse(css, { from: opts.from }) でAST配列に変換
2. parseCss関数によるディレクティブ処理
   ├─ 2.1 コンテキストノードでASTをラップ（ベースディレクトリ設定）
   ├─ 2.2 @import解決（substituteAtImports）
   ├─ 2.3 ASTウォーク開始
   │   ├─ @tailwind utilities の検出・位置記録
   │   ├─ @utility カスタムユーティリティ収集
   │   ├─ @source スキャン対象パス収集
   │   ├─ @variant / @custom-variant バリアント定義収集
   │   ├─ @media パラメータ処理（source/theme/prefix/important/reference）
   │   └─ @theme テーマ変数収集・Themeオブジェクト構築
   ├─ 2.4 DesignSystem構築（buildDesignSystem）
   ├─ 2.5 後方互換フック適用（applyCompatibilityHooks）
   ├─ 2.6 カスタムバリアント登録（トポロジカルソート順）
   ├─ 2.7 カスタムユーティリティ登録
   ├─ 2.8 テーマ変数の出力設定
   ├─ 2.9 @variant置換（substituteAtVariant）
   ├─ 2.10 CSS関数置換（substituteFunctions）
   └─ 2.11 @apply置換（substituteAtApply）
3. compileAst関数によるbuild関数の構築
   ├─ 3.1 バージョンコメント追加
   ├─ 3.2 インライン候補の初期登録
   └─ 3.3 build関数のクロージャ定義
4. compile関数のラッパー処理
   ├─ 4.1 build呼び出し時: ASTからCSS文字列変換（toCss）
   └─ 4.2 buildSourceMap呼び出し時: ソースマップ生成（createSourceMap）
```

### フローチャート

```mermaid
flowchart TD
    A[CSS文字列入力] --> B[CSS.parse でASTに変換]
    B --> C[parseCss: ディレクティブ処理]
    C --> D{@import あり?}
    D -->|Yes| E[substituteAtImports: 外部CSS展開]
    D -->|No| F[ASTウォーク開始]
    E --> F
    F --> G[@theme テーマ変数収集]
    F --> H[@tailwind utilities 位置記録]
    F --> I[@source パス収集]
    F --> J[@custom-variant 定義収集]
    F --> K[@utility 定義収集]
    G --> L[DesignSystem構築]
    H --> L
    I --> L
    J --> L
    K --> L
    L --> M[後方互換フック適用]
    M --> N[カスタムバリアント/ユーティリティ登録]
    N --> O[@variant/@apply/CSS関数の置換]
    O --> P[build関数を返却]
    P --> Q{build呼び出し}
    Q --> R[compileCandidates: 候補からAST生成]
    R --> S[optimizeAst: AST最適化]
    S --> T[toCss: CSS文字列出力]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 重複@tailwind utilities除去 | 2つ目以降の`@tailwind utilities`ノードは除去される | 複数の`@tailwind utilities`が存在する場合 |
| BR-02 | @referenceコンテキスト内の除去 | `@reference`コンテキスト内の`@tailwind utilities`は除去される | @referenceでインポートされた場合 |
| BR-03 | カスタムバリアント順序 | カスタムバリアントはトポロジカルソートにより依存関係順に登録される | @custom-variant間に依存関係がある場合 |
| BR-04 | テーマ変数の結合 | 最初の`@theme`ルール位置に全テーマ変数が出力される | 複数の@themeブロックが存在する場合 |
| BR-05 | ビルドキャッシュ | 候補クラスが変化しない場合、前回のコンパイル結果をキャッシュとして返す | build関数の連続呼び出し時 |
| BR-06 | 無効候補の記録 | 無効な候補クラスはinvalidCandidatesセットに記録され、以降のビルドでスキップされる | 候補クラスが解析不能な場合 |
| BR-07 | important設定 | `@import "tailwindcss" important`でグローバルに!importantが付与される | important修飾子が指定された場合 |

### 計算ロジック

- ビルドキャッシュの差分検出: 新しいASTノード数と前回のノード数を比較し、変化がない場合はキャッシュを返却
- 候補クラスの有効性判定: `designSystem.invalidCandidates`セットに含まれない候補のみを処理対象とする

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

### 操作別データベース影響一覧

該当なし（本機能はデータベースを使用しない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | `loadModule`未指定時にプラグイン/設定の読み込みが必要 | `No 'loadModule' function provided to 'compile'` |
| - | Error | `loadStylesheet`未指定時に@importの解決が必要 | `No 'loadStylesheet' function provided to 'compile'` |
| - | Error | `@utility`がネストされている | `'@utility' cannot be nested.` |
| - | Error | `@utility`が空のボディを持つ | `'@utility {name}' is empty.` |
| - | Error | `@source`がボディを持つ | `'@source' cannot have a body.` |
| - | Error | `@source`パスが引用符で囲まれていない | `'@source' paths must be quoted.` |
| - | Error | `@custom-variant`がネストされている | `'@custom-variant' cannot be nested.` |
| - | Error | `@theme`ブロックにカスタムプロパティ以外が含まれる | `'@theme' blocks must only contain custom properties or '@keyframes'.` |
| - | Error | カスタムバリアントの循環依存 | `Circular dependency detected in custom variants` |
| - | Error | プレフィックスが無効 | `The prefix "{prefix}" is invalid.` |

### リトライ仕様

リトライは行わない。エラー発生時はビルドプロセスが中断される。

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

該当なし（本機能はインメモリ処理であり、トランザクション管理は不要）

## パフォーマンス要件

- build関数はキャッシュ機構を持ち、候補クラスに変化がない場合は前回のコンパイル結果を再利用する
- `allValidCandidates`のサイズ変化を監視し、不要な再コンパイルを回避する
- 無効な候補はinvalidCandidatesセットに記録し、2回目以降のパース処理をスキップする

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

- `loadModule`コールバックを通じて任意のJSモジュールが実行される可能性がある。呼び出し元で信頼できるモジュールパスのみを許可する必要がある
- `loadStylesheet`コールバックを通じて任意のファイルが読み込まれる可能性がある

## 備考

- `__unstable__loadDesignSystem`関数はDesignSystemオブジェクトのみを取得するためのヘルパー関数として公開されている
- `compileAst`関数は`compile`関数の内部実装であるが、パース済みASTを直接受け取る用途で外部にも公開されている（No.2参照）
- デフォルトエクスポートの`postcssPluginWarning`は、直接PostCSSプラグインとして使用しようとした場合のエラーメッセージを提供する

---

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

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

### 推奨読解順序

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

まず、コンパイルパイプラインで使用されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ast.ts | `packages/tailwindcss/src/ast.ts` | AstNode型（StyleRule, AtRule, Declaration, Comment, Context, AtRoot）の構造を理解する |
| 1-2 | index.ts | `packages/tailwindcss/src/index.ts` | CompileOptions型（54-75行目）とFeatures列挙型（116-139行目）、Polyfills列挙型（41-52行目）を理解する |

**読解のコツ**: TypeScriptの`const enum`はコンパイル時にインライン化されるため、実行時には数値として扱われる。`Features`や`Polyfills`はビットフラグパターンを使用しており、`|=`演算子でフラグを追加、`&`演算子でフラグの有無を判定する。

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

処理の起点となる`compile`関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/tailwindcss/src/index.ts` | `compile`関数（819-855行目）がメインエントリーポイント。CSS文字列のパースからbuild関数の構築までの全体像を把握する |

**主要処理フロー**:
1. **829行目**: `CSS.parse(css, { from: opts.from })` でCSS文字列をASTに変換
2. **830行目**: `compileAst(ast, opts)` でAST処理とbuild関数の構築
3. **836-847行目**: build関数のラッパー。ASTからCSS文字列への変換（toCss）とキャッシュ機構
4. **849-853行目**: buildSourceMap関数。ソースマップの生成

#### Step 3: parseCss関数を理解する

compile関数の中核であるparseCss関数の処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/tailwindcss/src/index.ts` | `parseCss`関数（141-707行目）。ディレクティブ処理の全体を担当する |

**主要処理フロー**:
- **151行目**: コンテキストノードでASTをラップ（ベースディレクトリ情報を付加）
- **153行目**: `substituteAtImports`による@import解決
- **169-596行目**: ASTウォークによるディレクティブ処理ループ
  - **175-220行目**: `@tailwind utilities`の検出と位置記録
  - **223-254行目**: `@utility`カスタムユーティリティの収集
  - **257-307行目**: `@source`スキャン対象パスの収集
  - **310-348行目**: `@variant`の処理
  - **351-449行目**: `@custom-variant`の登録処理
  - **451-539行目**: `@media`パラメータ処理（source/theme/prefix/important/reference）
  - **542-596行目**: `@theme`テーマ変数の収集
- **598行目**: `buildDesignSystem`でDesignSystemを構築
- **614-620行目**: `applyCompatibilityHooks`で後方互換フックを適用
- **629-643行目**: カスタムバリアントをトポロジカルソート順に登録
- **645-647行目**: カスタムユーティリティを登録
- **672-674行目**: `substituteAtVariant`、`substituteFunctions`、`substituteAtApply`による置換処理

#### Step 4: compileAst関数（build関数生成）を理解する

build関数のクロージャ構造と候補クラス処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.ts | `packages/tailwindcss/src/index.ts` | `compileAst`関数（709-815行目）。build関数の生成ロジックを理解する |

**主要処理フロー**:
- **718-719行目**: parseCssの結果を受け取る
- **733-734行目**: キャッシュ変数（allValidCandidates, compiled, previousAstNodeCount）の初期化
- **749-813行目**: build関数のクロージャ定義
  - **750-752行目**: features === Features.Noneの場合、入力をそのまま返却
  - **754-757行目**: utilitiesNodeが無い場合、静的ASTの最適化のみ
  - **765-776行目**: 新しい候補の追加と差分検出
  - **785-787行目**: `compileCandidates`による候補クラスからASTノード生成
  - **809行目**: ユーティリティノードに新しいASTノードを設定
  - **811行目**: `optimizeAst`でAST最適化

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

```
compile(css, opts)
    |
    +-- CSS.parse(css)                     ... CSSパーサー
    |
    +-- compileAst(ast, opts)
         |
         +-- parseCss(ast, opts)
         |    |
         |    +-- substituteAtImports()     ... @import解決
         |    |
         |    +-- walk(ast)                 ... ディレクティブ処理ループ
         |    |    +-- @tailwind utilities 検出
         |    |    +-- @utility 収集
         |    |    +-- @source パス収集
         |    |    +-- @custom-variant 登録
         |    |    +-- @theme 変数収集
         |    |
         |    +-- buildDesignSystem()       ... DesignSystem構築
         |    |
         |    +-- applyCompatibilityHooks() ... v3互換処理
         |    |
         |    +-- topologicalSort()         ... カスタムバリアント順序決定
         |    |
         |    +-- substituteAtVariant()     ... @variant置換
         |    +-- substituteFunctions()     ... CSS関数置換
         |    +-- substituteAtApply()       ... @apply置換
         |
         +-- build(candidates)             ... クロージャとして返却
              |
              +-- compileCandidates()      ... 候補からASTノード生成
              +-- optimizeAst()            ... AST最適化
              +-- toCss()                  ... CSS文字列変換
```

### データフロー図

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

CSS文字列         ──▶  CSS.parse             ──▶  AstNode[]
                       (css-parser.ts)

AstNode[]         ──▶  parseCss              ──▶  DesignSystem
                       (index.ts)                  sources[]
                                                   utilitiesNode
                                                   features

DesignSystem      ──▶  build(candidates)     ──▶  AstNode[]（最適化済み）
候補クラス名[]          (index.ts内クロージャ)

AstNode[]         ──▶  toCss                 ──▶  CSS文字列
                       (ast.ts)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/tailwindcss/src/index.ts` | ソース | compile/compileAst/parseCss関数の定義。メインエントリーポイント |
| css-parser.ts | `packages/tailwindcss/src/css-parser.ts` | ソース | CSS文字列をASTにパースする |
| ast.ts | `packages/tailwindcss/src/ast.ts` | ソース | ASTノード型定義、ノード生成関数、toCss、optimizeAst |
| compile.ts | `packages/tailwindcss/src/compile.ts` | ソース | compileCandidates関数。候補クラスからASTノードを生成 |
| design-system.ts | `packages/tailwindcss/src/design-system.ts` | ソース | DesignSystem構築（buildDesignSystem） |
| theme.ts | `packages/tailwindcss/src/theme.ts` | ソース | テーマ管理（Theme）クラス |
| walk.ts | `packages/tailwindcss/src/walk.ts` | ソース | ASTウォーカー |
| at-import.ts | `packages/tailwindcss/src/at-import.ts` | ソース | @import解決処理 |
| apply.ts | `packages/tailwindcss/src/apply.ts` | ソース | @apply置換処理 |
| css-functions.ts | `packages/tailwindcss/src/css-functions.ts` | ソース | CSS関数置換処理（theme(), --spacing()等） |
| variants.ts | `packages/tailwindcss/src/variants.ts` | ソース | バリアント管理・@variant置換処理 |
| utilities.ts | `packages/tailwindcss/src/utilities.ts` | ソース | ユーティリティ登録・生成 |
| compat/apply-compat-hooks.ts | `packages/tailwindcss/src/compat/apply-compat-hooks.ts` | ソース | v3後方互換フック |
| utils/topological-sort.ts | `packages/tailwindcss/src/utils/topological-sort.ts` | ソース | トポロジカルソート |
| utils/brace-expansion.ts | `packages/tailwindcss/src/utils/brace-expansion.ts` | ソース | ブレース展開 |
| utils/segment.ts | `packages/tailwindcss/src/utils/segment.ts` | ソース | 文字列セグメント分割 |
| utils/escape.ts | `packages/tailwindcss/src/utils/escape.ts` | ソース | CSSエスケープ処理 |
| source-maps/source-map.ts | `packages/tailwindcss/src/source-maps/source-map.ts` | ソース | ソースマップ生成 |
