# 機能設計書 86-ノートブックレンダラー

## 概要

本ドキュメントは、VS Codeの「ノートブックレンダラー（notebook-renderers）」機能の設計内容を記載する。Jupyter Notebookなどのノートブック出力（画像、HTML、テキスト、エラー等）をWebview内でレンダリングする。

### 本機能の処理概要

builtin-notebook-renderers拡張機能は、ノートブックセルの出力をMIMEタイプに応じて適切にレンダリングする。画像、HTML、JavaScript、プレーンテキスト、エラースタックトレースなど、様々な出力形式に対応する。

**業務上の目的・背景**：Jupyter Notebookをはじめとするノートブック形式のドキュメントでは、コード実行結果を様々な形式（グラフ、表、テキストなど）で表示する必要がある。本機能は、これらの出力を適切にレンダリングし、インタラクティブなデータ分析環境を提供する。

**機能の利用シーン**：
- Pythonコードを実行して生成されたmatplotlibグラフを表示
- pandasのDataFrameをHTML表として表示
- エラー発生時のスタックトレースを見やすく整形表示

**主要な処理内容**：
1. MIMEタイプに基づく出力タイプ判定
2. 画像（PNG、JPEG、GIF、SVG）のレンダリング
3. HTML/JavaScriptコンテンツの実行とレンダリング
4. エラースタックトレースのフォーマットと表示
5. ストリーム出力（stdout/stderr）のスクロール対応表示

**関連システム・外部連携**：VS Codeノートブックシステム、Webview API

**権限による制御**：信頼されていないワークスペースでもサポート（ただしHTML/JSは信頼時のみ実行）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | エディタ領域 | 主画面 | ノートブックセル出力の表示 |

## 機能種別

コンテンツレンダリング / Webview表示

## 入力仕様

### 入力パラメータ

サポートするMIMEタイプ：

| MIMEタイプ | 説明 | レンダリング方式 |
|-----------|------|-----------------|
| image/gif | GIF画像 | renderImage |
| image/png | PNG画像 | renderImage |
| image/jpeg | JPEG画像 | renderImage |
| image/svg+xml | SVGベクター画像 | renderHTML |
| text/html | HTMLコンテンツ | renderHTML |
| application/javascript | JavaScriptコード | renderJavascript |
| application/vnd.code.notebook.error | エラー情報 | renderError |
| application/vnd.code.notebook.stdout | 標準出力 | renderStream |
| application/vnd.code.notebook.stderr | 標準エラー出力 | renderStream |
| text/plain | プレーンテキスト | renderText |

### 入力データソース

- ノートブックセルの出力データ（OutputItem）
- レンダラーコンテキスト（RendererContext）
- 出力メタデータ（alt_text等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| element | HTMLElement | レンダリングされたDOM要素 |
| disposable | IDisposable | リソース解放用ハンドラ |

### 出力先

ノートブックセルのWebview領域

## 処理フロー

### 処理シーケンス

```
1. セル実行完了
   └─ 出力データが生成される

2. レンダラー呼び出し
   └─ MIMEタイプに基づきレンダラー選択

3. 出力タイプ判定
   └─ switch文でMIMEタイプ分岐

4. レンダリング処理
   ├─ 画像: Blob URL作成、img要素生成
   ├─ HTML: innerHTML設定、script実行
   ├─ JavaScript: script要素作成、モジュール実行
   ├─ エラー: スタックトレースフォーマット
   └─ ストリーム: ANSIカラー対応、スクロール可能

5. DOM挿入
   └─ コンテナ要素に追加

6. イベント登録
   └─ スクロール、設定変更リスナー
```

### フローチャート

```mermaid
flowchart TD
    A[セル出力発生] --> B{MIMEタイプ判定}
    B -->|image/*| C[renderImage]
    B -->|text/html, svg| D{信頼済み?}
    B -->|application/javascript| E{信頼済み?}
    B -->|error| F[renderError]
    B -->|stdout/stderr| G[renderStream]
    B -->|text/plain| H[renderText]
    D -->|Yes| I[renderHTML]
    D -->|No| J[スキップ]
    E -->|Yes| K[renderJavascript]
    E -->|No| J
    C --> L[Blob URL作成]
    L --> M[img要素生成]
    I --> N[innerHTML設定]
    N --> O[domEval - script実行]
    K --> P[script要素作成]
    P --> Q[モジュールとして実行]
    F --> R[スタックトレースフォーマット]
    R --> S[ミニマルエラー表示]
    G --> T[ANSIカラー処理]
    T --> U[スクロール可能コンテナ]
    H --> V[テキスト表示]
    M --> W[DOM挿入]
    O --> W
    Q --> W
    S --> W
    U --> W
    V --> W
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-86-1 | 信頼チェック | HTML/JSは信頼済みワークスペースでのみ実行 | text/html, application/javascript |
| BR-86-2 | 画像altテキスト | メタデータのvscode_altTextを使用 | image/* |
| BR-86-3 | スクロール設定 | outputScrollingメタデータで制御 | ストリーム/テキスト |
| BR-86-4 | ミニマルエラー | minimalErrorモードで折りたたみ表示 | エラー出力 |
| BR-86-5 | SVG特別処理 | SVGにタイトル要素追加（アクセシビリティ） | image/svg+xml |

### レンダリング優先順位

1. 出力メタデータのscrollable設定を優先
2. グローバル設定のoutputScrollingをフォールバック

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 警告 | 信頼されていないワークスペースでHTML/JS | 空の出力（スキップ） |
| - | 情報 | エラー出力のJSON解析失敗 | スキップ |

### リトライ仕様

リトライは行わない。出力データが更新された場合は再レンダリング。

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

該当なし

## パフォーマンス要件

- 画像はBlob URLを使用してメモリ効率化
- 画像URL解放（revokeObjectURL）で適切なリソース管理
- ストリーム出力の追記モードで効率的な更新

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

- 信頼されていないワークスペースではHTML/JS実行を無効化
- Trusted Typesポリシー（ttPolicy）を使用してXSS対策
- CSP（Content Security Policy）によるスクリプト制限

## 備考

- ANSIエスケープシーケンスをHTMLに変換してカラー表示
- ワードラップ設定に対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | package.json | `extensions/notebook-renderers/package.json` | notebookRenderer定義とmimeTypes（18-41行目） |
| 1-2 | rendererTypes.ts | `extensions/notebook-renderers/src/rendererTypes.ts` | RenderOptions、IDisposableインターフェース |

**読解のコツ**: package.jsonのcontributes.notebookRendererでサポートするMIMEタイプを確認。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `extensions/notebook-renderers/src/index.ts` | activate関数（419-639行目） |

**主要処理フロー**:
1. **419-424行目**: disposables、htmlHooks、jsHooksの初期化
2. **426-538行目**: スタイル定義の挿入
3. **540-614行目**: renderOutputItem関数でMIMEタイプ分岐
4. **615-621行目**: disposeOutputItem関数

#### Step 3: 各レンダリング関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `extensions/notebook-renderers/src/index.ts` | renderImage（18-52行目） |
| 3-2 | index.ts | `extensions/notebook-renderers/src/index.ts` | renderHTML（107-124行目） |
| 3-3 | index.ts | `extensions/notebook-renderers/src/index.ts` | renderError（167-224行目） |
| 3-4 | index.ts | `extensions/notebook-renderers/src/index.ts` | renderStream（350-396行目） |

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

```
activate() [419行目]
    │
    └─ return { renderOutputItem, disposeOutputItem, ... }
           │
           └─ renderOutputItem() [541行目]
                  │
                  ├─ switch(outputInfo.mime)
                  │      │
                  │      ├─ 'text/html' / 'image/svg+xml'
                  │      │      └─ renderHTML() [107行目]
                  │      │             ├─ ttPolicy.createHTML() [111行目]
                  │      │             ├─ fixUpSvgElement() [113行目]
                  │      │             └─ domEval() [123行目]
                  │      │
                  │      ├─ 'application/javascript'
                  │      │      └─ renderJavascript() [126行目]
                  │      │
                  │      ├─ 'image/gif' / 'image/png' / 'image/jpeg'
                  │      │      └─ renderImage() [18行目]
                  │      │             ├─ new Blob() [19行目]
                  │      │             ├─ URL.createObjectURL() [20行目]
                  │      │             └─ image.src = src [36行目]
                  │      │
                  │      ├─ 'application/vnd.code.notebook.error'
                  │      │      └─ renderError() [167行目]
                  │      │             ├─ JSON.parse() [181行目]
                  │      │             └─ formatStackTrace() [193行目]
                  │      │
                  │      ├─ 'stdout' / 'stderr'
                  │      │      └─ renderStream() [350行目]
                  │      │             └─ createOutputContent() [366行目]
                  │      │
                  │      └─ 'text/plain'
                  │             └─ renderText() [398行目]
                  │
                  └─ disposeOutputItem() [615行目]
                         └─ disposables.get(id)?.dispose()
```

### データフロー図

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

OutputItem           ──▶ renderOutputItem()
(data, mime)               │
                           ▼
                      switch(mime) [543行目]
                           │
    ┌──────────────────────┼──────────────────────┐
    ▼                      ▼                      ▼
image/*              text/html              vnd.code.notebook.error
    │                      │                      │
    ▼                      ▼                      ▼
new Blob()           ttPolicy.createHTML()   JSON.parse()
    │                      │                      │
    ▼                      ▼                      ▼
createObjectURL()    innerHTML設定           formatStackTrace()
    │                      │                      │
    ▼                      ▼                      ▼
<img src="...">      domEval() - script実行  createOutputContent()
    │                      │                      │
    └──────────────────────┼──────────────────────┘
                           ▼
                      element.appendChild()  ──▶ DOM挿入
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `extensions/notebook-renderers/src/index.ts` | ソース | メインレンダリングロジック |
| textHelper.ts | `extensions/notebook-renderers/src/textHelper.ts` | ソース | テキスト出力ヘルパー、ANSIカラー |
| htmlHelper.ts | `extensions/notebook-renderers/src/htmlHelper.ts` | ソース | Trusted Typesポリシー |
| stackTraceHelper.ts | `extensions/notebook-renderers/src/stackTraceHelper.ts` | ソース | スタックトレースフォーマット |
| rendererTypes.ts | `extensions/notebook-renderers/src/rendererTypes.ts` | ソース | 型定義 |
| package.json | `extensions/notebook-renderers/package.json` | 設定 | マニフェスト、MIMEタイプ定義 |
