# 帳票設計書 10-Markdown Document Renderer

## 概要

本ドキュメントは、VS CodeのMarkdownドキュメントレンダリング機能における帳票出力仕様を定義するものである。この機能は拡張機能のREADME、Webビュー内のMarkdownコンテンツ等をHTML形式でレンダリングする。

### 本帳票の処理概要

Markdown Document Rendererは、Markdown形式のテキストをHTML形式に変換し、VS Codeのシンタックスハイライトを適用したコードブロック付きで表示する機能である。

**業務上の目的・背景**：拡張機能のドキュメント表示、Webビュー内のMarkdownコンテンツ表示、リリースノート表示等に使用される。VS Codeのテーマに適合したスタイリングとセキュアなHTML出力を提供する。

**帳票の利用シーン**：
- 拡張機能マーケットプレイスでのREADME表示
- Webビュー内でのMarkdownコンテンツ表示
- リリースノート表示

**主要な出力内容**：
1. HTML変換されたMarkdownコンテンツ
2. VS Codeテーマ対応のスタイルシート
3. シンタックスハイライト付きコードブロック

**帳票の出力タイミング**：Markdownコンテンツの表示要求時。

**帳票の利用者**：VS Codeユーザー、拡張機能開発者

## 帳票種別

HTML出力 / ドキュメントレンダリング

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | Extension View | - | 拡張機能README表示 |
| - | Webview | - | Markdownコンテンツ表示 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | HTML (TrustedHTML) |
| 用紙サイズ | N/A |
| 向き | N/A |
| 出力方法 | DOM注入 |
| 文字コード | UTF-8 |

### サニタイズ設定

| 項目 | 内容 |
|-----|------|
| 許可プロトコル（リンク） | http, https |
| 許可プロトコル（メディア） | 設定可能 |
| 許可タグ | allowedMarkdownHtmlTags |
| 許可属性 | name, id, class, role, tabindex, placeholder + Markdown標準 |

## 帳票レイアウト

### レイアウト概要

Markdownコンテンツは標準的なHTML構造でレンダリングされ、VS Codeのテーマ変数を使用したスタイリングが適用される。

### デフォルトスタイル

```css
body {
  padding: 10px 20px;
  line-height: 22px;
  max-width: 882px;
  margin: 0 auto;
}

code {
  font-family: "SF Mono", Monaco, Menlo, ...;
}

pre code {
  font-family: var(--vscode-editor-font-family);
  font-weight: var(--vscode-editor-font-weight);
  font-size: var(--vscode-editor-font-size);
  line-height: 1.5;
  color: var(--vscode-editor-foreground);
  tab-size: 4;
}
```

### テーマ対応

| テーマ | 適用スタイル |
|-------|------------|
| vscode-light | ライトテーマ用ボーダーカラー |
| vscode-dark | ダークテーマ用ボーダーカラー |
| vscode-high-contrast | ハイコントラスト用スタイル |

### コードブロックレンダリング

| No | 言語 | 処理 |
|----|------|------|
| 1 | 指定言語 | languageService.getLanguageIdByLanguageNameでID取得 |
| 2 | 言語ID取得成功 | tokenizeToStringでトークン化+HTML変換 |
| 3 | 言語ID取得失敗 | エスケープしたプレーンテキスト |

## 出力条件

### レンダリング条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| Markdownテキスト | 有効なMarkdown文字列 | Yes |
| 拡張機能登録完了 | extensionService.whenInstalledExtensionsRegistered | Yes |
| キャンセルなし | CancellationToken.isCancellationRequested === false | Yes |

### サニタイズオプション

| オプション | 説明 | デフォルト |
|-----------|------|----------|
| allowedLinkProtocols | 許可するリンクプロトコル | http, https |
| allowRelativeLinkPaths | 相対リンクパス許可 | false |
| allowedMediaProtocols | 許可するメディアプロトコル | - |
| allowRelativeMediaPaths | 相対メディアパス許可 | false |
| allowedTags.augment | 追加許可タグ | - |
| allowedAttributes.augment | 追加許可属性 | - |

### 改ページ条件

N/A（HTML出力のため改ページなし）

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| N/A | 入力テキストを直接処理 | - |

### データ取得元

#### 入力パラメータ

| 参照項目 | 帳票項目との対応 | 取得方法 | 備考 |
|---------|----------------|---------|------|
| text | Markdownテキスト | 引数 | string |
| extensionService | 拡張機能サービス | DI | IExtensionService |
| languageService | 言語サービス | DI | ILanguageService |
| options | レンダリングオプション | 引数 | IRenderMarkdownDocumentOptions |
| token | キャンセルトークン | 引数 | CancellationToken |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| N/A | テキスト変換のみ | - | 計算なし |

## 処理フロー

### レンダリングフロー

```mermaid
flowchart TD
    A[renderMarkdownDocument呼び出し] --> B[Marked初期化]
    B --> C[MarkedHighlightプラグイン設定]
    C --> D[markedGfmHeadingIdPlugin設定]
    D --> E[追加markedExtensions適用]
    E --> F[marked.parse実行]
    F --> G{コードブロック?}
    G -->|Yes| H[highlight関数呼び出し]
    G -->|No| I[通常Markdown変換]
    H --> J[extensionService.whenInstalledExtensionsRegistered]
    J --> K{キャンセル?}
    K -->|Yes| L[空文字返却]
    K -->|No| M[languageId取得]
    M --> N[tokenizeToString]
    N --> I
    I --> O[sanitize]
    O --> P[TrustedHTML返却]
```

### コードハイライトフロー

```mermaid
flowchart TD
    A[highlight関数] --> B{lang指定あり?}
    B -->|No| C[escape(code)返却]
    B -->|Yes| D[whenInstalledExtensionsRegistered]
    D --> E{キャンセル?}
    E -->|Yes| F[空文字返却]
    E -->|No| G[getLanguageIdByLanguageName]
    G --> H{言語ID取得?}
    H -->|No| I[言語名の先頭部分で再試行]
    H -->|Yes| J[tokenizeToString]
    I --> J
    J --> K[ハイライト済みHTML返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| キャンセル | CancellationToken発火 | (空文字返却) | - |
| 言語ID不明 | 言語名が認識されない | (エスケープテキスト) | プレーンテキストとして表示 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1ドキュメント/呼び出し |
| 目標レンダリング時間 | 500ms以内（中規模ドキュメント） |
| 同時実行数上限 | 複数可（非同期） |

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

- 出力はTrustedHTML型で型安全
- sanitizeHtmlでXSS攻撃を防止
- 許可プロトコルのホワイトリスト方式
- 許可タグ/属性のホワイトリスト方式
- スクリプト実行は不可

## 備考

- marked.jsライブラリを使用
- GFM（GitHub Flavored Markdown）の見出しID対応
- VS Codeのトークナイザーによるシンタックスハイライト
- 非同期処理（async/await）でパフォーマンス最適化

---

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

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

### 推奨読解順序

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

レンダリング関数の入り口を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | markdownDocumentRenderer.ts | `src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts` | renderMarkdownDocument() (行223-253) |
| 1-2 | markdownDocumentRenderer.ts | `src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts` | IRenderMarkdownDocumentOptions (行212-215) |

**読解のコツ**: renderMarkdownDocument()が主要なエントリーポイント。async関数で非同期処理。

#### Step 2: Markedプラグイン設定を理解する

marked.jsのプラグイン設定を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | markdownDocumentRenderer.ts | `src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts` | MarkedHighlight.markedHighlight() (行258-296) |
| 2-2 | markdownDocumentRenderer.ts | `src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts` | highlight関数 (行233-244) |

**主要処理フロー**:
- **行230-232**: Markedインスタンス作成
- **行233-244**: highlight関数でコードブロック処理
- **行251**: marked.parse()でMarkdown→HTML変換
- **行252**: sanitize()でセキュリティ処理

#### Step 3: サニタイズ処理を理解する

HTML出力のセキュリティ処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | markdownDocumentRenderer.ts | `src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts` | sanitize() (行165-190) |
| 3-2 | markdownDocumentRenderer.ts | `src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts` | MarkdownDocumentSanitizerConfig (行192-210) |

**主要処理フロー**:
- **行166-189**: sanitizeHtml()呼び出し
- **行167-168**: allowedLinkProtocolsデフォルト設定
- **行173-176**: allowedTagsのoverride/augment
- **行177-188**: allowedAttributesのoverride/augment

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

```
renderMarkdownDocument()
    │
    ├─ new marked.Marked()
    │      │
    │      ├─ MarkedHighlight.markedHighlight()
    │      │      │
    │      │      └─ highlight(code, lang)
    │      │             │
    │      │             ├─ extensionService.whenInstalledExtensionsRegistered()
    │      │             │
    │      │             ├─ languageService.getLanguageIdByLanguageName()
    │      │             │
    │      │             └─ tokenizeToString()
    │      │
    │      └─ markedGfmHeadingIdPlugin()
    │
    ├─ m.parse(text, { async: true })
    │
    └─ sanitize(raw, options.sanitizerConfig)
           │
           └─ sanitizeHtml()
                  │
                  ├─ allowedLinkProtocols処理
                  ├─ allowedTags処理
                  └─ allowedAttributes処理
```

### データフロー図

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

Markdownテキスト      ┌─────────────────────┐
                     │                     │
  ─────────────────▶│ renderMarkdown      │
                     │   Document()        │
                     │                     │
IExtensionService ──▶│ - Marked初期化      │
                     │ - highlight処理     │──────▶ TrustedHTML
ILanguageService ───▶│ - parse実行         │
                     │ - sanitize処理      │
SanitizerConfig ────▶│                     │
                     └─────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| markdownDocumentRenderer.ts | `src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts` | ソース | メインレンダラー |
| markedGfmHeadingIdPlugin.ts | `src/vs/workbench/contrib/markdown/browser/markedGfmHeadingIdPlugin.ts` | ソース | GFM見出しIDプラグイン |
| domSanitize.ts | `src/vs/base/browser/domSanitize.ts` | ソース | HTMLサニタイズ |
| markdownRenderer.ts | `src/vs/base/browser/markdownRenderer.ts` | ソース | 許可タグ/属性定義 |
| textToHtmlTokenizer.ts | `src/vs/editor/common/languages/textToHtmlTokenizer.ts` | ソース | トークナイザー |
