# バッチ設計書 10-license2rtf.mjs

## 概要

本ドキュメントは、Node.jsプロジェクトのライセンスRTF変換スクリプト「tools/license2rtf.mjs」の設計仕様を記載したものである。

### 本バッチの処理概要

license2rtf.mjsは、プレーンテキストのLICENSEファイルをRTF（Rich Text Format）形式に変換するNode.jsスクリプトである。Windowsインストーラー（MSI）で使用するライセンス表示用のRTFファイルを生成する。

**業務上の目的・背景**：WindowsのMSIインストーラーは、ライセンス表示にRTF形式を要求する。license2rtf.mjsは、Node.jsのLICENSEファイル（プレーンテキスト）を適切にフォーマットされたRTFに変換することで、WindowsインストーラービルドプロセスをサポートするStreamベースの変換パイプラインを提供する。

**バッチの実行タイミング**：Windowsインストーラー（MSI）のビルド時に実行される。

**主要な処理内容**：
1. 標準入力からテキストを読み込み
2. 行分割（LineSplitter）
3. 段落解析（ParagraphParser）- ライセンスブロックの検出
4. テキストの折り返し解除（Unwrapper）
5. RTF形式への変換（RtfGenerator）
6. 標準出力にRTFを出力

**前後の処理との関連**：license-builder.shで生成されたLICENSEファイルを入力として使用する。vcbuild.batのMSIビルドプロセスで呼び出される。

**影響範囲**：WindowsインストーラーのライセンスダイアログUIに影響を与える。

## バッチ種別

ファイル変換

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | MSIビルド時 |
| 実行時刻 | 指定なし |
| 実行曜日 | 指定なし |
| 実行日 | 指定なし |
| トリガー | vcbuild msi / WiXビルドプロセス |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Node.js | スクリプト実行用にNode.jsが必要 |
| LICENSE | 入力となるLICENSEファイルが存在すること |

### 実行可否判定

- 標準入力がない場合は空のRTFを出力
- 入力テキストのフォーマットが想定外でも処理は継続

## 入力仕様

### 入力パラメータ

本スクリプトは標準入力からテキストを読み込む。コマンドライン引数はない。

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| stdin | テキスト（UTF-8） | LICENSEファイルの内容 |

### 入力フォーマット

LICENSEファイルは以下の構造を持つ：
- ヘッダ部分（Node.jsライセンス）
- `"""` または `===` で区切られたライセンスブロック
- 各ライブラリのライセンステキスト

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| stdout | RTF | 変換されたRTFドキュメント |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | 呼び出し元で指定（リダイレクト） |
| 出力先 | 標準出力 |
| 文字コード | ANSI（RTF標準） |
| フォント | Tahoma |

### RTF出力構造

```rtf
{\rtf1\ansi\ansicpg1252\uc1\deff0\deflang1033
{\fonttbl{\f0\fswiss\fcharset0 Tahoma;}}\fs20
{\*\generator txt2rtf 0.0.1;}
\pard\sa150\sl300\slmult1 {段落テキスト}\par
...
}
```

## 処理フロー

### 処理シーケンス

```
1. ストリーム初期化
   └─ 標準入力をUTF-8エンコーディングで設定
2. LineSplitter
   └─ 入力テキストを行に分割（CR/LF/CRLF対応）
3. ParagraphParser
   └─ 行を段落オブジェクトに変換
   └─ ライセンスブロック（"""で囲まれた部分）を検出
   └─ インデント、リスト項目を解析
4. Unwrapper
   └─ 自然な改行を保持しつつ不要な折り返しを解除
   └─ 短い行（50文字未満）は改行を保持
5. RtfGenerator
   └─ 段落オブジェクトをRTF形式に変換
   └─ ライセンスブロックは通常テキスト、それ以外は太字
   └─ 特殊文字のエスケープ処理
6. 出力
   └─ 変換されたRTFを標準出力に出力
```

### フローチャート

```mermaid
flowchart TD
    A[license2rtf.mjs開始] --> B[stdin設定]
    B --> C[pipeline開始]
    C --> D[LineSplitter]
    D --> E[テキストを行に分割]
    E --> F[ParagraphParser]
    F --> G{ブロック区切り?}
    G -->|=== or """| H[ブロック切り替え]
    G -->|No| I[行を段落に追加]
    H --> J[段落をemit]
    I --> J
    J --> K[Unwrapper]
    K --> L[折り返し解除]
    L --> M[RtfGenerator]
    M --> N[RTFヘッダ出力]
    N --> O[段落をRTF変換]
    O --> P{ライセンスブロック?}
    P -->|Yes| Q[通常テキスト]
    P -->|No| R[太字テキスト]
    Q --> S[特殊文字エスケープ]
    R --> S
    S --> T[RTF出力]
    T --> U[RTFフッタ出力]
    U --> V[終了]
```

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

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

本バッチはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 入力エラー | 標準入力なし | 空のRTFが出力される |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0回 |
| リトライ間隔 | N/A |
| リトライ対象エラー | なし |

### 障害時対応

- 入力ファイルのフォーマットを確認
- Node.jsのバージョンを確認（ESM対応が必要）

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1ファイル |
| 目標処理時間 | 1秒未満 |
| メモリ使用量上限 | 数MB |

## 排他制御

標準入出力を使用するため、排他制御は不要。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| なし | - | 標準的なログ出力は行わない |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 終了コード | 0以外 | 呼び出し元 |

## 備考

### Streamクラス一覧

| クラス名 | 役割 |
|---------|------|
| LineSplitter | 入力テキストを行に分割（CR/LF/CRLF対応） |
| ParagraphParser | 行を段落オブジェクトに変換、ライセンスブロック検出 |
| Unwrapper | 不要な折り返しを解除（50文字未満の行は保持） |
| RtfGenerator | 段落オブジェクトをRTF形式に変換 |

### RTFエスケープ処理

| 入力 | 出力 |
|-----|------|
| \\ | \\\\ |
| { | \\{ |
| } | \\} |
| タブ | \\tab |
| 0x00-0x1F, 0x7F-0xFF | \\'XX（16進） |
| BOM (U+FEFF) | 削除 |
| U+0100以上 | \\uXXXX? |

### 段落フォーマット

- ライセンスブロック外：太字（\\b ... \\b0）
- ライセンスブロック内：通常テキスト、右マージン240twips（\\ri240）
- リスト項目：タブでインデント（\\fi-240）
- 行間：300twips、段落後150twips

### 使用例

```bash
cat LICENSE | node tools/license2rtf.mjs > license.rtf
```

- node:stream/promisesのpipelineを使用したストリーム処理
- 各変換ステージはwritable Streamとして実装
- RTFコードページはANSI 1252（西ヨーロッパ）を使用
