# 機能設計書 39-ソースマップシリアライズ

## 概要

本ドキュメントは、Tailwind CSSにおけるDecodedSourceMapのJSON形式へのシリアライズ機能の機能設計を記述する。

### 本機能の処理概要

DecodedSourceMap（ECMA-426準拠のオブジェクトグラフ形式ソースマップ）をJSON文字列にシリアライズする機能である。source-map-jsライブラリのSourceMapGeneratorを使用してエンコードし、インラインソースマップ（Base64埋め込み）および外部ファイル形式のソースマップコメントを生成する。

**業務上の目的・背景**：No.38のソースマップ生成で構築されたDecodedSourceMapは、オブジェクトグラフ形式のため、そのままブラウザやツールで消費することはできない。本機能は、このデコード形式をJSON文字列（Source Map v3形式）にシリアライズすることで、ブラウザの開発者ツールや各種ビルドツールで利用可能な標準的なソースマップ形式に変換する。インラインソースマップ（Base64エンコードしてCSSコメント内に埋め込む形式）と、外部ファイル形式のソースマップコメントの両方に対応する。

**機能の利用シーン**：
- PostCSSプラグイン、Viteプラグイン、CLIでのビルド時のソースマップ出力
- インラインソースマップの生成（開発ビルド）
- 外部ソースマップファイルの生成（本番ビルド）

**主要な処理内容**：
1. DecodedSourceMapまたはJSON文字列をtoSourceMapに渡す
2. DecodedSourceMapの場合はserializeSourceMapでJSON文字列に変換
3. serializeSourceMapはSourceMapGeneratorを使用し、各マッピングを追加してシリアライズ
4. SourceMapオブジェクトとして、raw（JSON文字列）、inline（Base64インライン）、comment（URLコメント）を返す

**関連システム・外部連携**：source-map-jsライブラリに依存。ブラウザ開発者ツールおよびビルドツール（PostCSS、Vite、webpack等）と連携する。

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

## 関連画面

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

## 機能種別

データ変換処理（ソースマップのシリアライズ）

## 入力仕様

### 入力パラメータ

#### toSourceMap

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| map | DecodedSourceMap \| string | Yes | デコードされたソースマップオブジェクトまたは既にシリアライズ済みのJSON文字列 | 有効なDecodedSourceMapまたはJSON文字列 |

### 入力データソース

No.38のcreateSourceMap関数が生成したDecodedSourceMapが入力される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | SourceMap | シリアライズされたソースマップオブジェクト |

SourceMap構造:

| フィールド | 型 | 説明 |
|-----------|-----|------|
| raw | string（readonly） | ソースマップのJSON文字列 |
| inline | string（readonly, getter） | Base64エンコードしたインラインソースマップコメント |
| comment | (url: string) => string | 外部ソースマップへのURLコメントを生成する関数 |

### 出力先

呼び出し元への戻り値として返される。PostCSS/Vite/CLI等のプラグインがCSS出力に付加する。

## 処理フロー

### 処理シーケンス

```
1. 入力の型判定
   ├─ string型: そのままrawとして使用
   └─ DecodedSourceMap型: serializeSourceMap()でJSON文字列に変換
2. serializeSourceMap処理（DecodedSourceMapの場合）
   a. SourceMapGenerator()を初期化
   b. sourceTable（DefaultMap）を初期化（未知ソースに連番URLを付与）
   c. 各マッピングについて:
      ├─ sourceTableからソースURL/内容を取得
      ├─ generator.addMapping()でマッピングを追加
      └─ generator.setSourceContent()でソース内容を設定
   d. generator.toString()でJSON文字列を返す
3. SourceMapオブジェクトの構築
   ├─ raw: JSON文字列
   ├─ inline: Base64エンコード → data:URI形式のCSSコメント（遅延評価getter）
   └─ comment: URLを受け取りCSSコメント文字列を返す関数
```

### フローチャート

```mermaid
flowchart TD
    A[開始: map受け取り] --> B{mapの型判定}
    B -->|string| C[raw = map]
    B -->|DecodedSourceMap| D[serializeSourceMap呼び出し]
    D --> E[SourceMapGenerator初期化]
    E --> F[sourceTable DefaultMap初期化]
    F --> G[各mappingをループ]
    G --> H[sourceTableからソース情報取得]
    H --> I[generator.addMapping]
    I --> J[generator.setSourceContent]
    J --> G
    G --> K[generator.toString]
    K --> C
    C --> L[SourceMapオブジェクト構築]
    L --> M[raw, inline getter, comment関数を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-39-01 | 型分岐 | 入力がstring型の場合はシリアライズをスキップし、そのままrawとして使用する | typeof map === 'string' |
| BR-39-02 | 未知ソースURL | ソースURL（src.url）がnullの場合、`<unknown N>`形式の連番URLを付与する | src?.url がnullの場合 |
| BR-39-03 | 未知ソース内容 | ソース内容（src.content）がnullの場合、`<none>`を設定する | src?.content がnullの場合 |
| BR-39-04 | インラインBase64 | inlineプロパティはgetter（遅延評価）で、Base64エンコードしたdata:URIコメントを返す | inlineプロパティアクセス時 |
| BR-39-05 | コメント形式 | ソースマップコメントは`/*# sourceMappingURL=... */\n`形式 | comment関数呼び出し時 |
| BR-39-06 | ソース内容設定 | 各ソースファイルに対してsetSourceContentでソース内容をインライン設定する | 常に |

### 計算ロジック

インラインソースマップの生成:
1. JSON文字列をUTF-8としてBufferに変換
2. Base64エンコード
3. `data:application/json;base64,{encoded}`形式のURLを構築
4. `/*# sourceMappingURL={url} */\n`形式のCSSコメントを生成

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

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

データベース操作なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | nullソース | マッピングのoriginalPosition.sourceがnullの場合 | sourceTableのDefaultMapで`<unknown N>`URLを付与 |

### リトライ仕様

リトライは不要。

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

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

## パフォーマンス要件

- inlineプロパティはgetter（遅延評価）であり、アクセスされるまでBase64エンコードは行われない
- SourceMapGeneratorのシリアライズコストはマッピング数に比例する

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

- インラインソースマップにはソースコードの内容がBase64エンコードで含まれる。本番環境ではインラインソースマップの使用を避け、外部ファイル形式を使用することが推奨される

## 備考

- source-map-jsライブラリはMozillaのsource-mapパッケージのフォークであり、V8エンジンに最適化されている
- SourceMapオブジェクトのinlineプロパティはNode.jsのBufferを使用するため、ブラウザ環境では使用できない

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | source-maps.ts | `packages/@tailwindcss-node/src/source-maps.ts` | SourceMap型定義（6-10行目） |
| 1-2 | source-map.ts | `packages/tailwindcss/src/source-maps/source-map.ts` | DecodedSourceMap、DecodedSource型の再export |

**読解のコツ**:
- `SourceMap`: raw, inline, commentの3フィールドを持つ
- `inline`はgetterで遅延評価される
- `comment`はURLを受け取る関数

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | source-maps.ts | `packages/@tailwindcss-node/src/source-maps.ts` | `toSourceMap`関数（45-60行目） |

**主要処理フロー**:
1. **46行目**: `typeof map === 'string' ? map : serializeSourceMap(map)`で型分岐
2. **48-49行目**: `comment`関数の定義
3. **52-58行目**: SourceMapオブジェクトの構築
4. **54行目**: `get inline()`のgetter定義 - Base64エンコード処理

#### Step 3: serializeSourceMap関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | source-maps.ts | `packages/@tailwindcss-node/src/source-maps.ts` | `serializeSourceMap`関数（12-43行目） |

**主要処理フロー**:
1. **13行目**: `new SourceMapGenerator()`で初期化
2. **15-27行目**: `sourceTable = new DefaultMap(...)`の定義。nullソースに連番URLを付与
3. **29-40行目**: 各マッピングのループ
4. **32-37行目**: `generator.addMapping()`でマッピング追加
5. **39行目**: `generator.setSourceContent()`でソース内容設定
6. **42行目**: `generator.toString()`でJSON文字列化

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

```
PostCSS/Vite/CLIプラグイン
    │
    └─ toSourceMap (source-maps.ts:45)
           │
           ├─ serializeSourceMap (source-maps.ts:12)
           │      │
           │      ├─ new SourceMapGenerator() [source-map-js]
           │      ├─ DefaultMap（sourceTable）
           │      ├─ generator.addMapping()
           │      ├─ generator.setSourceContent()
           │      └─ generator.toString()
           │
           └─ SourceMapオブジェクト構築
                  ├─ raw: JSON文字列
                  ├─ inline: Buffer.from().toString('base64')
                  └─ comment: (url) => CSSコメント
```

### データフロー図

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

DecodedSourceMap     ───▶ serializeSourceMap()           ───▶ JSON文字列
  .mappings                │
  .sources                 ├─ SourceMapGenerator
                           │   ├─ addMapping()
                           │   └─ setSourceContent()
                           │
                           └─ toString()                 ───▶ SourceMap {
                                                                raw: "{"version":3,...}",
                                                                inline: "/*# sourceMappingURL=
                                                                  data:application/json;base64,
                                                                  ... */\n",
                                                                comment: (url) => string
                                                              }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| source-maps.ts | `packages/@tailwindcss-node/src/source-maps.ts` | ソース | メイン処理: toSourceMap/serializeSourceMap関数 |
| source-map.ts | `packages/tailwindcss/src/source-maps/source-map.ts` | ソース | DecodedSourceMap型定義（No.38） |
| default-map.ts | `packages/tailwindcss/src/utils/default-map.ts` | ソース | DefaultMap: 連番URL生成に使用 |
| source-map-js | （外部ライブラリ） | 依存関係 | SourceMapGenerator: ソースマップのエンコード |
