# 機能設計書 65-比較関数（compare）

## 概要

本ドキュメントは、Tailwind CSSにおける文字列の自然順ソート比較関数`compare`の機能設計を記述する。文字列内の数値部分を文字列としてではなく数値として比較する「自然順ソート（natural sort）」を実現し、クラスリストのアルファベット順ソートに使用される。

### 本機能の処理概要

**業務上の目的・背景**：Tailwind CSSのクラスリスト出力やIntelliSenseの補完候補表示において、クラス名を直感的な順序でソートする必要がある。通常の文字列ソートでは`p-2`が`p-10`より後に来てしまうが、自然順ソートにより`p-2`→`p-10`の正しい順序が保証される。これにより、`bg-red-50`, `bg-red-500`のような数値付きクラス名が期待通りの順序で並ぶ。

**機能の利用シーン**：IntelliSenseのクラスリスト取得（intellisense.ts）でのクラス名ソート、候補クラスのコンパイル（compile.ts）でのソート処理に使用される。

**主要な処理内容**：
1. 2つの文字列を1文字ずつ比較する
2. 両方の文字が数字の場合、連続する数字列を数値として比較する
3. 数値が同じだが文字列表現が異なる場合（例: `0123` vs `123`）は文字列ソートにフォールバック
4. 文字列の長さが異なる場合、短い文字列が先に来る

**関連システム・外部連携**：外部システムとの連携はない。Array.prototype.sortの比較関数として使用される。

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

## 関連画面

本機能は内部ユーティリティ関数であり、画面に直接関連しない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | 補助機能 | クラスリストのソート処理として間接的にIDE補完・CSS出力順序に寄与 |

## 機能種別

計算処理（文字列比較・ソート）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| a | string | Yes | 比較対象の1番目の文字列 | 任意の文字列 |
| z | string | Yes | 比較対象の2番目の文字列 | 任意の文字列 |

### 入力データソース

Array.prototype.sortの比較関数として呼び出される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | number | 負の数: aがzより前、0: 同値、正の数: aがzより後 |

### 出力先

Array.prototype.sortへの比較結果として返却される。

## 処理フロー

### 処理シーケンス

```
1. 両文字列の長さを取得し、短い方の長さを計算
   └─ minLen = Math.min(aLen, zLen)
2. minLen回のループで1文字ずつ比較
   ├─ 2a. 両方が数字(0-9)の場合
   │      ├─ 各文字列の連続する数字列を消費
   │      ├─ 数値として比較（差があればその差を返却）
   │      ├─ 数値が同じ場合は文字列表現で比較（先頭ゼロ等の考慮）
   │      └─ 完全に同じ場合はcontinue
   ├─ 2b. 同じ文字コードの場合
   │      └─ continue
   └─ 2c. 異なる文字コードの場合
          └─ 文字コードの差を返却
3. ループ完了（共通部分が同一）
   └─ 文字列の長さの差を返却（短い方が先）
```

### フローチャート

```mermaid
flowchart TD
    A[開始: a, z] --> B[minLen = min aLen, zLen]
    B --> C{i < minLen?}
    C -->|No| H["return a.length - z.length"]
    C -->|Yes| D[aCode, zCode を取得]
    D --> E{両方が数字?}
    E -->|Yes| F1[連続する数字列を消費]
    F1 --> F2[数値として比較]
    F2 --> F3{差がある?}
    F3 -->|Yes| F4[return diff]
    F3 -->|No| F5{文字列表現が異なる?}
    F5 -->|Yes| F6["return -1 or 1"]
    F5 -->|No| G1[continue]
    E -->|No| G{aCode === zCode?}
    G -->|Yes| G1
    G -->|No| G2["return aCode - zCode"]
    G1 --> C
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-65-01 | 自然順ソート | 文字列内の数値部分は数値として比較する | 両方の現在位置が数字の場合 |
| BR-65-02 | 数値優先 | 数値として異なる場合、数値の大小で順序を決定する | 数値比較結果が非ゼロ |
| BR-65-03 | 文字列フォールバック | 数値が同じだが文字列表現が異なる場合は辞書順で比較する | 例: `0123` vs `123` |
| BR-65-04 | 短い文字列優先 | 共通プレフィックスが同一の場合、短い文字列が先に来る | ループ完了時 |
| BR-65-05 | 安定ソート | 同値の場合は0を返し、ソートの安定性を保証する | 文字列が完全一致 |

### 計算ロジック

数字列の数値比較: `Number(aNumber) - Number(zNumber)`

数字の判定: charCodeが48('0')以上57('9')以下

文字列長の比較: `a.length - z.length`（短い文字列が先）

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

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

データベース操作はない。

## エラー処理

### エラーケース一覧

エラーはスローされない。全ての入力に対して数値を返す。

### リトライ仕様

リトライ処理はない。

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

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

## パフォーマンス要件

- O(n)の計算量（n: 短い方の文字列の長さ）
- charCodeAtによる直接的な文字コード比較で高速に動作
- 追加のメモリ割り当ては数字列のスライスのみ

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

セキュリティ上の考慮事項はない。

## 備考

- テストケースでは`bg-red-50`と`bg-red-500`の正しいソート順が検証されている
- `duration-initial`のような非数値文字列は数値付き文字列の後に来る
- Heapのアルゴリズムによる全順列テストで安定ソートが検証されている

---

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

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

### 推奨読解順序

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

本関数は独自のデータ型定義を持たず、プリミティブ型のみで動作する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | compare.ts | `packages/tailwindcss/src/utils/compare.ts` | **1-2行目**: ZERO(48)とNINE(57)の定数定義。数字判定に使用される文字コード |

**読解のコツ**: charCodeAtで取得した数値を直接定数と比較している。48は'0'、57は'9'のASCIIコード。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | compare.ts | `packages/tailwindcss/src/utils/compare.ts` | **8-61行目**: compare関数の全体実装 |

**主要処理フロー**:
1. **9-11行目**: 両文字列の長さとminLenの計算
2. **13-15行目**: メインループ。各位置のcharCodeを取得
3. **18-48行目**: 数字判定。両方が数字の場合の処理
   - **19-30行目**: 連続する数字列の消費（aEnd, zEndの拡張）
   - **32-33行目**: 数字列をスライスで取得
   - **35-36行目**: Number()で数値変換し差を計算。差があればreturn
   - **40-41行目**: 数値は同じだが文字列表現が異なる場合の辞書順フォールバック
   - **47行目**: 完全に同じ場合はcontinue（短い文字列が後に来ないよう）
4. **51行目**: 同じ文字コードの場合はcontinue
5. **54行目**: 異なる文字コードの場合は差を返却
6. **60行目**: ループ完了後、文字列長の差を返却

#### Step 3: テストコードで挙動を確認する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | compare.test.ts | `packages/tailwindcss/src/utils/compare.test.ts` | 基本的な比較テスト、数値付きクラス名ソート、複数数値のソート、安定ソート検証 |

**テストケースの注目ポイント**:
- **34-52行目**: `p-0`～`p-21`の自然順ソート結果の検証
- **54-88行目**: `bg-red-50`/`bg-red-500`の修飾子付きソート
- **134-168行目**: Heapのアルゴリズムによる全順列での安定ソート検証

#### Step 4: 利用箇所を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | intellisense.ts | `packages/tailwindcss/src/intellisense.ts` | クラスリスト取得時のソートにcompareを使用 |
| 4-2 | compile.ts | `packages/tailwindcss/src/compile.ts` | 候補クラスのコンパイル時のソートにcompareを使用 |

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

```
[呼び出し元]
    │
    ├─ intellisense.ts (getClassList)
    │      └─ classNames.sort(compare) ── クラス名の自然順ソート
    │
    └─ compile.ts (compileCandidates)
           └─ candidates.sort(compare) ── 候補クラスの自然順ソート
```

### データフロー図

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

文字列a ─────────▶ compare(a, z)
                          │
                          ├─ 文字ごとの比較ループ
                          │    ├─ 数字判定
                          │    ├─ 数字列の消費・数値比較
                          │    └─ 文字コード比較               ───▶ number
                          │                                          (負/0/正)
文字列z ─────────▶
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| compare.ts | `packages/tailwindcss/src/utils/compare.ts` | ソース | 自然順ソート比較関数の実装 |
| compare.test.ts | `packages/tailwindcss/src/utils/compare.test.ts` | テスト | 比較関数のユニットテスト |
| intellisense.ts | `packages/tailwindcss/src/intellisense.ts` | ソース | クラスリスト取得時のソートで利用 |
| compile.ts | `packages/tailwindcss/src/compile.ts` | ソース | 候補クラスのコンパイル時のソートで利用 |
