# 機能設計書 50-プラグイン定義API（createPlugin）

## 概要

本ドキュメントは、Tailwind CSSプラグインを定義するための `createPlugin` 関数およびwithOptionsパターンの設計を記述する。

### 本機能の処理概要

createPluginは、Tailwind CSSプラグインの公式な定義APIである。handler関数とオプション設定を受け取り、PluginWithConfigオブジェクトを返す。`withOptions` パターンにより、ユーザーがプラグイン使用時にオプションを渡せるプラグインも定義できる。

**業務上の目的・背景**：Tailwind CSSのプラグインエコシステムでは、サードパーティの開発者がカスタムユーティリティ・バリアント・ベーススタイルを提供するプラグインを作成する。`createPlugin` はその公式APIであり、`tailwindcss/plugin` からインポートして使用する。handler関数にはPluginAPIが渡され、`addUtilities`、`addVariant` 等のメソッドでDesignSystemを拡張できる。

**機能の利用シーン**：プラグイン開発者が新しいプラグインを作成するとき。`@plugin "パス"` ディレクティブで読み込まれるJSファイル内、またはtailwind.config.jsのpluginsセクションで使用される。

**主要な処理内容**：
1. `createPlugin(handler, config?)`: handler関数とオプション設定からPluginWithConfigを生成
2. `createPlugin.withOptions(pluginFn, configFn?)`: オプション受け付け可能なプラグインを生成
3. `withOptions` パターンでは `__isOptionsFunction: true` マーカーを付与
4. オプション付き呼び出し時に handler と config を遅延生成

**関連システム・外部連携**：PluginAPI（plugin-api.ts）を通じてDesignSystemに間接アクセスする。

**権限による制御**：特になし。

## 関連画面

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

## 機能種別

計算処理（プラグイン定義）

## 入力仕様

### 入力パラメータ

#### createPlugin

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| handler | PluginFn | Yes | プラグインのhandler関数 | (api: PluginAPI) => void の形式 |
| config | Partial<Config> | No | プラグインのデフォルト設定 | 有効なConfig形式 |

#### createPlugin.withOptions

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pluginFunction | (options?: T) => PluginFn | Yes | オプションからhandler関数を生成する関数 | 関数であること |
| configFunction | (options?: T) => Partial<Config> | No | オプションから設定を生成する関数 | 関数であること（デフォルト: () => ({})） |

### 入力データソース

- プラグイン開発者によるJavaScriptコード

## 出力仕様

### 出力データ

#### createPlugin

| 項目名 | 型 | 説明 |
|--------|-----|------|
| plugin | PluginWithConfig | handler + config を持つプラグインオブジェクト |

#### createPlugin.withOptions

| 項目名 | 型 | 説明 |
|--------|-----|------|
| pluginFactory | PluginWithOptions<T> | オプションを受け取りPluginWithConfigを返す関数 |

### 出力先

- tailwind.config.jsのpluginsセクション
- @pluginディレクティブ経由のapplyCompatibilityHooks

## 処理フロー

### 処理シーケンス

```
createPlugin(handler, config):
1. PluginWithConfigオブジェクトを生成
   └─ { handler, config } を返す

createPlugin.withOptions(pluginFunction, configFunction):
1. optionsFunction関数を生成
   ├─ options引数を受け取り、pluginFunction(options)でhandlerを生成
   └─ configFunction(options)でconfigを生成
2. __isOptionsFunction = true マーカーを付与
3. optionsFunction を PluginWithOptions<T> として返す
```

### フローチャート

```mermaid
flowchart TD
    A{createPlugin使用パターン}
    A -->|基本| B["createPlugin(handler, config?)"]
    A -->|withOptions| C["createPlugin.withOptions(pluginFn, configFn?)"]
    B --> D["{ handler, config }"]
    C --> E["optionsFunction生成"]
    E --> F["__isOptionsFunction = true"]
    F --> G["optionsFunction返却"]
    G --> H{プラグイン使用時}
    H -->|オプション付き| I["optionsFunction(opts)"]
    I --> J["{ handler: pluginFn(opts), config: configFn(opts) }"]
    H -->|オプションなし| K["resolveConfig内で optionsFunction() 呼び出し"]
    K --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-50-01 | 基本パターン | handler + configを持つPluginWithConfigを生成する | createPlugin呼び出し |
| BR-50-02 | withOptionsパターン | オプション関数を返し、呼び出し時にhandler/configを遅延生成する | withOptions呼び出し |
| BR-50-03 | __isOptionsFunction | withOptionsで生成された関数には`__isOptionsFunction: true`が付与される | withOptions |
| BR-50-04 | configFunction省略 | configFunctionが省略された場合、デフォルトで空オブジェクトを返す | configFunction未指定 |
| BR-50-05 | オプション受け渡し | @pluginのbodyで定義されたオプションがwithOptionsのoptions引数に渡される | @plugin使用時 |

### 計算ロジック

**withOptionsの動作フロー**:
1. プラグイン定義時: `createPlugin.withOptions(fn, configFn)` → `optionsFunction`
2. プラグイン使用時: `optionsFunction(options)` → `{ handler: fn(options), config: configFn(options) }`
3. オプションなしの場合（resolveConfig内）: `optionsFunction()` → `{ handler: fn(undefined), config: configFn(undefined) }`

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | withOptionsでないプラグインにオプションが渡された場合 | apply-compat-hooks.tsの265行目でエラーが投げられる |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- createPluginは単純なオブジェクト生成のためオーバーヘッドは無視できる

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

- プラグインのhandler関数はサードパーティコードを実行するため、信頼されたプラグインのみ使用すべきである

## 備考

- `plugin.ts` は `tailwindcss/plugin` としてエクスポートされ、プラグイン開発者が `import plugin from 'tailwindcss/plugin'` でインポートする
- v3互換の型（Config, PluginAPI, PluginCreator, PluginsConfig, PluginUtils, ThemeConfig）もre-exportされている
- `__isOptionsFunction` マーカーは `resolveConfig` のextractConfigsと `applyCompatibilityHooks` のupgradeToFullPluginSupportで、withOptionsプラグインの判定に使用される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | plugin-api.ts | `packages/tailwindcss/src/compat/plugin-api.ts` | PluginFn/PluginWithConfig/PluginWithOptions型の定義（22-36行目） |
| 1-2 | plugin-api.ts | `packages/tailwindcss/src/compat/plugin-api.ts` | Plugin union型（36行目）。PluginFn, PluginWithConfig, PluginWithOptions<any>のunion |
| 1-3 | plugin-api.ts | `packages/tailwindcss/src/compat/plugin-api.ts` | PluginAPI型（38-89行目）。handler関数に渡されるAPI一覧 |

**読解のコツ**: Plugin型はunion型で3つの形式がある。createPluginはPluginWithConfigを生成し、createPlugin.withOptionsはPluginWithOptions<T>を生成する。

#### Step 2: createPlugin関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | plugin.ts | `packages/tailwindcss/src/plugin.ts` | createPlugin関数（12-17行目）。非常にシンプルなオブジェクト生成 |

**主要処理フロー**:
1. **12行目**: `function createPlugin(handler, config?)` のシグネチャ
2. **13-16行目**: `{ handler, config }` を返すのみ

#### Step 3: withOptionsパターンを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | plugin.ts | `packages/tailwindcss/src/plugin.ts` | createPlugin.withOptions（19-33行目） |

**主要処理フロー**:
1. **19-21行目**: pluginFunctionとconfigFunction（デフォルト: () => ({})）を受け取る
2. **23-27行目**: optionsFunction内でhandlerとconfigを遅延生成
3. **30行目**: `__isOptionsFunction = true` マーカーの付与
4. **32行目**: optionsFunctionをPluginWithOptions<T>として返す

#### Step 4: withOptionsの使用箇所を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | resolve-config.ts | `packages/tailwindcss/src/compat/config/resolve-config.ts` | extractConfigs内のプラグイン正規化（143行目）。__isOptionsFunction判定 |
| 4-2 | apply-compat-hooks.ts | `packages/tailwindcss/src/compat/apply-compat-hooks.ts` | upgradeToFullPluginSupport内（256行目）。withOptionsプラグインへのオプション渡し |

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

```
createPlugin(handler, config)
    └─ { handler, config }  [PluginWithConfig]

createPlugin.withOptions(pluginFn, configFn)
    └─ optionsFunction  [PluginWithOptions<T>]
           │
           ├─ (options) → { handler: pluginFn(options), config: configFn(options) }
           │
           └─ __isOptionsFunction = true
                  │
                  ├─ extractConfigs: plugin() → PluginWithConfig
                  │   (オプションなし呼び出し)
                  │
                  └─ upgradeToFullPluginSupport: plugin(options) → PluginWithConfig
                      (CSSオプション付き呼び出し)
```

### データフロー図

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

handler関数 ─────────▶ createPlugin() ──────▶ PluginWithConfig
config設定                                      { handler, config }

pluginFunction ─────▶ createPlugin.withOptions() ▶ PluginWithOptions<T>
configFunction                                      optionsFunction
                                                         │
                           使用時                        ▼
options (CSS/@plugin) ──▶ optionsFunction(opts) ──▶ PluginWithConfig
                                                      { handler, config }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| plugin.ts | `packages/tailwindcss/src/plugin.ts` | ソース | createPlugin関数の定義 |
| plugin-api.ts | `packages/tailwindcss/src/compat/plugin-api.ts` | ソース | PluginFn/PluginWithConfig/PluginWithOptions/PluginAPI型、buildPluginApi関数 |
| resolve-config.ts | `packages/tailwindcss/src/compat/config/resolve-config.ts` | ソース | extractConfigs内のプラグイン正規化（__isOptionsFunction判定） |
| apply-compat-hooks.ts | `packages/tailwindcss/src/compat/apply-compat-hooks.ts` | ソース | @pluginのオプション解析、withOptionsプラグインへのオプション渡し |
| types.ts | `packages/tailwindcss/src/compat/config/types.ts` | ソース | UserConfig型（pluginsプロパティ） |
