# 機能設計書 20-CSS関数の置換（substituteFunctions）

## 概要

本ドキュメントは、CSS内の `theme()`・`--theme()`・`--spacing()`・`--alpha()` 等のカスタム関数呼び出しを実際の値に置換するsubstituteFunctions関数の設計について記述する。

### 本機能の処理概要

substituteFunctions関数は、AST内のCSS宣言値やat-ruleパラメータに含まれるカスタム関数呼び出しを検出し、テーマ値やcalc()式等の実際のCSS値に置換する。

**業務上の目的・背景**：Tailwind CSSでは、CSS内でテーマ値を参照するための専用関数が提供されている。`theme()` はv3互換のレガシー形式で、`--theme()` はv4のネイティブ形式である。`--spacing()` はテーマのspacing値に基づいた間隔計算を行い、`--alpha()` は色にアルファ値を適用する。これらの関数をコンパイル時に実際のCSS値に置換することで、ブラウザが理解できるCSSを生成する。

**機能の利用シーン**：`@theme` ブロック内でテーマ値を参照する際、カスタムCSSでテーマ値を使用する際、`@media` や `@supports` のクエリ内でテーマ値を使用する際に実行される。

**主要な処理内容**：
1. AST走査による関数呼び出しの検出（declaration値、at-ruleパラメータ）
2. `--alpha(color / alpha)`: color-mix()によるアルファ値適用
3. `--spacing(multiplier)`: テーマのspacing値に乗数を掛けたcalc()式の生成
4. `--theme(--variable)`: CSS変数からのテーマ値参照（v4形式）
5. `theme(path)`: ドット区切りパスからのテーマ値参照（v3互換レガシー形式）
6. ValueParserによるネストされた関数呼び出しの再帰的処理
7. THEME_FUNCTION_INVOCATIONの正規表現による高速な事前フィルタリング

**関連システム・外部連携**：DesignSystem（design-system.ts）を通じてThemeのresolveThemeValueを参照する。withAlpha（utilities.ts）を使用してcolor-mix式を生成する。

**権限による制御**：権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに直接の関連画面なし。CSS内の関数呼び出しの内部処理 |

## 機能種別

CSS変換処理 / 値解決処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ast | AstNode[] | Yes | 処理対象のAST配列 | - |
| designSystem | DesignSystem | Yes | デザインシステムオブジェクト | - |

### 各関数の入力パラメータ

| 関数名 | パラメータ | 型 | 説明 |
|--------|----------|-----|------|
| --alpha | value | string | `color / alpha` 形式の文字列 |
| --spacing | value | string | 乗数（例: `2`, `0.5`） |
| --theme | path | string | CSS変数名（`--` で始まる） |
| --theme | fallback | string[] | フォールバック値（オプション） |
| theme | path | string | ドット区切りまたはCSS変数パス |
| theme | fallback | string[] | フォールバック値（オプション） |

### 入力データソース

- コンパイルパイプラインで処理中のAST（declaration値、at-ruleパラメータ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| features | Features | 使用されたフィーチャーフラグ（Features.ThemeFunction） |

### 出力先

- 入力ASTが直接変更される（破壊的操作）
- 関数呼び出しが解決済みの値で置換される

## 処理フロー

### 処理シーケンス

```
1. AST 走査（walk）
   ├─ declaration ノード
   │   ├─ THEME_FUNCTION_INVOCATION 正規表現でフィルタ
   │   └─ substituteFunctionsInValue で値を置換
   └─ at-rule ノード（@media, @custom-media, @container, @supports）
       ├─ THEME_FUNCTION_INVOCATION 正規表現でフィルタ
       └─ substituteFunctionsInValue でパラメータを置換

2. substituteFunctionsInValue
   ├─ ValueParser.parse で値ASTに変換
   ├─ walk で関数ノードを検出
   ├─ CSS_FUNCTIONS マップで対応する関数を呼び出し
   ├─ 引数をカンマで分割
   └─ WalkAction.Replace で結果を置換

3. 各関数の処理
   ├─ --alpha(color / alpha): withAlpha で color-mix 式生成
   ├─ --spacing(multiplier): calc(spacing * multiplier) 生成
   ├─ --theme(--var): resolveThemeValue で値解決
   └─ theme(path): レガシー形式のテーマ値解決
```

### フローチャート

```mermaid
flowchart TD
    A["AST走査"] --> B{ノード種別}
    B -->|declaration| C{"THEME_FUNCTION_INVOCATION?"}
    B -->|at-rule| D{"対象at-rule かつ THEME_FUNCTION_INVOCATION?"}
    C -->|No| E["スキップ"]
    C -->|Yes| F["substituteFunctionsInValue(value)"]
    D -->|No| E
    D -->|Yes| G["substituteFunctionsInValue(params)"]
    F --> H["ValueParser.parse"]
    G --> H
    H --> I["walk で関数ノード検出"]
    I --> J{"関数名?"}
    J -->|--alpha| K["withAlpha(color, alpha)"]
    J -->|--spacing| L["calc(spacing * value)"]
    J -->|--theme| M["resolveThemeValue(path)"]
    J -->|theme| N["legacyTheme(path)"]
    K --> O["WalkAction.Replace"]
    L --> O
    M --> O
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-20-01 | --alpha必須引数 | --alpha()は色とアルファ値の両方が必要。`/` で区切る | --alpha呼び出し時 |
| BR-20-02 | --alpha単一引数 | --alpha()は1つの引数のみ受け付ける | --alpha呼び出し時 |
| BR-20-03 | --spacing必須引数 | --spacing()は引数が必須 | --spacing呼び出し時 |
| BR-20-04 | --spacing単一引数 | --spacing()は1つの引数のみ受け付ける | --spacing呼び出し時 |
| BR-20-05 | --spacingテーマ依存 | --spacing()はテーマに `--spacing` 変数が存在する必要がある | --spacing呼び出し時 |
| BR-20-06 | --themeCSS変数 | --theme()のパスは `--` で始まるCSS変数名である必要がある | --theme呼び出し時 |
| BR-20-07 | --themeインライン | --theme()で `inline` キーワードを末尾に付けるとインライン解決を強制する | `--theme(--var inline)` 形式 |
| BR-20-08 | at-ruleインライン | at-rule内での--theme()使用時は自動的にインライン解決される | @media等のat-rule内 |
| BR-20-09 | フォールバック | --theme() / theme()にフォールバック値を指定可能。テーマ値が見つからない場合に使用 | 第2引数以降 |
| BR-20-10 | 正規表現フィルタ | THEME_FUNCTION_INVOCATIONで事前フィルタリングし、不要なパースを回避する | 常時 |

### 計算ロジック

- `--alpha(color / alpha)`: `color-mix(in oklab, color alpha%, transparent)` 形式に変換。alpha が100%の場合は color-mix を省略する
- `--spacing(multiplier)`: `calc(var(--spacing) * multiplier)` 形式に変換。`--spacing` テーマ変数を基準に計算する
- `--theme(--var, fallback)`: テーマ値を解決し、フォールバック付きの `var()` 関数や `initial` フォールバックの注入を行う

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | --alpha()に色またはアルファ値が不足している場合 | エラーメッセージをスロー |
| - | Error | --alpha()に複数引数が指定された場合 | エラーメッセージをスロー |
| - | Error | --spacing()に引数がない場合 | エラーメッセージをスロー |
| - | Error | --spacing()に複数引数が指定された場合 | エラーメッセージをスロー |
| - | Error | --spacing()で`--spacing`テーマ変数が存在しない場合 | エラーメッセージをスロー |
| - | Error | --theme()のパスが`--`で始まらない場合 | エラーメッセージをスロー |
| - | Error | テーマ値が解決できずフォールバックもない場合 | エラーメッセージをスロー |

### リトライ仕様

リトライ処理は存在しない。

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

トランザクション管理は存在しない。

## パフォーマンス要件

- THEME_FUNCTION_INVOCATION 正規表現による事前フィルタリングで、関数呼び出しを含まないノードのパースを回避する
- ValueParser によるパースは関数呼び出しを含むノードに対してのみ実行される

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

CSS仕様の範囲内で処理される。テーマ値の注入にCSS変数を使用するため、CSSインジェクションのリスクはCSS仕様により制限される。

## 備考

- CSS_FUNCTIONS はオブジェクトリテラルで定義され、関数名から処理関数へのマッピングを保持する
- THEME_FUNCTION_INVOCATION は動的に生成される正規表現で、CSS_FUNCTIONS のキーから構築される
- v3互換の `theme()` 関数はドット区切りパス（例: `theme(colors.blue.500)`）をサポートする。v4の `--theme()` はCSS変数名形式（例: `--theme(--color-blue-500)`）を使用する
- `injectFallbackForInitialFallback` 関数は、ネストされた `var()` / `theme()` のフォールバック値を適切に注入する

---

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

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

### 推奨読解順序

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

CSS関数マッピングと正規表現フィルタを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | css-functions.ts | `packages/tailwindcss/src/css-functions.ts` | CSS_FUNCTIONS オブジェクト（9-17行目）。4つのカスタム関数のマッピング |
| 1-2 | css-functions.ts | `packages/tailwindcss/src/css-functions.ts` | THEME_FUNCTION_INVOCATION 正規表現（152-156行目）。事前フィルタリング用 |

**読解のコツ**: CSS_FUNCTIONS は `Record<string, Function>` 型で、関数名をキーとして処理関数を値に持つ。これにより新しい関数の追加が容易になっている。

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

substituteFunctions 関数のAST走査ロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | css-functions.ts | `packages/tailwindcss/src/css-functions.ts` | substituteFunctions関数（158-183行目）。AST走査とノード種別による分岐 |

**主要処理フロー**:
1. **160行目**: `walk(ast, callback)` でAST走査開始
2. **162-165行目**: declaration ノードの処理。値に関数呼び出しが含まれるかチェック
3. **169-179行目**: at-rule ノードの処理。@media / @custom-media / @container / @supports のパラメータをチェック
4. **163-164行目**: Features.ThemeFunction フラグの設定

#### Step 3: 値置換処理を理解する

substituteFunctionsInValue 関数の実装を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | css-functions.ts | `packages/tailwindcss/src/css-functions.ts` | substituteFunctionsInValue関数（185-204行目）。ValueParserによるパースと関数呼び出しの置換 |

**主要処理フロー**:
- **190行目**: `ValueParser.parse(value)` で値ASTに変換
- **191-200行目**: walk で関数ノードを検出し、CSS_FUNCTIONS からハンドラを呼び出す
- **193行目**: `segment(ValueParser.toCss(node.nodes).trim(), ',')` で引数を分割
- **199行目**: `WalkAction.Replace(ValueParser.parse(result))` で結果を置換

#### Step 4: 各関数の実装を理解する

4つのカスタム関数の個別実装を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | css-functions.ts | `packages/tailwindcss/src/css-functions.ts` | alpha関数（19-40行目）。`/` で色とアルファを分離し withAlpha を呼び出す |
| 4-2 | css-functions.ts | `packages/tailwindcss/src/css-functions.ts` | spacing関数（42-66行目）。テーマの `--spacing` 値を基にcalc()式を生成 |
| 4-3 | css-functions.ts | `packages/tailwindcss/src/css-functions.ts` | theme関数（68-127行目）。v4形式のテーマ値参照。inline / フォールバック対応 |
| 4-4 | css-functions.ts | `packages/tailwindcss/src/css-functions.ts` | legacyTheme関数（129-150行目）。v3互換のレガシーテーマ値参照 |
| 4-5 | css-functions.ts | `packages/tailwindcss/src/css-functions.ts` | injectFallbackForInitialFallback関数（226-243行目）。フォールバック値の注入 |

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

```
substituteFunctions(ast, designSystem)
    │
    ├─ walk(ast, callback)
    │      │
    │      ├─ [declaration] THEME_FUNCTION_INVOCATION.test(value)
    │      │      └─ substituteFunctionsInValue(value, node, designSystem)
    │      │
    │      └─ [at-rule] THEME_FUNCTION_INVOCATION.test(params)
    │             └─ substituteFunctionsInValue(params, node, designSystem)
    │
    └─ substituteFunctionsInValue(value, source, designSystem)
           ├─ ValueParser.parse(value)
           ├─ walk(ast, callback)
           │      └─ CSS_FUNCTIONS[node.value](designSystem, source, ...args)
           │             ├─ alpha() → withAlpha(color, alpha)
           │             ├─ spacing() → calc(spacing * value)
           │             ├─ theme() → designSystem.resolveThemeValue(path)
           │             └─ legacyTheme() → designSystem.resolveThemeValue(path)
           └─ ValueParser.toCss(ast)
```

### データフロー図

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

color: --alpha(red / 50%)    ───▶ alpha()                    ───▶ color: color-mix(in oklab, red 50%, transparent)

gap: --spacing(2)            ───▶ spacing()                  ───▶ gap: calc(var(--spacing) * 2)

color: --theme(--color-red)  ───▶ theme()                    ───▶ color: var(--color-red)

color: theme(colors.red.500) ───▶ legacyTheme()              ───▶ color: var(--color-red-500)

@media (width >= --theme(    ───▶ theme() [inline=true]      ───▶ @media (width >= 768px)
  --breakpoint-md))
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| css-functions.ts | `packages/tailwindcss/src/css-functions.ts` | ソース | substituteFunctions関数本体と4つのカスタム関数実装 |
| design-system.ts | `packages/tailwindcss/src/design-system.ts` | ソース | resolveThemeValue メソッド。テーマ値の解決 |
| theme.ts | `packages/tailwindcss/src/theme.ts` | ソース | Theme クラス。テーマ値の管理 |
| utilities.ts | `packages/tailwindcss/src/utilities.ts` | ソース | withAlpha 関数。color-mix式の生成 |
| value-parser.ts | `packages/tailwindcss/src/value-parser.ts` | ソース | CSS値のパース・シリアライズ |
| segment.ts | `packages/tailwindcss/src/utils/segment.ts` | ソース | 引数のカンマ分割 |
| walk.ts | `packages/tailwindcss/src/walk.ts` | ソース | ASTウォーカー。WalkAction.Replace |
| index.ts | `packages/tailwindcss/src/index.ts` | ソース | コンパイルパイプラインからのsubstituteFunctions呼び出し |
