# 機能設計書 33-クラス順序の決定（getClassOrder）

## 概要

本ドキュメントは、Tailwind CSSにおけるユーティリティクラスのソート順序を決定するgetClassOrder関数の機能設計を記述する。

### 本機能の処理概要

候補クラス名のリストに対して、Tailwind CSSの正しいソート順序を付与する機能である。各クラスにbigint型のソート番号を割り当て、Prettierプラグインやエディタツール等で一貫したクラス順序を実現する。

**業務上の目的・背景**：Tailwind CSSのユーティリティクラスは、CSS出力における順序が重要である。後に出力されるクラスほどスタイルの優先度が高くなるため、意図しない順序でクラスが並ぶとスタイルの上書きが発生する可能性がある。本機能は、任意のクラス名リストに対してTailwind CSSの内部的なソート順序を返すことで、Prettierプラグイン（prettier-plugin-tailwindcss）等のツールがclass属性内のクラス名を正しい順序にソートできるようにする。

**機能の利用シーン**：
- Prettierプラグインによるclass属性内のクラス名の自動ソート
- IDE拡張機能でのクラス順序の検証・修正
- DesignSystem APIを通じた外部ツールからのクラス順序参照

**主要な処理内容**：
1. 入力クラス名リストをcompileCandidatesに渡してソート済みASTを生成する
2. 各クラス名にnull（Tailwindクラスでない）で初期化したMapを作成する
3. ソート済みASTノードを走査し、各候補クラスにインクリメンタルなbigint番号を割り当てる
4. 複数のルールにマッチする候補は、最初のルールの位置を採用する
5. クラス名と対応するソート番号のペア配列を返す

**関連システム・外部連携**：DesignSystem APIの一部として公開される。prettier-plugin-tailwindcss等の外部ツールから利用される。

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

## 関連画面

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

## 機能種別

計算処理（クラス名のソート順序計算）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| design | DesignSystem | Yes | デザインシステムオブジェクト | 有効なDesignSystemインスタンスであること |
| classes | string[] | Yes | ソート順序を取得するクラス名の配列 | 空配列も許容 |

### 入力データソース

DesignSystem APIのgetClassOrderメソッド経由で呼び出される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | [string, bigint \| null][] | クラス名とソート順序番号のペア配列。Tailwindクラスでない場合はnull |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. compileCandidatesの呼び出し
   └─ 入力クラスリストからソート済みASTとnodeSortingマップを取得
2. 初期Mapの作成
   └─ 全クラス名をキーとし、値をnullで初期化
3. ASTノードの走査
   └─ ソート済みastNodesを順に走査し、各ノードの候補クラス名を取得
4. ソート番号の割り当て
   └─ インクリメンタルなbigint（0n, 1n, 2n, ...）を各候補に割り当て
   └─ 既に番号が割り当てられている場合はスキップ（最初の位置を維持）
5. 結果の構築
   └─ 入力classes配列の順序を維持しつつ、各クラス名にソート番号を付与
```

### フローチャート

```mermaid
flowchart TD
    A[開始: classes配列を受け取り] --> B[compileCandidates実行]
    B --> C[astNodes, nodeSortingを取得]
    C --> D[sorted Map作成: 全クラス→null]
    D --> E[idx = 0n で初期化]
    E --> F{astNodesを順に走査}
    F --> G[nodeSorting.getで候補クラス名取得]
    G --> H{候補クラスが存在?}
    H -->|No| F
    H -->|Yes| I{既にソート番号あり?}
    I -->|Yes| J[既存番号を維持]
    I -->|No| K[sorted.set: candidate → idx++]
    J --> F
    K --> F
    F --> L[classes.mapで[className, sorted番号]ペア配列を構築]
    L --> M[終了: ペア配列を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-33-01 | 非Tailwindクラス | Tailwind CSSのユーティリティとして認識されないクラスにはnullが返される | parseCandidate/compileCandidatesで認識できないクラス |
| BR-33-02 | 最初のルール優先 | 複数のルールにマッチする候補は、最初に出現したルールの位置を採用する | 同一候補が複数ルールを生成する場合 |
| BR-33-03 | ソート順序の一貫性 | 同じクラスセットを入力した場合、常に同じソート順序が返される | 常に |
| BR-33-04 | 入力順序の保持 | 出力配列の順序は入力classes配列の順序を維持する | 常に |

### 計算ロジック

ソート番号はcompileCandidatesの内部ソートアルゴリズムに基づく:
1. バリアント順序（bigintビットフラグ）
2. CSSプロパティの出現順（GLOBAL_PROPERTY_ORDER）
3. プロパティ数（多い方が先）
4. アルファベット順

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

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

データベース操作なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 認識不能クラス | 入力クラス名がTailwindユーティリティとして認識できない | nullを返す（エラーにはしない） |

### リトライ仕様

リトライは不要。

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

トランザクション管理なし。

## パフォーマンス要件

- compileCandidatesの呼び出しが主要な計算コストである。クラス数が多い場合はパース・コンパイル・ソートのオーバーヘッドが増加する
- 内部でcompileCandidatesを毎回呼び出すため、大量のクラスリストに対する頻繁な呼び出しにはキャッシュ戦略が必要な場合がある

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

特になし。

## 備考

- bigint型を使用しているのは、大量のクラスに対して精度を失わずにソート番号を表現するため
- getClassOrderはDesignSystemオブジェクトのメソッドとして公開されており、design-system.tsの167-169行目でラップされている

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | design-system.ts | `packages/tailwindcss/src/design-system.ts` | DesignSystem型定義（35-68行目）のgetClassOrderシグネチャ（45行目） |
| 1-2 | compile.ts | `packages/tailwindcss/src/compile.ts` | compileCandidatesの戻り値型（astNodes, nodeSorting） |

**読解のコツ**: nodeSortingはAstNodeをキーとし、`{ properties, variants, candidate }`を値とするMapである。candidateフィールドが元のクラス名文字列を保持している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sort.ts | `packages/tailwindcss/src/sort.ts` | `getClassOrder`関数の全体（4-30行目） |

**主要処理フロー**:
1. **6行目**: `compileCandidates(Array.from(classes), design)`でソート済みASTを生成
2. **10行目**: 全クラス名をnullで初期化したMapを作成
3. **13行目**: idx = 0n でインクリメンタルカウンタを初期化
4. **15-22行目**: astNodesを走査し、nodeSortingから候補クラス名を取得して番号を割り当て
5. **21行目**: `sorted.get(candidate) ?? idx++` - 既存番号がない場合のみ新番号を割り当て
6. **25-29行目**: 入力classes配列の順序でペア配列を構築

#### Step 3: compileCandidatesのソートロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | compile.ts | `packages/tailwindcss/src/compile.ts` | compileCandidates関数（11-121行目）のソート処理（83-115行目） |

**主要処理フロー**:
- **83-115行目**: astNodes.sort()のコンパレータ関数
- **92-94行目**: バリアント順序による比較（bigint）
- **96-114行目**: プロパティ順序 → プロパティ数 → アルファベット順による比較

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

```
DesignSystem.getClassOrder (design-system.ts:167-169)
    │
    └─ getClassOrder (sort.ts:4)
           │
           ├─ compileCandidates (compile.ts:11)
           │      ├─ designSystem.parseCandidate()
           │      ├─ designSystem.compileAstNodes()
           │      └─ astNodes.sort() [バリアント順→プロパティ順→アルファベット順]
           │
           └─ nodeSorting.get(node)
                  └─ 候補クラス名の取得
```

### データフロー図

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

classes: string[]   ───▶ compileCandidates()           ───▶ ソート済みAST
["mt-4", "p-2",          │
 "flex", "custom"]       ├─ sorted Map初期化
                         │   {mt-4: null, p-2: null,
                         │    flex: null, custom: null}
                         │
                         ├─ AST走査 & 番号割り当て
                         │   {flex: 0n, mt-4: 1n,
                         │    p-2: 2n, custom: null}
                         │
                         └─ ペア配列構築              ───▶ [["mt-4", 1n],
                                                            ["p-2", 2n],
                                                            ["flex", 0n],
                                                            ["custom", null]]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sort.ts | `packages/tailwindcss/src/sort.ts` | ソース | メイン処理: getClassOrder関数 |
| compile.ts | `packages/tailwindcss/src/compile.ts` | ソース | compileCandidates: ソート済みAST生成 |
| design-system.ts | `packages/tailwindcss/src/design-system.ts` | ソース | DesignSystem API: getClassOrderメソッド公開 |
| property-order.ts | `packages/tailwindcss/src/property-order.ts` | ソース | プロパティ順序表（ソートに間接的に使用） |
