# 機能設計書 32-宣言の展開（expandDeclaration）

## 概要

本ドキュメントは、Tailwind CSSにおけるCSS省略プロパティの個別プロパティへの展開処理（expandDeclaration）の機能設計を記述する。

### 本機能の処理概要

CSS省略プロパティ（shorthand property）を個別のロングハンドプロパティに展開する機能である。margin、padding、inset、gap等の省略プロパティを個別方向のプロパティに分解し、論理プロパティの物理プロパティへの変換も行う。

**業務上の目的・背景**：Tailwind CSSの候補クラスの正規化処理において、省略プロパティを個別プロパティに展開する必要がある。これにより、`margin: 1rem 2rem`のような省略記法を`margin-top: 1rem; margin-right: 2rem; margin-bottom: 1rem; margin-left: 2rem`に分解し、各プロパティ単位での比較・ソートを可能にする。また、CSS論理プロパティ（margin-inline等）を物理プロパティ（margin-left/right）に変換することで、一貫したプロパティ順序の管理を実現する。

**機能の利用シーン**：候補の正規化処理（canonicalizeCandidates）の中でCSS宣言のプロパティ展開が必要な際に呼び出される。特に、ユーティリティクラスのシグネチャ比較において、異なる記述形式を統一した形に正規化する目的で使用される。

**主要な処理内容**：
1. 論理プロパティの物理プロパティへの変換（LogicalToPhysicalフラグが有効な場合）
2. 可変長論理プロパティ（inset-block、margin-inline等）の展開
3. 固定論理プロパティ（border-block、border-inline等）の展開
4. 標準可変長プロパティ（inset、margin、padding、gap）の展開

**関連システム・外部連携**：外部システムとの連携はない。内部的にAST構築関数（decl）とsegmentユーティリティに依存する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面に直接関連しない内部処理機能 |

## 機能種別

計算処理（CSS省略プロパティの展開・変換）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| node | Declaration（AstNode） | Yes | CSS宣言ノード（property, value, importantを含む） | kindが'declaration'であること |
| options | SignatureFeatures | Yes | 展開オプション。LogicalToPhysicalフラグにより論理→物理変換の有効/無効を制御 | ビットフラグ値 |

### 入力データソース

候補の正規化処理（canonicalize-candidates.ts）から呼び出される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | AstNode[] \| null | 展開されたCSS宣言ノードの配列。展開不要な場合はnullを返す |

### 出力先

呼び出し元関数への戻り値として返される。

## 処理フロー

### 処理シーケンス

```
1. LogicalToPhysicalフラグの確認
   ├─ 有効な場合:
   │   ├─ 可変長論理プロパティの展開（VARIADIC_LOGICAL_EXPANSION_MAP）
   │   │   └─ inset-block, inset-inline, margin-block, margin-inline,
   │   │       padding-block, padding-inline
   │   └─ 固定論理プロパティの展開（LOGICAL_EXPANSION_MAP）
   │       └─ border-block, border-block-color, border-block-style,
   │           border-block-width, border-inline, border-inline-color,
   │           border-inline-style, border-inline-width
   └─ 無効な場合: 論理プロパティの展開をスキップ
2. 標準可変長プロパティの展開（VARIADIC_EXPANSION_MAP）
   └─ inset, margin, padding, gap
3. 該当しない場合はnullを返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始: Declaration nodeを受け取り] --> B{LogicalToPhysicalフラグ有効?}
    B -->|Yes| C{可変長論理プロパティ?}
    C -->|Yes| D[値をスペースで分割]
    D --> E[分割数に応じたプロパティマッピングで展開]
    E --> F[展開済みDeclaration配列を返却]
    C -->|No| G{固定論理プロパティ?}
    G -->|Yes| H[全展開先プロパティに同一値を適用]
    H --> F
    G -->|No| I{標準可変長プロパティ?}
    B -->|No| I
    I -->|Yes| J[値をスペースで分割]
    J --> K[分割数に応じたプロパティマッピングで展開]
    K --> F
    I -->|No| L[nullを返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-32-01 | 可変長展開（1値） | `margin: 1rem` → 4方向すべてに同一値を適用 | 値が1つの場合 |
| BR-32-02 | 可変長展開（2値） | `margin: 1rem 2rem` → 上下に1rem、左右に2rem | 値が2つの場合 |
| BR-32-03 | 可変長展開（3値） | `margin: 1rem 2rem 3rem` → 上1rem、左右2rem、下3rem | 値が3つの場合 |
| BR-32-04 | 可変長展開（4値） | `margin: 1rem 2rem 3rem 4rem` → 上1rem、右2rem、下3rem、左4rem | 値が4つの場合 |
| BR-32-05 | ペア展開（1値） | `gap: 1rem` → row-gapとcolumn-gapに同一値 | gapの値が1つの場合 |
| BR-32-06 | ペア展開（2値） | `gap: 1rem 2rem` → row-gapに1rem、column-gapに2rem | gapの値が2つの場合 |
| BR-32-07 | 論理→物理変換 | inset-block → top/bottom、margin-inline → margin-left/margin-right等 | LogicalToPhysicalフラグ有効時 |
| BR-32-08 | border論理展開 | border-block → border-bottom/border-top（値はそのまま複製） | LogicalToPhysicalフラグ有効時 |
| BR-32-09 | importantの伝播 | 元のノードのimportantフラグが展開後の全ノードに伝播される | 常に |

### 計算ロジック

CSSの省略プロパティ展開はCSS仕様に準拠する:
- 1値: 全方向に同一値
- 2値: 上下/左右のペア
- 3値: 上 / 左右 / 下
- 4値: 上 / 右 / 下 / 左（時計回り）

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

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

データベース操作なし。純粋な関数型の変換処理である。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 展開不可 | マッピングに存在しないプロパティ | nullを返す |
| - | 展開不可 | 値の分割数がマッピングに存在しない | undefined（暗黙的にnullish）を返す |

### リトライ仕様

リトライは不要。入力に対して常に決定的な結果を返す。

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

トランザクション管理なし。ステートレスな純粋関数である。

## パフォーマンス要件

軽量な文字列操作とマッピング参照のみのため、特別なパフォーマンス要件はない。

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

特になし。外部入力を直接受け取らない内部処理関数である。

## 備考

- 展開マッピングは静的に定義されたレコードオブジェクトであり、実行時の変更はない
- CSS仕様のcreateQuad展開（1→4値、2→4値、3→4値、4→4値）に準拠している

---

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

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

### 推奨読解順序

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

展開マッピングの定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | expand-declaration.ts | `packages/tailwindcss/src/expand-declaration.ts` | ヘルパー関数と展開マッピング定義（5-64行目） |

**読解のコツ**:
- `createPrefixedQuad`（5-13行目）: `margin`のようなプレフィックスから4方向プロパティ名を生成するヘルパー
- `createBareQuad`（16-23行目）: top/right/bottom/leftの4方向展開マッピングを生成。キーは値の個数（1-4）、値は`[プロパティ名, インデックス]`のペア配列
- `createPair`（26-31行目）: 2方向展開マッピングを生成
- `VARIADIC_EXPANSION_MAP`（34-39行目）: inset, margin, padding, gapの展開マッピング
- `VARIADIC_LOGICAL_EXPANSION_MAP`（42-52行目）: 論理プロパティの可変長展開マッピング
- `LOGICAL_EXPANSION_MAP`（55-64行目）: 論理プロパティの固定展開マッピング（値を複製）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | expand-declaration.ts | `packages/tailwindcss/src/expand-declaration.ts` | `expandDeclaration`関数（66-93行目） |

**主要処理フロー**:
1. **66-69行目**: 関数定義。Declarationノードとoptions（SignatureFeatures）を受け取る
2. **70行目**: `options & SignatureFeatures.LogicalToPhysical`で論理→物理変換フラグを確認
3. **71-76行目**: 可変長論理プロパティの展開。segment()で値をスペース分割し、分割数に応じたマッピングで展開
4. **78-83行目**: 固定論理プロパティの展開。全展開先に同一値を適用
5. **85-90行目**: 標準可変長プロパティの展開
6. **92行目**: 該当しない場合はnullを返す

#### Step 3: 依存関係を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ast.ts | `packages/tailwindcss/src/ast.ts` | `decl()`関数 - 展開後のDeclarationノードを生成 |
| 3-2 | segment.ts | `packages/tailwindcss/src/utils/segment.ts` | `segment()`関数 - 値文字列のスペース区切り分割 |
| 3-3 | canonicalize-candidates.ts | `packages/tailwindcss/src/canonicalize-candidates.ts` | 呼び出し元 - SignatureFeaturesの定義を含む |

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

```
canonicalizeCandidates (canonicalize-candidates.ts)
    │
    └─ expandDeclaration (expand-declaration.ts:66)
           │
           ├─ segment() (utils/segment.ts)
           │      └─ 値文字列をスペースで分割
           │
           ├─ VARIADIC_LOGICAL_EXPANSION_MAP 参照
           │      └─ createPair() / createBareQuad()で事前定義
           │
           ├─ LOGICAL_EXPANSION_MAP 参照
           │
           ├─ VARIADIC_EXPANSION_MAP 参照
           │      └─ createPrefixedQuad() / createBareQuad() / createPair()で事前定義
           │
           └─ decl() (ast.ts)
                  └─ Declarationノード生成
```

### データフロー図

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

Declaration {              展開マッピング参照               AstNode[] | null
  property: "margin",  ──▶  │
  value: "1rem 2rem",       ├─ segment("1rem 2rem", " ")
  important: false          │   → ["1rem", "2rem"]
}                           │
                            ├─ VARIADIC_EXPANSION_MAP["margin"][2]
                            │   → [[margin-top, 0], [margin-right, 1],
                            │      [margin-bottom, 0], [margin-left, 1]]
                            │
                            └─ decl()で各ノード生成     ──▶ [
                                                             decl("margin-top", "1rem"),
                                                             decl("margin-right", "2rem"),
                                                             decl("margin-bottom", "1rem"),
                                                             decl("margin-left", "2rem")
                                                           ]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| expand-declaration.ts | `packages/tailwindcss/src/expand-declaration.ts` | ソース | メイン処理: CSS省略プロパティの展開 |
| ast.ts | `packages/tailwindcss/src/ast.ts` | ソース | decl()関数によるDeclarationノード生成 |
| segment.ts | `packages/tailwindcss/src/utils/segment.ts` | ソース | 文字列分割ユーティリティ |
| canonicalize-candidates.ts | `packages/tailwindcss/src/canonicalize-candidates.ts` | ソース | 呼び出し元。SignatureFeatures定義を含む |
