# 画面設計書 2-Playground

## 概要

本ドキュメントはPrettier Playgroundの画面設計書です。ブラウザ上でPrettierを試用できるインタラクティブなコードフォーマッター画面であり、Vue 3とReactを組み合わせた独立SPAとして構築されています。

### 本画面の処理概要

Playgroundは、ユーザーがコードを入力するとリアルタイムでPrettierによるフォーマット結果を確認できるインタラクティブな画面です。サイドバーで各種フォーマットオプションを設定し、即座にその効果を確認できます。

**業務上の目的・背景**：Prettierを導入検討中のユーザーや、特定のオプション設定の効果を確認したいユーザーに対して、インストール不要でブラウザ上でPrettierを試用できる環境を提供します。また、バグレポート作成時の再現コード共有や、チーム内での設定共有にも活用されます。

**画面へのアクセス方法**：
- ホームページの「Try It Online」ボタンをクリック
- ブラウザで直接 `https://prettier.io/playground/` にアクセス
- NavbarのPlaygroundリンクをクリック

**主要な操作・処理内容**：
1. 入力パネルにコードを入力
2. サイドバーでパーサー（言語）を選択
3. サイドバーで各種フォーマットオプションを設定
4. 出力パネルでフォーマット結果をリアルタイム確認
5. デバッグパネルでAST、Doc、コメント情報を確認
6. 範囲フォーマット（rangeStart/rangeEnd）の設定
7. カーソル位置追跡フォーマットの実行
8. 設定のJSON形式コピー
9. 共有リンクの生成とコピー
10. GitHub Issueレポートの作成

**画面遷移**：
- 遷移元：ホームページ、Navbar
- 遷移先：GitHub Issue作成ページ（外部）、ホームページ

**権限による表示制御**：本画面は公開ページのため、権限による表示制御はありません。全ての訪問者が同一の機能を利用できます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | コードフォーマット（format） | 主機能 | 入力コードをリアルタイムでフォーマットする主処理 |
| 2 | カーソル位置追跡フォーマット（formatWithCursor） | 主機能 | カーソル位置を追跡しながらフォーマットを実行 |
| 4 | 範囲フォーマット | 補助機能 | 選択範囲のみをフォーマットする処理（rangeStart/rangeEnd指定時） |
| 5 | JavaScript/TypeScript パース | API連携 | Babel、TypeScript等のパーサーでコードをパース |
| 6 | CSS/SCSS/Less パース | API連携 | PostCSSでCSS/SCSS/Lessをパース |
| 7 | HTML/Vue/Angular パース | API連携 | HTML、Vue、Angularテンプレートをパース |
| 8 | Markdown/MDX パース | API連携 | MarkdownおよびMDXをパース |
| 9 | YAML パース | API連携 | YAMLファイルをパース |
| 10 | GraphQL パース | API連携 | GraphQLクエリ・スキーマをパース |
| 11 | JSON/JSON5/JSONC パース | API連携 | JSON、JSON5、JSONCをパース |
| 12 | Handlebars/Glimmer パース | API連携 | Ember/Handlebarsテンプレートをパース |
| 28 | サポート情報取得（getSupportInfo） | API連携 | 利用可能なオプション情報を取得してサイドバーに表示 |
| 29 | ASTパース（__debug.parse） | 補助機能 | デバッグパネルでASTを表示する際に使用 |
| 30 | ASTからDoc生成（__debug.printToDoc） | 補助機能 | デバッグパネルでDocを表示する際に使用 |
| 40-60 | 各種フォーマットオプション | 補助機能 | サイドバーから各オプションを設定 |

## 画面種別

ツール / インタラクティブエディタ

## URL/ルーティング

- URL: `/playground/`
- ファイルパス: `website/playground/index.jsx`
- 独立SPA（Vite構築）

## 入出力項目

### 入力項目

| 項目名 | 型 | 必須 | デフォルト値 | 説明 |
|--------|-----|------|-------------|------|
| code | string | - | サンプルコード | フォーマット対象のコード |
| parser | string | ○ | babel | 使用するパーサー |
| printWidth | number | - | 80 | 行の最大幅 |
| tabWidth | number | - | 2 | タブ幅 |
| useTabs | boolean | - | false | タブを使用するか |
| semi | boolean | - | true | セミコロンを出力するか |
| singleQuote | boolean | - | false | シングルクォートを使用するか |
| bracketSpacing | boolean | - | true | オブジェクトのブラケット内スペース |
| jsxSingleQuote | boolean | - | false | JSXでシングルクォートを使用するか |
| quoteProps | string | - | as-needed | プロパティのクォート |
| arrowParens | string | - | always | アロー関数の括弧 |
| trailingComma | string | - | all | 末尾カンマ |
| proseWrap | string | - | preserve | Prose折り返し |
| htmlWhitespaceSensitivity | string | - | css | HTML空白処理 |
| endOfLine | string | - | lf | 改行コード |
| rangeStart | number | - | - | 範囲開始位置 |
| rangeEnd | number | - | - | 範囲終了位置 |
| cursorOffset | number | - | -1 | カーソル位置 |

### 出力項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| formatted | string | フォーマット済みコード |
| ast | string | パース結果のAST（JSON） |
| preprocessedAst | string | 前処理済みAST（JSON） |
| doc | string | 生成されたDoc |
| comments | string | コメント情報（JSON） |
| reformatted | string | 二度目のフォーマット結果（冪等性チェック用） |
| cursorOffset | number | フォーマット後のカーソル位置 |

## 表示項目

| セクション | 項目名 | 表示形式 | データソース |
|------------|--------|----------|--------------|
| ヘッダー | Prettierロゴ | 画像 | /icon.png |
| ヘッダー | バージョン情報 | テキスト+リンク | worker.getMetadata() |
| ヘッダー | GitHubスターボタン | ボタン | github-button.vue |
| ヘッダー | テーマトグル | ボタン | theme-toggle.vue |
| サイドバー | パーサー選択 | ドロップダウン | getSupportInfo().options |
| サイドバー | 各種オプション | チェックボックス/入力欄 | getSupportInfo().options |
| サイドバー | Range設定 | 数値入力 | 内部ステート |
| サイドバー | Cursor設定 | 数値入力+チェックボックス | 内部ステート |
| サイドバー | Debug設定 | チェックボックス群 | playground-settings.js |
| 入力パネル | コードエディタ | CodeMirror | 内部ステート |
| 出力パネル | フォーマット結果 | CodeMirror（読み取り専用） | format結果 |
| デバッグパネル | AST | CodeMirror（読み取り専用） | __debug.parse結果 |
| デバッグパネル | Doc | CodeMirror（読み取り専用） | __debug.printToDoc結果 |
| ボトムバー | 各種ボタン | ボタン群 | - |

## イベント仕様

### 1-コード入力

ユーザーが入力パネルにコードを入力すると、リアルタイムでフォーマットが実行されます。

**処理フロー**：
1. CodeMirrorの`onChange`イベント発火
2. `setContent`関数でステート更新
3. `watch`により`format`関数が自動実行
4. Web Workerでフォーマット処理
5. 結果がステートに反映され、出力パネル更新

### 2-オプション変更

サイドバーでオプションを変更すると、即座にフォーマットが再実行されます。

**処理フロー**：
1. オプションコンポーネントの`onChange`イベント発火
2. `handleOptionValueChange`関数でオプションステート更新
3. パーサー変更時はサンプルコードも更新
4. `watch`により`format`関数が自動実行
5. URLハッシュが更新され、共有可能な状態に

### 3-範囲選択とフォーマット

テキスト選択後、「Set selected text as range」ボタンでrangeStart/rangeEndを設定できます。

**処理フロー**：
1. テキスト選択イベント発火
2. `setSelection`でselectionステート更新
3. ボタンクリックで`setSelectionAsRange`実行
4. rangeStart/rangeEndオプションに値を設定
5. 範囲フォーマットが実行され、選択範囲のみがフォーマット

### 4-共有リンクコピー

「Copy link」ボタンで現在の設定とコードを含むURLをコピーできます。

**処理フロー**：
1. ボタンクリックイベント発火
2. `window.location.href`をクリップボードにコピー
3. URLハッシュにはコードとオプションがエンコードされている

### 5-設定JSONコピー

「Copy config JSON」ボタンで.prettierrc用のJSON設定をコピーできます。

**処理フロー**：
1. ボタンクリックイベント発火
2. 現在のオプション（parser除く）をJSON文字列化
3. クリップボードにコピー

### 6-GitHub Issueレポート

「Report issue」ボタンでバグレポート用のMarkdownを生成しGitHub Issueを作成できます。

**処理フロー**：
1. ボタンクリックイベント発火
2. `formatMarkdown`でレポート用Markdownを生成
3. 8000文字以内ならURLに埋め込み、超える場合はクリップボードコピー
4. GitHub Issue作成ページへ遷移

## データベース更新仕様

本画面はデータベースを使用しません。全てのデータはブラウザのローカルステート、URLハッシュ、LocalStorageで管理されます。

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

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

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|----------------|----------|
| MSG-01 | 情報 | Loading... | 初期ロード中 |
| MSG-02 | 成功 | Second format is unchanged. | 二度目のフォーマットが同一の場合 |
| MSG-03 | エラー | パースエラーメッセージ | コードのパースに失敗した場合 |

## 例外処理

| 例外ケース | 処理内容 | ユーザーへの表示 |
|-----------|----------|-----------------|
| パースエラー | エラー情報を出力パネルに表示 | エラーメッセージとスタックトレース |
| Web Worker通信エラー | Promiseリジェクト | エラーメッセージ表示 |
| 無効なオプション値 | デフォルト値にフォールバック | 正常動作継続 |
| URLハッシュ不正 | デフォルト状態で起動 | 正常動作継続 |

## 備考

- Vue 3 + React（JSX）のハイブリッド構成
- Web Workerでフォーマット処理を実行（UIブロッキング防止）
- URLハッシュにコードとオプションを保存（共有可能）
- LocalStorageで表示設定を永続化
- Service Workerによるオフライン対応
- 複数バージョンのPrettierをサポート（バージョン切り替え可能）

---

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

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

### 推奨読解順序

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

まず、Playgroundで使用されるデータ構造と設定を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | playground-settings.js | `website/playground/composables/playground-settings.js` | 表示設定のリアクティブステート定義 |
| 1-2 | urlHash.js | `website/playground/urlHash.js` | URLハッシュのエンコード/デコード仕様 |
| 1-3 | utilities.js | `website/playground/utilities.js` | デフォルト値生成、CLIオプション構築 |

**読解のコツ**: Vueのreactive/refとURLハッシュの同期方法を理解することが重要です。

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

アプリケーションの起動フローを追跡します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.jsx | `website/playground/index.jsx` | Vueアプリケーションの初期化とマウント |

**主要処理フロー**:
1. **1行目**: Service Workerのインストール
2. **11-50行目**: Appコンポーネントのsetup関数でメタデータ取得
3. **18-27行目**: `updateMetadata`でgetSupportInfo呼び出し
4. **52-63行目**: オプションの拡張（CLI名生成）
5. **65-67行目**: DOMマウント

#### Step 3: メインコンポーネントを理解する

Playgroundコンポーネントの構造を把握します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Playground.jsx | `website/playground/Playground.jsx` | メインUIコンポーネント |

**主要処理フロー**:
- **59-94行目**: setup関数での初期化処理
- **95-134行目**: ステート更新関数群の定義
- **145-161行目**: オプション変更ハンドラ
- **237-535行目**: render関数でのUI構築
- **537-543行目**: URLハッシュの同期watch

#### Step 4: フォーマット処理を理解する

Web Workerを使用したフォーマット処理フローを追跡します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | PrettierFormat.js | `website/playground/PrettierFormat.js` | フォーマット実行コンポーネント |
| 4-2 | prettier-worker.js | `website/playground/composables/prettier-worker.js` | Web Worker通信API |

**主要処理フロー**:
- **PrettierFormat.js 13-21行目**: `format`関数でWorker呼び出し
- **prettier-worker.js 41-48行目**: メッセージ送受信のPromise化
- **prettier-worker.js 65-68行目**: フォーマットメッセージ構築

#### Step 5: UIコンポーネントを理解する

サイドバー、パネル等のUIコンポーネント構造を把握します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | sidebar/SidebarOptions.jsx | `website/playground/sidebar/SidebarOptions.jsx` | オプションサイドバー |
| 5-2 | panels.jsx | `website/playground/panels.jsx` | 入力/出力パネル |
| 5-3 | header.vue | `website/playground/header.vue` | ヘッダーコンポーネント |

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

```
index.jsx (エントリーポイント)
    │
    ├─ createApp(App)
    │      │
    │      └─ App.setup()
    │             │
    │             ├─ worker.getMetadata(version)
    │             │      └─ WorkerApi.#postMessage()
    │             │
    │             └─ render()
    │                    │
    │                    ├─ Header (header.vue)
    │                    │      ├─ VersionLink
    │                    │      ├─ GithubButton
    │                    │      └─ ThemeToggle
    │                    │
    │                    └─ Playground (Playground.jsx)
    │                           │
    │                           ├─ PrettierFormat (PrettierFormat.js)
    │                           │      └─ worker.format()
    │                           │             └─ WorkerApi.#postMessage()
    │                           │
    │                           ├─ Sidebar
    │                           │      └─ SidebarOptions
    │                           │             └─ Option × N
    │                           │
    │                           ├─ InputPanel (panels.jsx)
    │                           │      └─ CodeMirror
    │                           │
    │                           ├─ OutputPanel (panels.jsx)
    │                           │      └─ CodeMirror
    │                           │
    │                           └─ DebugPanel (panels.jsx) × N
    │                                  └─ CodeMirror
    │
    └─ root.mount(container)
```

### データフロー図

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

URLハッシュ      ───▶ urlHash.read()            ───▶ 初期ステート
         │
         ▼
ユーザー入力     ───▶ setContent()              ───▶ state.content
         │
         ▼
オプション変更   ───▶ handleOptionValueChange() ───▶ state.options
         │
         ▼
ステート変更     ───▶ watch() トリガー          ───▶ format() 呼び出し
         │
         ▼
format()        ───▶ worker.format()           ───▶ Web Worker
         │
         ▼
Worker結果      ───▶ PrettierFormat.state      ───▶ 出力パネル更新
         │
         ▼
ステート変更     ───▶ urlHash.replace()         ───▶ URLハッシュ更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.jsx | `website/playground/index.jsx` | ソース | エントリーポイント、Vueアプリ初期化 |
| Playground.jsx | `website/playground/Playground.jsx` | ソース | メインPlaygroundコンポーネント |
| PrettierFormat.js | `website/playground/PrettierFormat.js` | ソース | フォーマット実行ラッパー |
| prettier-worker.js | `website/playground/composables/prettier-worker.js` | ソース | Web Worker通信API |
| playground-settings.js | `website/playground/composables/playground-settings.js` | ソース | 表示設定管理 |
| use-version.js | `website/playground/composables/use-version.js` | ソース | バージョン管理 |
| use-theme.js | `website/playground/composables/use-theme.js` | ソース | テーマ管理 |
| urlHash.js | `website/playground/urlHash.js` | ソース | URLハッシュ管理 |
| utilities.js | `website/playground/utilities.js` | ソース | ユーティリティ関数 |
| header.vue | `website/playground/header.vue` | ソース | ヘッダーコンポーネント |
| panels.jsx | `website/playground/panels.jsx` | ソース | パネルコンポーネント群 |
| buttons.jsx | `website/playground/buttons.jsx` | ソース | ボタンコンポーネント群 |
| sidebar/components.jsx | `website/playground/sidebar/components.jsx` | ソース | サイドバーコンポーネント |
| sidebar/SidebarOptions.jsx | `website/playground/sidebar/SidebarOptions.jsx` | ソース | オプションサイドバー |
| sidebar/options.jsx | `website/playground/sidebar/options.jsx` | ソース | オプション入力コンポーネント |
| sidebar/inputs.jsx | `website/playground/sidebar/inputs.jsx` | ソース | 入力コンポーネント |
| panel/language.js | `website/playground/panel/language.js` | ソース | CodeMirrorモード判定 |
| codeSamples.mjs | `website/playground/codeSamples.mjs` | データ | 各パーサー用サンプルコード |
| markdown.js | `website/playground/markdown.js` | ソース | レポート用Markdown生成 |
| storage.js | `website/playground/storage.js` | ソース | LocalStorageラッパー |
| dummyId.js | `website/playground/dummyId.js` | ソース | ダミーID生成 |
| install-service-worker.js | `website/playground/install-service-worker.js` | ソース | Service Worker登録 |
