# 機能設計書 18-HTML取得

## 概要

本ドキュメントは、EtherpadにおけるHTML取得機能（getHTML）の設計仕様を定義する。この機能は、指定されたパッドのコンテンツをHTML形式で取得するためのAPIを提供する。

### 本機能の処理概要

HTML取得機能は、パッドに保存されているテキストと書式情報をHTML形式に変換して取得する機能である。書式（太字、斜体、見出し、リスト等）が保持されたHTMLが生成される。特定のリビジョン番号を指定して過去の状態を取得することも可能。

**業務上の目的・背景**：
共同編集されたドキュメントを外部で利用する際、書式情報を保持したまま取得したい場合に使用される。Webページへの埋め込み、他のエディタへのコピー、HTMLメールの作成、ドキュメントのアーカイブなど、書式付きコンテンツが必要なユースケースに対応する。

**機能の利用シーン**：
- パッドの内容をWebページとして公開
- 他のエディタやCMSへのインポート
- HTMLメールの本文として利用
- ドキュメントのアーカイブ保存
- 過去リビジョンのHTML形式での確認

**主要な処理内容**：
1. 対象パッドの存在確認
2. リビジョン番号の指定確認（オプション）
3. 指定リビジョンまたは最新コンテンツの取得
4. ATextからHTMLへの変換処理
5. HTML形式での返却

**関連システム・外部連携**：
- REST API（GET /api/2/pads/html）を通じて外部システムから呼び出し可能
- ExportHtmlモジュールを使用してHTML変換

**権限による制御**：
- APIキーまたはOAuth2トークンによる認証が必要
- パッドの内容を取得できるため、機密情報へのアクセス制御を考慮

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はAPIのみで提供され、直接関連する画面はない |

## 機能種別

データ参照（Read操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| padID | string | Yes | HTMLを取得するパッドのID | 正規表現に一致、存在するパッドであること |
| rev | string/number | No | 取得するリビジョン番号（省略時は最新） | 整数、0以上かつhead以下 |

### 入力データソース

REST API経由でのHTTPリクエスト（GET /api/2/pads/html）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| code | number | 結果コード（0: 成功、1: エラー、4: 認証エラー） |
| message | string | 結果メッセージ（"ok" または エラーメッセージ） |
| data | object | HTMLを含むオブジェクト |
| data.html | string | パッドのHTMLコンテンツ（DOCTYPE付き完全HTML） |

### 出力先

HTTPレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. APIリクエスト受信
   └─ GET /api/2/pads/html?padID=xxx&rev=n
2. 認証チェック
   └─ APIキーまたはOAuth2トークンの検証
3. パラメータ抽出
   └─ padID, revの取得
4. リビジョン番号検証（指定時）
   └─ 整数変換、範囲チェック
5. パッド取得
   └─ getPadSafe(padID, true)
6. HTML生成
   └─ exportHtml.getPadHTML(pad, rev)
7. HTMLラッピング
   └─ DOCTYPE、html、body タグで囲む
8. レスポンス返却
   └─ {code: 0, message: "ok", data: {html: "..."}}
```

### フローチャート

```mermaid
flowchart TD
    A[開始: getHTML API呼び出し] --> B{認証チェック}
    B -->|失敗| C[401 Unauthorized]
    B -->|成功| D[パッド存在確認]
    D -->|存在しない| E[400 padID does not exist]
    D -->|存在する| F{rev指定あり?}
    F -->|Yes| G[リビジョン番号検証]
    G -->|不正| H[400 rev is higher than head]
    G -->|正常| I[getInternalRevisionAText]
    F -->|No| J[pad.atextから取得]
    I --> K[getHTMLFromAtext]
    J --> K
    K --> L[HTMLタグでラップ]
    L --> M[200 OK: html返却]
    M --> N[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-018-01 | 最新HTML | rev未指定時は最新のHTMLを返却 | revパラメータなし |
| BR-018-02 | 履歴アクセス | 指定されたリビジョンのHTMLを返却 | revパラメータあり |
| BR-018-03 | 範囲チェック | revがhead以上の場合はエラー | rev > headRevisionNumber |
| BR-018-04 | 完全HTML | DOCTYPE付きの完全なHTML文書を返却 | 常時 |
| BR-018-05 | 書式保持 | 太字、斜体、見出し、リスト等の書式を保持 | 常時 |

### 計算ロジック

HTML生成のフロー:
1. ATextから行ごとにテキストと属性を抽出
2. 属性に応じてHTMLタグ（strong、em、h1等）を生成
3. リスト構造を解析してol/ulタグを生成
4. URLを検出してaタグに変換
5. 全体をhtml/body タグでラップ

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 参照 | pad:{padID} | SELECT | パッドメタデータ取得 |
| 参照 | pad:{padID}:revs:{n} | SELECT | リビジョン情報取得（rev指定時） |

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

#### pad:{padID}

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | atext | 最新テキストと属性 | rev未指定時 |
| SELECT | pool | 属性プール | 属性→HTMLタグ変換に使用 |
| SELECT | head | 最新リビジョン番号 | 範囲チェック用 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | apierror | パッドが存在しない | 正しいパッドIDを指定 |
| 1 | apierror | revがhead以上 | 有効なリビジョン番号を指定 |
| 1 | apierror | revが数値でない | 整数を指定 |
| 4 | authError | 認証情報が無効 | 正しいAPIキーまたはトークンを使用 |

### リトライ仕様

データベース操作に関してはueberDB2のリトライ機構に依存。読み取り専用操作のため通常リトライは不要。

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

読み取り専用操作のため、トランザクション管理は不要。

## パフォーマンス要件

- パッドのサイズに比例した処理時間
- HTML変換処理は属性解析が必要なためテキスト取得より負荷が高い
- プラグインフックの呼び出しにより追加の処理時間が発生する可能性

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

- APIキーまたはOAuth2認証が必須
- 出力されるHTMLはサニタイズされている（XSS対策）
- 外部リンクにはrel="noreferrer noopener"が付与される

## 備考

- 出力されるHTMLはDOCTYPE付きの完全な文書形式
- プラグインによる追加タグ（exportHtmlAdditionalTags）がサポートされる
- URL自動リンク機能が含まれる
- リストの入れ子構造もサポートされる

---

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

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

### 推奨読解順序

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

パッドのHTML変換における内部構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ExportHtml.ts | `src/node/utils/ExportHtml.ts` | getPadHTML関数（34-44行目）、getHTMLFromAtext関数（46-477行目） |
| 1-2 | Pad.ts | `src/node/db/Pad.ts` | apool()メソッド（69-71行目） |

**読解のコツ**: getHTMLFromAtextがHTML変換の中核。属性プール（apool）を参照して属性→HTMLタグの変換を行う。

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

REST APIからの呼び出しフローを追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestAPI.ts | `src/node/handler/RestAPI.ts` | API定義（612-626行目でgetHTMLのマッピング） |
| 2-2 | APIHandler.ts | `src/node/handler/APIHandler.ts` | パラメータ定義（52行目でgetHTMLの引数） |

**主要処理フロー**:
1. **612-626行目**: GET /pads/html のルート定義
2. **52行目**: getHTMLの引数（padID, rev）

#### Step 3: ビジネスロジックを理解する

実際のHTML変換ロジックを読み解く。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | API.ts | `src/node/db/API.ts` | getHTML関数（252-274行目） |
| 3-2 | ExportHtml.ts | `src/node/utils/ExportHtml.ts` | getPadHTML関数（34-44行目） |
| 3-3 | ExportHtml.ts | `src/node/utils/ExportHtml.ts` | getHTMLFromAtext関数（46-477行目） |

**主要処理フロー**:
- **API.ts 253-255行目**: リビジョン番号のパース
- **API.ts 257行目**: パッド取得
- **API.ts 260-266行目**: リビジョン範囲チェック
- **API.ts 269行目**: exportHtml.getPadHTML呼び出し
- **API.ts 272行目**: DOCTYPE付きHTMLでラップ

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

```
GET /api/2/pads/html (RestAPI.ts)
    │
    └─ apiHandler.handle() (APIHandler.ts)
           │
           └─ api.getHTML() (API.ts:252-274)
                  │
                  ├─ checkValidRev(rev) (253-255行目)
                  │
                  ├─ getPadSafe(padID, true) (257行目)
                  │
                  └─ exportHtml.getPadHTML(pad, rev) (269行目)
                         │
                         ├─ [rev指定あり]
                         │      └─ pad.getInternalRevisionAText(rev)
                         │
                         └─ getHTMLFromAtext(pad, atext)
                                │
                                ├─ splitAttributionLines() (49行目)
                                ├─ _analyzeLine() (314行目)
                                ├─ getLineHTML() (128行目)
                                │      ├─ 属性→タグ変換
                                │      ├─ URL検出・リンク化
                                │      └─ HTMLエスケープ
                                └─ リスト構造生成 (312-459行目)
```

### データフロー図

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

padID         ───────▶ getPadSafe() ──────────────▶ Padオブジェクト
rev                          │
                             ▼
                    ┌─[rev指定あり]─────────────────────────┐
                    │                                       │
                    │  getInternalRevisionAText(rev)        │
                    │         │                             │
                    │         └─▶ AText復元                 │
                    │                                       │
                    └─[rev指定なし]─────────────────────────┘
                             │
                             ├─▶ pad.atext（最新）
                             │
                             ▼
                    getHTMLFromAtext()
                         │
                         ├─▶ 属性プール解析
                         │
                         ├─▶ 行ごとのHTML生成
                         │      ├─ タグ変換（strong,em,h1...）
                         │      ├─ URL検出・aタグ生成
                         │      └─ HTMLエスケープ
                         │
                         └─▶ リスト構造生成（ol/ul）
                             │
                             ▼
                    HTMLラッピング
                         │
                         └─▶ DOCTYPE + html + body
                             │
                             ▼
                    {html: "<!DOCTYPE HTML>..."} ─▶ JSON Response
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| API.ts | `src/node/db/API.ts` | ソース | getHTML関数の実装 |
| ExportHtml.ts | `src/node/utils/ExportHtml.ts` | ソース | getPadHTML、getHTMLFromAtext |
| ExportHelper.ts | `src/node/utils/ExportHelper.ts` | ソース | _analyzeLine、_encodeWhitespace |
| Pad.ts | `src/node/db/Pad.ts` | ソース | Padクラス、getInternalRevisionAText |
| RestAPI.ts | `src/node/handler/RestAPI.ts` | ソース | REST APIエンドポイント定義 |
| APIHandler.ts | `src/node/handler/APIHandler.ts` | ソース | API呼び出しハンドリング |
| Security.ts | `src/static/js/security.ts` | ソース | HTMLエスケープ処理 |
| pad_utils.ts | `src/static/js/pad_utils.ts` | ソース | URL検出処理 |
