# バッチ設計書 50-lint-md.mjs

## 概要

本ドキュメントは、Node.jsプロジェクトのMarkdownドキュメント（.mdファイル）に対してスタイルチェックを実行するNode.jsスクリプト `lint-md.mjs` の設計書です。

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

このバッチは、プロジェクト内のMarkdownファイルに対して、unified/remarkエコシステムを使用したリントチェックとフォーマットを実行します。

**業務上の目的・背景**：Node.jsプロジェクトには大量のドキュメント（APIドキュメント、ガイド、CHANGELOG等）が含まれています。Markdownドキュメントの品質と一貫性を維持することで、可読性とメンテナンス性が向上します。remark-preset-lint-nodeはNode.jsプロジェクト固有のルールセットを提供し、ドキュメントの品質を保証します。

**バッチの実行タイミング**：CI/CDパイプライン、開発者によるローカル実行、プレコミットフック等で実行されます。

**主要な処理内容**：
1. コマンドライン引数のパース（--formatオプション、対象パス）
2. 各Markdownファイルを読み込み
3. unified/remarkを使用してリントチェックを実行
4. doc/api/配下のファイルに対しては`introduced_in`バージョンの存在を確認
5. `--format`オプション使用時はファイルを自動フォーマット
6. エラー・警告をvfile-reporterで出力

**前後の処理との関連**：このスクリプトはMakefileから呼び出されます（`make lint-md`、`make format-md`）。CIパイプラインの一部として実行されることが多いです。

**影響範囲**：Markdownファイル（.md）のスタイルチェック結果、`--format`オプション使用時はファイルの自動フォーマット

## バッチ種別

コード品質

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時 |
| 実行時刻 | 任意 |
| 実行曜日 | 任意 |
| 実行日 | 任意 |
| トリガー | 手動 / CI/CD / プレコミットフック |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Node.js | スクリプト実行に必要 |
| npm依存関係 | unified、remark-parse、remark-stringify、remark-preset-lint-node、to-vfile、vfile-reporter |

### 実行可否判定

コマンドライン引数でMarkdownファイルのパスが指定されている場合に実行されます。パスが指定されていない場合はUsageメッセージを表示して終了します。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| path | 文字列 | Yes | - | チェック対象のMarkdownファイルパス（複数指定可） |
| --format | フラグ | No | false | 自動フォーマットモードを有効化 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| Markdownファイル | Text | チェック対象の.mdファイル |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| 標準出力 | Text | フォーマット差分に関するエラーメッセージ |
| 標準エラー出力 | Text | vfile-reporter形式のリント結果 |
| 終了コード | Integer | 0=成功、1=エラーあり |
| ファイル（--format時） | Text | 自動フォーマットされたMarkdownファイル |

### 出力ファイル仕様

`--format`オプション使用時のみファイルを変更します。

| 項目 | 内容 |
|-----|------|
| ファイル名 | 入力と同じ.mdファイル |
| 出力先 | 元のファイルパス |
| 文字コード | UTF-8 |
| 区切り文字 | N/A |

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数パース
   └─ parseArgsでオプションと位置引数を解析
2. 引数検証
   └─ パスが指定されていない場合はUsageを表示して終了
3. linterインスタンス作成
   └─ unified().use(remarkParse).use(presetLintNode).use(remarkStringify)
4. ファイルごとの処理ループ
   └─ 各ファイルに対して以下を実行
5. ファイル読み込み
   └─ to-vfileのread関数で読み込み
6. linter.process実行
   └─ remarkでパース、リント、stringify
7. 差分チェック
   └─ 元ファイルとprocessed結果を比較
8. introduced_inチェック（doc/api/のみ）
   └─ ファイル内に'introduced_in'が含まれているか確認
9. 結果処理
   └─ --format時: fs.writeFileSyncでファイルを上書き
   └─ 通常時: 差分があればエラー、messagesがあればvfile-reporterで出力
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[コマンドライン引数パース]
    B --> C{パス指定あり?}
    C -->|No| D[Usage表示して終了]
    C -->|Yes| E[linterインスタンス作成]
    E --> F[次のファイルを取得]
    F --> G[ファイル読み込み]
    G --> H[linter.process実行]
    H --> I{doc/api/配下?}
    I -->|Yes| J{introduced_inあり?}
    I -->|No| K[差分チェック]
    J -->|No| L[エラー報告]
    J -->|Yes| K
    L --> K
    K --> M{--format?}
    M -->|Yes| N{差分あり?}
    N -->|Yes| O[ファイル書き込み]
    N -->|No| P[スキップ]
    M -->|No| Q{差分あり?}
    Q -->|Yes| R[エラー報告]
    Q -->|No| S[messagesチェック]
    O --> T{次のファイルあり?}
    P --> T
    R --> S
    S --> U{messagesあり?}
    U -->|Yes| V[vfile-reporter出力]
    U -->|No| T
    V --> T
    T -->|Yes| F
    T -->|No| W[バッチ終了]
```

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

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

本バッチはデータベース操作を行いません。

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| N/A | N/A | N/A | データベース操作なし |

### テーブル別操作詳細

N/A

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | Lint Error | remarkがスタイル違反を検出 | --formatで自動修正するか、手動で修正 |
| 1 | Format Error | ファイルがフォーマットされていない | `make format-md`または`vcbuild format-md`で修正 |
| 1 | Missing introduced_in | doc/api/配下でintroduced_inがない | introduced_inバージョンを追加 |
| 1 | No Path | パスが指定されていない | 対象ファイルパスを指定 |

### リトライ仕様

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

### 障害時対応

1. フォーマットエラーは`make format-md`で自動修正可能
2. リントエラーは手動で修正
3. エラー詳細は標準エラー出力（vfile-reporter形式）に出力

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A（--format時はファイル単位） |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 数百ファイル |
| 目標処理時間 | 1分以内 |
| メモリ使用量上限 | 特になし |

## 排他制御

`--format`オプション使用時は同一ファイルへの同時アクセスを避ける必要があります。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| エラーログ | フォーマット差分時 | "{path} is not formatted. Please run '{cmd} format-md'." |
| エラーログ | introduced_in不足時 | "{path} is missing an 'introduced_in' version. Please add one." |
| リントログ | メッセージあり時 | vfile-reporter形式のリント結果 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| エラー件数 | 0件以上 | CI/CDログ |
| 処理時間 | 5分 | CI/CDタイムアウト |

## 備考

- 使用ライブラリ:
  - unified - 統一されたテキスト処理パイプライン
  - remark-parse - MarkdownからASTへのパース
  - remark-stringify - ASTからMarkdownへの変換
  - remark-preset-lint-node - Node.js固有のリントルールセット
  - to-vfile - ファイル読み込みユーティリティ
  - vfile-reporter - エラー/警告レポート出力
- doc/api/配下のファイルには`introduced_in`バージョンが必須です
- プラットフォームによって修正コマンドが異なります:
  - Windows: `vcbuild format-md`
  - Unix系: `make format-md`
- 非同期処理（async/await）でファイルを並列処理します
- `--format`オプションは差分がある場合のみファイルを書き込みます
