# 機能設計書 22-編集プレビュー

## 概要

本ドキュメントは、Wikipedia iOSアプリケーションにおける編集プレビュー機能の設計を記載する。この機能により、ユーザーは編集したウィキテキストがレンダリングされた状態を保存前に確認できる。

### 本機能の処理概要

編集プレビュー機能は、ユーザーが入力したウィキテキストをモバイルHTML形式に変換し、実際の記事表示に近い形でプレビューを表示する。

**業務上の目的・背景**：ウィキテキストは複雑なマークアップ言語であり、編集結果が意図通りに表示されるかを保存前に確認することは重要である。プレビュー機能により、誤った編集を未然に防ぎ、記事品質の維持に貢献する。

**機能の利用シーン**：ユーザーがエディタで編集を完了し、次へ進む際に使用される。特に複雑な書式やリンク、テンプレートを含む編集では、レンダリング結果の確認が重要となる。

**主要な処理内容**：
1. 編集されたウィキテキストをMediaWiki APIに送信
2. APIからモバイルHTML形式のプレビューを取得
3. WebViewでプレビューコンテンツを表示
4. リンク（内部・外部）のタップ時にアラート表示
5. 参照（Reference）のポップアップ表示
6. 記事と同様のテーマ・マージン設定を適用

**関連システム・外部連携**：MediaWiki REST API（wikitext-to-mobilehtml変換）、ArticleWebMessagingController（WebView通信）

**権限による制御**：編集権限のあるユーザーのみがプレビュー画面に到達可能（エディタで事前にチェック済み）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | エディタ画面 | 呼び出し元 | 進むボタンタップで遷移 |
| - | プレビュー画面 | 主画面 | 編集結果のプレビュー表示 |
| - | 保存画面 | 遷移先 | 次へボタンタップで遷移 |
| - | リンクプレビューアラート | モーダル | 内部/外部リンクの情報表示 |
| - | 参照ポップオーバー | ポップオーバー | 参照情報の表示 |

## 機能種別

データ変換処理、WebView表示、UI制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| pageURL | URL | Yes | プレビュー対象の記事URL | 有効なWikipedia記事URL |
| sectionID | Int? | No | 編集対象のセクションID | nil（全体）または0以上の整数 |
| languageCode | String? | No | 言語コード | 有効な言語コード |
| wikitext | String | Yes | プレビュー対象のウィキテキスト | 空文字列も許可 |
| needsNextButton | Bool | Yes | 次へボタン表示フラグ | true/false |
| needsSimplifiedFormatToast | Bool | Yes | 簡略化形式トースト表示フラグ | true/false |

### 入力データソース

- EditorViewController（編集済みウィキテキスト）
- MediaWiki REST API（プレビューHTML）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| renderedPreview | HTML | レンダリングされたプレビューコンテンツ |

### 出力先

- PreviewWebViewContainer（WebView表示）
- EditSaveViewController（次へボタンタップ時の遷移先）
- EditPreviewViewControllerDelegate（遷移通知）

## 処理フロー

### 処理シーケンス

```
1. プレビュー画面の初期化
   └─ PreviewWebViewContainerのセットアップ

2. viewWillAppear
   └─ loadPreviewIfNecessary()の呼び出し

3. プレビュー読み込み
   ├─ ArticleWebMessagingControllerのセットアップ
   ├─ 読み込み中アラートの表示
   └─ wikitext-to-mobilehtml APIリクエスト

4. プレビュー表示
   ├─ 環境判定（production/local/staging）
   ├─ HTMLコンテンツのWebView読み込み
   └─ 簡略化形式トースト表示（必要時）

5. ユーザー操作
   ├─ リンクタップ：内部/外部リンクアラート表示
   ├─ 参照タップ：参照ポップオーバー表示
   └─ 次へボタン：保存画面への遷移
```

### フローチャート

```mermaid
flowchart TD
    A[プレビュー開始] --> B[WebView準備]
    B --> C[MessagingController設定]
    C --> D[読み込みアラート表示]
    D --> E{環境判定}
    E -->|Production| F[REST API直接リクエスト]
    E -->|Local/Staging| G[分割リクエスト処理]
    F --> H[WebView読み込み]
    G --> H
    H --> I{簡略化トースト必要?}
    I -->|Yes| J[トースト表示]
    I -->|No| K[プレビュー表示完了]
    J --> K
    K --> L{ユーザー操作}
    L -->|リンクタップ| M[リンクアラート]
    L -->|参照タップ| N[参照ポップオーバー]
    L -->|次へ| O[保存画面遷移]
    L -->|戻る| P[エディタに戻る]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | プレビュー一回性 | 一度読み込んだプレビューは再読み込みしない | viewWillAppear時にhasPreviewed確認 |
| BR-002 | 外部リンク警告 | 外部サイトへのリンクはアラートで表示 | リンクホストがページホストと異なる場合 |
| BR-003 | 内部リンクプレビュー | 内部リンクはコンテキストメニューでプレビュー可能 | リンクホストがページホストと一致する場合 |
| BR-004 | 次へボタン表示制御 | 編集フローに応じて次へボタンの表示を制御 | needsNextButton設定に従う |
| BR-005 | 簡略化形式通知 | トークページプレビュー時に簡略化形式を通知 | needsSimplifiedFormatToast=true時 |

### 計算ロジック

該当なし

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

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| networkError | 接続エラー | ネットワーク接続なし | 汎用エラー表示 |
| fetchError | 取得エラー | APIからのHTML取得失敗 | showGenericError()呼び出し |
| webViewError | 表示エラー | WebViewでのHTML読み込み失敗 | showError(error)呼び出し |

### リトライ仕様

自動リトライは行わない。ユーザーが戻って再度プレビューを試行する必要がある。

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

該当なし（読み取り専用操作）

## パフォーマンス要件

- プレビューHTML取得：ウィキテキストの複雑さに依存（通常5秒以内を想定）
- WebView読み込み：HTML受信後1秒以内

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

- 外部リンクはアラートで表示し、直接遷移しない
- WebViewのコンテンツはMediaWiki APIから取得した信頼されたHTMLのみ

## 備考

- PCS（Page Content Service）の環境（production/local/staging）に応じて異なるAPI呼び出しパスを使用
- Local/Staging環境では、wikitext-to-htmlとhtml-to-mobilehtmlの2段階リクエストが必要

---

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

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

### 推奨読解順序

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

プレビュー画面で使用されるプロパティと設定を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | EditPreviewViewController.swift | `Wikipedia/Code/EditPreviewViewController.swift` | プロパティ定義（L16-24） |

**読解のコツ**: needsNextButtonとneedsSimplifiedFormatToastは編集フローに応じた表示制御に使用される。

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

エディタからのプレビュー画面遷移を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | EditorViewController.swift | `Wikipedia/Code/EditorViewController.swift` | showEditPreview（L652-673） |

**主要処理フロー**:
1. **L652-656**: sourceEditorの存在確認
2. **L658-663**: EditPreviewViewControllerの初期化
3. **L664-671**: 編集フローに応じたneedsNextButton/needsSimplifiedFormatToast設定
4. **L672**: ナビゲーションプッシュ

#### Step 3: ライフサイクルを理解する

プレビュー画面の初期化と表示処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | EditPreviewViewController.swift | `Wikipedia/Code/EditPreviewViewController.swift` | viewDidLoad, viewWillAppear（L91-107） |

**主要処理フロー**:
- **L91-100**: viewDidLoad - PreviewWebViewContainerの設定
- **L102-107**: viewWillAppear - プレビュー読み込みとナビゲーションバー設定

#### Step 4: プレビュー読み込み処理を理解する

wikitext-to-mobilehtml変換処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | EditPreviewViewController.swift | `Wikipedia/Code/EditPreviewViewController.swift` | loadPreviewIfNecessary（L140-208） |

**主要処理フロー**:
- **L140-144**: hasPreviewed確認で二重読み込み防止
- **L145**: ArticleWebMessagingControllerのセットアップ
- **L146**: 読み込み中アラート表示
- **L148-171**: pcsLocalAndStagingEnvironmentsCompletion - Local/Staging環境用の分割処理
- **L173-185**: pcsProductionCompletion - Production環境用の直接リクエスト
- **L187-207**: 環境に応じた処理分岐

#### Step 5: リンク・参照ハンドリングを理解する

WebViewからのアクション処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | EditPreviewViewController.swift | `Wikipedia/Code/EditPreviewViewController.swift` | didReceive(action:)（L247-273） |

**主要処理フロー**:
- **L249-250**: unknown - 外部リンクアラート表示
- **L251-252**: backLink - 参照バックリンク表示
- **L253-254**: reference - 参照ポップオーバー表示
- **L255-267**: link - 内部/外部リンクの判定と処理

#### Step 6: デリゲート実装を理解する

プレビューからの遷移処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | EditPreviewViewController.swift | `Wikipedia/Code/EditPreviewViewController.swift` | goForward（L86-89） |
| 6-2 | EditorViewController.swift | `Wikipedia/Code/EditorViewController.swift` | EditPreviewViewControllerDelegate実装（L999-1018） |

**主要処理フロー**:
- **L86-89**: goForward - デリゲートへの通知
- **L1000-1017**: editPreviewViewControllerDidTapNext - 保存画面への遷移

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

```
EditorViewController
    │
    └─ showEditPreview(editFlow:)
           │
           └─ EditPreviewViewController.init(pageURL:)
                  │
                  ├─ viewDidLoad()
                  │      └─ PreviewWebViewContainer設定
                  │
                  ├─ viewWillAppear()
                  │      ├─ loadPreviewIfNecessary()
                  │      │      ├─ ArticleWebMessagingController.setup()
                  │      │      └─ ArticleFetcher.wikitextToMobileHTMLPreviewRequest()
                  │      │             または
                  │      │             ArticleFetcher.fetchMobileHTMLFromWikitext()
                  │      │
                  │      └─ configureNavigationBar()
                  │
                  └─ goForward()
                         └─ delegate.editPreviewViewControllerDidTapNext()
                                └─ showEditSave() → EditSaveViewController
```

### データフロー図

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

wikitext (String)     ───▶ ArticleFetcher                   ───▶ WebView
                              │
                              ├─ wikitextToMobileHTMLPreviewRequest()
                              │         (Production)
                              │
                              └─ fetchMobileHTMLFromWikitext()
                                        (Local/Staging)
                                               │
                                               ▼
                                    PreviewWebViewContainer
                                               │
                                    ┌──────────┼──────────┐
                                    ▼          ▼          ▼
                              リンクタップ   参照タップ   次へタップ
                                    │          │          │
                                    ▼          ▼          ▼
                              アラート表示  ポップオーバー  保存画面
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| EditPreviewViewController.swift | `Wikipedia/Code/EditPreviewViewController.swift` | ソース | プレビュー画面メインコントローラー |
| EditorViewController.swift | `Wikipedia/Code/EditorViewController.swift` | ソース | プレビュー画面への遷移とデリゲート実装 |
| PreviewWebViewContainer.swift | `Wikipedia/Code/PreviewWebViewContainer.swift` | ソース | プレビュー用WebViewコンテナ |
| ArticleWebMessagingController.swift | `Wikipedia/Code/ArticleWebMessagingController.swift` | ソース | WebViewとのJavaScript通信 |
| ArticleFetcher.swift | `WMF Framework/` | ソース | wikitext-to-mobilehtml変換API呼び出し |
| ReferenceViewController.swift | `Wikipedia/Code/ReferenceViewController.swift` | ソース | 参照ポップオーバー表示 |
| ReferenceBackLinksViewController.swift | `Wikipedia/Code/ReferenceBackLinksViewController.swift` | ソース | 参照バックリンク表示 |
