# 通知設計書 21-ブロックリスト対象ユーティリティエラー

## 概要

本ドキュメントは、Tailwind CSSの`@apply`ディレクティブにおいて、ブロックリストに含まれるユーティリティクラスが使用された場合に発生するエラー通知の設計を定義する。

### 本通知の処理概要

ブロックリストに明示的に登録されたユーティリティクラスが`@apply`ディレクティブで参照された際に、開発者に対して明確なエラーメッセージを出力し、CSS生成処理を中断する通知処理である。

**業務上の目的・背景**：Tailwind CSS v4では、`blocklist`（JSコンフィグ経由）や`@source not inline(...)`ディレクティブにより、特定のユーティリティクラスを明示的に無効化できる。この機能はプロジェクトのコーディング規約やCSS出力サイズの最適化に活用される。`@apply`で無効化されたクラスが参照された場合、エラーメッセージにドキュメントURLを含めて出力し、開発者が迅速に原因と対処法を把握できるようにすることが本通知の目的である。

**通知の送信タイミング**：CSS生成処理の`@apply`展開フェーズにおいて、`compileCandidates`関数内の`onInvalidCandidate`コールバックが実行され、候補クラスが`designSystem.invalidCandidates`セットに含まれている場合にエラーがthrowされる。

**通知の受信者**：CLIでビルドコマンドを実行した開発者、またはPostCSSプラグイン経由でビルドを実行した開発者。エラーはthrowされるため、ビルドツールのコンソール出力に表示される。

**通知内容の概要**：`Cannot apply utility class \`{candidate}\` because it has been explicitly disabled`というメッセージに加え、公式ドキュメントへのリンク（`https://tailwindcss.com/docs/detecting-classes-in-source-files#explicitly-excluding-classes`）が含まれる。

**期待されるアクション**：開発者は、該当のユーティリティクラスをブロックリストから除外するか、`@apply`の使用箇所を別のユーティリティクラスに変更する。公式ドキュメントを参照し、ブロックリストの設定方法を確認することが推奨される。

## 通知種別

ランタイムエラー（`throw new Error`）。ビルド時にCLIのstderrまたはビルドツールのエラー出力としてコンソールに表示される。

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（throwによるエラー伝播） |
| 優先度 | 高（ビルド処理を中断する致命的エラー） |
| リトライ | 無（設定修正が必要） |

### 送信先決定ロジック

ビルドプロセスの呼び出し元に対してエラーが伝播する。CLIの場合はプロセスのstderrに出力され、PostCSSプラグインの場合は`console.error`経由で出力された後、PostCSSのエラーとして再throwされる。

## 通知テンプレート

### メール通知の場合

本通知はメール送信ではなく、コンソールエラー出力である。

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | N/A |
| 送信元名称 | N/A |
| 件名 | N/A |
| 形式 | テキスト（stderr出力） |

### 本文テンプレート

```
Cannot apply utility class `{candidate}` because it has been explicitly disabled: https://tailwindcss.com/docs/detecting-classes-in-source-files#explicitly-excluding-classes
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| N/A | N/A | N/A | 添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| candidate | @applyで指定されたユーティリティクラス名 | `@apply`ディレクティブのパラメータ解析結果 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ビルド処理 | `@apply`ディレクティブの展開処理 | `designSystem.invalidCandidates.has(candidate)` がtrueの場合 | ブロックリストに含まれるクラスの使用を検出 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| クラスがブロックリストに含まれない | `invalidCandidates`セットに含まれない場合はこのエラーは発生しない |
| 先にprefixエラーが該当する場合 | prefix設定がありprefixなしのクラスの場合は、先にprefixエラー（No.20）が発生する |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A["@applyディレクティブ検出"] --> B["compileCandidates呼び出し"]
    B --> C["candidateのパース"]
    C --> D{"invalidCandidates.has(candidate)?"}
    D -->|"Yes（ブロックリスト対象）"| E["compile.tsのonInvalidCandidate実行"]
    E --> F{"designSystem.invalidCandidates.has(candidate)?"}
    F -->|"Yes"| G["throw new Error（ブロックリストエラー）"]
    D -->|"No"| H["正常にCSS生成"]
    G --> I["ビルド処理中断"]
    H --> J["@apply展開完了"]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| N/A | N/A | データベースは使用しない |

### テーブル別参照項目詳細

本通知ではデータベースを参照しない。インメモリの`designSystem.invalidCandidates`（`Set<string>`）を参照する。

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| N/A | N/A | データベース更新なし |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ブロックリスト対象エラー | `designSystem.invalidCandidates`にcandidateが含まれる | ブロックリストから該当クラスを除外するか、`@apply`を別のクラスに変更する |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A（設定修正が必要） |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし。ビルド実行時に即座にエラーが出力される。

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

エラーメッセージにはユーティリティクラス名のみが含まれ、個人情報やシークレットは含まれない。外部URLへのリンクが含まれるが、公式ドキュメントへのリンクであるため問題はない。

## 備考

- `@apply`はテンプレートファイルからのクラス検出より前に処理されるため、`invalidCandidates`セットにはJSコンフィグの`blocklist`および`@source not inline(...)`で明示的に指定されたクラスのみが含まれる。
- 本エラーチェックは、prefix未付与エラー（No.20の`apply.ts:183-184`）の後に実行される。

---

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

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

### 推奨読解順序

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

まず、DesignSystemの`invalidCandidates`セットの構造と、ブロックリストがどのように構成されるかを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | design-system.ts | `packages/tailwindcss/src/design-system.ts` | `DesignSystem`型定義の`invalidCandidates: Set<string>`フィールド（40行目）を確認し、ブロックリスト管理の仕組みを理解する |

**読解のコツ**: `DesignSystem`はTailwind CSSのコア設計をまとめた型であり、`invalidCandidates`はビルド時にブロック対象と判定されたクラスの集合である。

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

`@apply`の処理エントリーポイントである`substituteAtApply`関数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | apply.ts | `packages/tailwindcss/src/apply.ts` | `substituteAtApply`関数（10行目）がAST全体をwalkして`@apply`ノードを収集し、トポロジカルソート後に展開する流れを把握する |

**主要処理フロー**:
1. **10行目**: `substituteAtApply`関数のエントリーポイント
2. **29-79行目**: ASTをwalkし`@apply`ノードと依存関係を収集
3. **86-154行目**: トポロジカルソートで展開順序を決定
4. **158-297行目**: `@apply`を実際のCSSに展開（ここでエラーチェックが実行される）

#### Step 3: エラー判定処理を理解する

`compileCandidates`の`onInvalidCandidate`コールバック内でのブロックリスト判定ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | apply.ts | `packages/tailwindcss/src/apply.ts` | 178-200行目の`onInvalidCandidate`コールバック内で、182-186行目のprefixチェック後、196-199行目で`invalidCandidates.has(candidate)`によるブロックリスト判定が行われる |
| 3-2 | compile.ts | `packages/tailwindcss/src/compile.ts` | 11-17行目の`compileCandidates`関数シグネチャと、28-30行目の`invalidCandidates`チェック処理を確認する |

**主要処理フロー**:
- **apply.ts 196行目**: `designSystem.invalidCandidates.has(candidate)` でブロックリスト判定
- **apply.ts 197-199行目**: `throw new Error` でエラーメッセージ（ドキュメントURL付き）を出力

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

```
substituteAtApply (apply.ts:10)
    |
    +-- walk([root], ...) (apply.ts:29)  # @applyノード収集
    |
    +-- visit(node, path) (apply.ts:86)  # トポロジカルソート
    |
    +-- walk(parent.nodes, ...) (apply.ts:161)  # @apply展開ループ
           |
           +-- compileCandidates(candidates, designSystem, {...}) (apply.ts:178)
                  |
                  +-- onInvalidCandidate(candidate) (apply.ts:180)
                         |
                         +-- prefix チェック (apply.ts:182-186)
                         |
                         +-- invalidCandidates.has(candidate) (apply.ts:196)
                         |      |
                         |      +-- throw new Error("Cannot apply...explicitly disabled...") (apply.ts:197-199)
                         |
                         +-- variant チェック (apply.ts:202-229)
                         +-- theme空チェック (apply.ts:235-239)
                         +-- 汎用エラー (apply.ts:242)
```

### データフロー図

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

CSSファイル中の            substituteAtApply()              throw new Error
@apply {candidate}  ───>   compileCandidates()  ───>       "Cannot apply utility class
                           onInvalidCandidate()             `{candidate}` because it has
                           invalidCandidates.has()          been explicitly disabled: ..."
                                                            ↓
designSystem                                           ビルド処理中断
.invalidCandidates  ───>   Set.has(candidate)           (CLIエラー出力 / PostCSS error)
(Set<string>)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| apply.ts | `packages/tailwindcss/src/apply.ts` | ソース | @apply展開処理のメインロジック。ブロックリストエラー判定を含む（196-199行目） |
| compile.ts | `packages/tailwindcss/src/compile.ts` | ソース | candidateのコンパイル処理。`onInvalidCandidate`コールバックを呼び出す |
| design-system.ts | `packages/tailwindcss/src/design-system.ts` | ソース | `DesignSystem`型定義。`invalidCandidates`フィールドを持つ |
| index.ts (postcss) | `packages/@tailwindcss-postcss/src/index.ts` | ソース | PostCSSプラグインのエントリーポイント。エラー発生時のconsole.error処理を含む |
