# 機能設計書 3-目次表示

## 概要

本ドキュメントは、Wikipedia iOSアプリにおける目次表示機能の設計仕様を記述する。記事のセクション一覧を表示し、セクション間のナビゲーションを提供する。

### 本機能の処理概要

**業務上の目的・背景**：長い記事を効率的に閲覧するため、記事の構造（セクション一覧）を視覚的に把握し、任意のセクションへ素早くジャンプできる機能を提供する。特に数十セクションを持つ長大な記事で有用。iPadでは常時表示（インライン）、iPhoneではモーダル表示と、デバイス特性に応じた表示モードを切り替える。

**機能の利用シーン**：
- 記事画面のツールバーから目次ボタンをタップした時
- iPadの横向き表示で目次を常時表示したい時
- 記事の特定セクションへ素早くジャンプしたい時
- 記事の全体構造を把握したい時

**主要な処理内容**：
1. 記事HTMLから目次項目（TableOfContentsItem）を抽出
2. TableOfContentsViewControllerで目次リストを表示
3. インラインモード（iPad）/ モーダルモード（iPhone）の切り替え
4. セクション選択時のWebViewスクロール
5. 現在表示中セクションのハイライト
6. RTL言語対応（右から左への表示）

**関連システム・外部連携**：
- ArticleViewController（親ビューコントローラー）
- WKWebView（スクロール位置の取得・設定）
- JavaScript（セクション位置の取得）

**権限による制御**：
- 特別な権限は不要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | TableOfContents画面 | 主画面 | 目次リストの表示、セクションナビゲーション |
| 5 | Article画面 | 親画面 | 目次表示のトリガー、セクションスクロール |

## 機能種別

表示処理 / ナビゲーション / インタラクション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| delegate | TableOfContentsViewControllerDelegate | Yes | デリゲートオブジェクト | nil不可 |
| theme | Theme | Yes | 適用するテーマ | 有効なThemeオブジェクト |
| displaySide | TableOfContentsDisplaySide | Yes | 表示位置（左/右） | .left または .right |

### 入力データソース

- ArticleViewController.tableOfContentsItems（目次項目配列）
- JavaScript wmf.elementLocation.getFirstOnScreenSection（現在表示セクション）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 選択されたセクション | TableOfContentsItem | ユーザーが選択した目次項目 |
| 表示状態 | Bool | 目次の表示/非表示状態 |

### 出力先

- TableOfContentsViewControllerDelegate（選択結果のコールバック）
- UserDefaults（インライン表示状態の永続化）

## 処理フロー

### 処理シーケンス

```
1. TableOfContentsViewController初期化
   └─ delegate、theme、displaySideを受け取り初期化
   └─ modalPresentationStyle = .customを設定
   └─ TableOfContentsAnimatorを遅延初期化

2. viewDidLoad
   └─ UITableView（grouped style）をセットアップ
   └─ TableOfContentsCellを登録
   └─ スワイプジェスチャーを設定（閉じる用）
   └─ テーマを適用

3. viewWillAppear
   └─ delegate?.tableOfContentsControllerWillDisplayを呼び出し

4. セクション選択
   └─ tableView:didSelectRowAtでセクション選択検出
   └─ selectItem(at:)でハイライト更新
   └─ delegate?.tableOfContentsController:didSelectItemでコールバック

5. 閉じる操作
   └─ スワイプジェスチャーまたはタップで閉じる
   └─ delegate?.tableOfContentsControllerDidCancelを呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[目次ボタンタップ] --> B{displayMode}
    B -->|inline| C[showInline]
    B -->|modal| D[showModal]
    C --> E[inlineContainerView表示]
    D --> F[モーダルpresent]
    E --> G[目次表示完了]
    F --> G
    G --> H{ユーザーアクション}
    H -->|セクションタップ| I[selectItem]
    H -->|スワイプ/タップ| J[hide]
    I --> K[delegate.didSelectItem]
    K --> L[WebViewスクロール]
    J --> M[目次非表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 表示モード切替 | compact環境ではモーダル、regular環境ではインライン | traitCollection.horizontalSizeClass |
| BR-002 | 選択状態保持 | 選択されたセクションをハイライト表示 | セクション選択時 |
| BR-003 | 親子ハイライト | 選択セクションの親/子もハイライト | shouldBeHighlightedAlongWithItem |
| BR-004 | インライン状態永続化 | インライン表示状態をUserDefaultsに保存 | インライン表示ON/OFF時 |
| BR-005 | RTL対応 | RTL言語の場合は右側に表示 | tableOfContentsSemanticContentAttribute |

### 計算ロジック

- インデントレベル: `indentationLevel < 1 ? .primary : .secondary`
- 表示側判定: `semanticContentAttribute == .forceRightToLeft ? .right : .left`

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

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

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

### UserDefaults操作

| キー | 操作 | 値 |
|-----|------|-----|
| wmf_isTableOfContentsVisibleInline | READ/WRITE | Bool |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 範囲外アクセス | 無効なインデックスでの選択 | assertionFailureでデバッグ検出、ガード文で保護 |

### リトライ仕様

- 特別なリトライ処理なし

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

- トランザクション処理なし

## パフォーマンス要件

- 目次表示までの目標時間：0.3秒以内
- スクロールは60fpsを維持

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

- 特別なセキュリティ要件なし

## 備考

- VoiceOver対応：選択セルにaccessibilityTraits = .selectedを設定
- アクセシビリティエスケープ：Escapeジェスチャーで閉じる対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | TableOfContentsItem.swift | `Wikipedia/Code/TableOfContentsItem.swift` | 目次項目のデータ構造 |

**主要コード**:
- **5-17行目**: `TableOfContentsItemType` enum - primary/secondaryの種別
- **26-43行目**: `TableOfContentsItem` struct - id、titleHTML、anchor、rootItemId、indentationLevel

**読解のコツ**: `indentationLevel`がセクションの階層を表す。0がトップレベル、1以上がサブセクション。

#### Step 2: 表示制御を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ArticleTableOfContentsDisplayController.swift | `Wikipedia/Code/ArticleTableOfContentsDisplayController.swift` | 表示モードの管理 |

**主要処理フロー**:
- **70-86行目**: `show(animated:)` / `hide(animated:)` - 表示モードに応じた表示/非表示
- **88-109行目**: `showModal(animated:)` - モーダル表示、現在セクションを選択してからpresent
- **116-122行目**: `showInline()` - インライン表示、UserDefaultsに状態保存
- **132-144行目**: `setup(with:)` / `update(with:)` - traitCollectionに応じたモード切替
- **159-204行目**: `setupTableOfContentsViewController()` - ViewControllerの再作成と配置

#### Step 3: メインViewControllerを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TableOfContentsViewController.swift | `Wikipedia/Code/TableOfContentsViewController.swift` | 目次のメインViewController |

**主要処理フロー**:
- **95-106行目**: `init` - 初期化、displaySide設定
- **113-152行目**: `selectItem(at:)` - セクション選択とハイライト更新
- **154-168行目**: `scrollToItem(at:)` - 選択セクションへのスクロール
- **178-215行目**: `viewDidLoad` - TableViewセットアップ、スワイプジェスチャー設定
- **232-263行目**: `cellForRowAt` - セル構成、ハイライト状態適用
- **281-286行目**: `didSelectRowAt` - セクション選択処理

#### Step 4: ArticleViewControllerとの連携を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ArticleViewController+TableOfContents.swift | `Wikipedia/Code/ArticleViewController+TableOfContents.swift` | 目次機能の拡張 |

**主要処理フロー**:
- **4-17行目**: `getVisibleSection` - JSで現在表示セクションを取得
- **27-33行目**: `showTableOfContents` / `hideTableOfContents` - 表示/非表示
- **51-71行目**: `tableOfContentsController:didSelectItem` - セクション選択時のスクロール処理

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

```
ArticleViewController
    │
    ├─ tableOfContentsController (ArticleTableOfContentsDisplayController)
    │      │
    │      ├─ viewController (TableOfContentsViewController)
    │      │      ├─ UITableView
    │      │      │      └─ TableOfContentsCell
    │      │      │
    │      │      ├─ TableOfContentsAnimator (モーダル時)
    │      │      │      └─ TableOfContentsPresentationController
    │      │      │
    │      │      └─ TableOfContentsHeader
    │      │
    │      ├─ stackView (インライン配置用)
    │      │      ├─ inlineContainerView
    │      │      ├─ separatorView
    │      │      └─ articleView (WKWebView)
    │      │
    │      └─ show() / hide()
    │
    └─ tableOfContentsItems: [TableOfContentsItem]
           (ArticleのtableOfContentsItemsから取得)
```

### データフロー図

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

Article HTML ───────────▶ tableOfContentsItems抽出
                               │
                               ▼
                         TableOfContentsItem配列
                               │
                               ▼
                         TableOfContentsViewController
                               │
                               ├─ TableView表示
                               │
                               ▼
ユーザー選択 ───────────▶ selectItem(at:)
                               │
                               ▼
                         delegate.didSelectItem
                               │
                               ▼
                         WebView.scroll(to: anchor)
                               │
                               ▼
                         [セクション表示]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TableOfContentsViewController.swift | `Wikipedia/Code/` | ソース | 目次メインViewController |
| TableOfContentsItem.swift | `Wikipedia/Code/` | ソース | 目次項目データ構造 |
| ArticleTableOfContentsDisplayController.swift | `Wikipedia/Code/` | ソース | 表示モード管理 |
| ArticleViewController+TableOfContents.swift | `Wikipedia/Code/` | ソース | ArticleVCの目次拡張 |
| TableOfContentsCell.swift | `Wikipedia/Code/` | ソース | 目次セルUI |
| TableOfContentsHeader.swift | `Wikipedia/Code/` | ソース | 目次ヘッダーUI |
| TableOfContentsAnimator.swift | `Wikipedia/Code/` | ソース | モーダルアニメーション |
| TableOfContentsPresentationController.swift | `Wikipedia/Code/` | ソース | モーダル表示制御 |
| TableOfContentsCell.xib | `Wikipedia/Code/` | リソース | セルレイアウト |
| TableOfContentsHeader.xib | `Wikipedia/Code/` | リソース | ヘッダーレイアウト |
