# 機能設計書 6-CSS/SCSS/Less パース

## 概要

本ドキュメントは、PrettierのCSS/SCSS/Lessパース機能の設計について記述する。

### 本機能の処理概要

PostCSSライブラリを使用してCSS、SCSS、Lessをパースし、AST（抽象構文木）を生成する機能である。各言語の構文特性に応じた専用パーサーを使用し、セレクタ、プロパティ、値などを詳細に解析する。

**業務上の目的・背景**：CSSとそのプリプロセッサ（SCSS、Less）はウェブ開発において不可欠なスタイル言語である。これらの言語をサポートすることで、フロントエンド開発者のワークフローを効率化し、一貫性のあるスタイルコードを維持できる。

**機能の利用シーン**：
- CSSファイルのフォーマット
- SCSS/Sassファイルのフォーマット
- Lessファイルのフォーマット
- Vue SFCのstyleセクションのフォーマット
- Playgroundでのスタイル言語パース

**主要な処理内容**：
1. Front Matterの解析（YAML/TOMLヘッダー）
2. PostCSS系パーサーによるメインパース
3. ネストされたCSS構造の解析
4. セレクタ、メディアクエリ、値の詳細パース
5. SCSS/Less固有構文の処理（変数、mixin等）
6. 位置情報の計算

**関連システム・外部連携**：
- postcss（CSS標準パーサー）
- postcss-scss（SCSSパーサー）
- postcss-less（Lessパーサー）
- postcss-selector-parser（セレクタパーサー）
- postcss-media-query-parser（メディアクエリパーサー）
- postcss-values-parser（値パーサー）

**権限による制御**：特になし。すべてのユーザーがパーサー機能を利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | Playground | API連携 | PostCSSでCSS/SCSS/Lessをパース |
| 5 | About - Prettier概要 | 補助機能 | 対応言語としてCSS/SCSS/Lessパースを説明 |

## 機能種別

計算処理 / パース処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| text | string | Yes | パース対象のスタイルシートコード | - |
| options | object | No | パースオプション | - |
| options.parser | string | No | パーサー名（css, scss, less） | 有効なパーサー名 |
| options.filepath | string | No | ファイルパス（パーサー推論用） | - |

### 入力データソース

- スタイルシートコードテキスト
- ファイルパス情報（パーサー推論用）

### サポートパーサー

| パーサー名 | 説明 | 使用ライブラリ |
|-----------|------|---------------|
| css | 標準CSSパーサー | postcss/lib/parse |
| scss | SCSSパーサー | postcss-scss |
| less | Lessパーサー | postcss-less |

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ast | object | パースされたCSS AST |
| frontMatter | object | Front Matter情報（存在する場合） |

### 出力先

- パース関数の戻り値として返却
- プリンターで使用

## 処理フロー

### 処理シーケンス

```
1. Front Matterの解析
   └─ YAML/TOMLヘッダーを検出・分離

2. パーサー選択
   └─ options.parserまたはfilepathから決定

3. PostCSSパース
   ├─ CSS: postcss/lib/parse
   ├─ SCSS: postcss-scss
   └─ Less: postcss-less

4. ネスト構造の解析
   └─ parseNestedCSS関数で再帰的に処理

5. セレクタパース
   └─ postcss-selector-parserで詳細解析

6. メディアクエリパース
   └─ postcss-media-query-parserで解析

7. 値パース
   └─ postcss-values-parserで解析

8. 位置情報計算
   └─ calculateLocで開始/終了位置を計算

9. 型プレフィックス付与
   └─ ノードタイプに"css-"プレフィックスを付与
```

### フローチャート

```mermaid
flowchart TD
    A[パース開始] --> B[Front Matter解析]
    B --> C{Front Matterあり?}
    C -->|Yes| D[Front Matter分離]
    C -->|No| E[パーサー選択]
    D --> E
    E --> F{パーサー種類}
    F -->|css| G[postcssParse]
    F -->|scss| H[postcssScssParse]
    F -->|less| I[postcssLess.parse]
    G --> J[parseNestedCSS]
    H --> J
    I --> J
    J --> K[セレクタ/メディア/値パース]
    K --> L[位置情報計算]
    L --> M[型プレフィックス付与]
    M --> N[AST返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | Front Matter対応 | ファイル先頭のYAML/TOMLヘッダーを解析 | ---または+++で囲まれた部分 |
| BR-02 | 型プレフィックス | すべてのノードタイプに"css-"プレフィックスを付与 | 常時 |
| BR-03 | カスタムプロパティ処理 | --で始まるプロパティは特別処理 | CSS変数定義時 |
| BR-04 | SCSS変数検出 | $で始まる識別子はSCSS変数として認識 | SCSSパーサー時 |
| BR-05 | SCSS指示子 | !defaultと!globalを検出・処理 | SCSSパーサー時 |
| BR-06 | Lessミックスイン | @で始まりパラメータを持つものはmixinとして認識 | Lessパーサー時 |
| BR-07 | Less変数 | @で始まり:が続くものは変数として認識 | Lessパーサー時 |

### 計算ロジック

**位置情報計算**：
各ノードのsourceプロパティから開始/終了オフセットを計算し、locStart/locEnd関数で取得可能にする。

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| CssSyntaxError | パースエラー | CSS構文エラー | コードを修正 |
| ConfigError | 設定エラー | パーサーが見つからない | パーサー名を確認 |

### リトライ仕様

リトライは行わない。エラー発生時は即座に例外をスロー。

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

トランザクション管理は不要（ステートレスな処理）。

## パフォーマンス要件

- 一般的なスタイルシート（500行程度）のパースは30ms以内
- ネストの深いSCSSでも安定した処理時間

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

- 入力コードの実行は行わない（静的解析のみ）
- ファイルアクセス（mapオプション）は無効化

## 備考

- postcss-lessには一部のバグがあり、インラインコメントのクォート処理でワークアラウンドを使用
- カスタムプロパティ（CSS変数）の値はネストされたルールとして再パースされる場合がある

---

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

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

### 推奨読解順序

#### Step 1: パーサープラグインの構成を理解する

CSSパーサーがプラグインとしてどのように構成されているかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | postcss.js | `src/plugins/postcss.js` | PostCSSパーサープラグインのエクスポート |
| 1-2 | index.js | `src/language-css/index.js` | 言語モジュールの構成 |

**読解のコツ**: プラグインファイルは言語モジュールを再エクスポートするだけの薄いラッパー。

#### Step 2: パーサー実装を理解する

CSSパーサーの詳細な実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | parser-postcss.js | `src/language-css/parser-postcss.js` | パーサー実装本体 |

**主要処理フロー**:
- **1-20行目**: 依存ライブラリのインポート
- **22-24行目**: SCSS指示子の正規表現
- **25-380行目**: parseNestedCSS関数（再帰的なCSS解析）
- **382-422行目**: parseWithParser関数（パーサー共通処理）
- **424-426行目**: parseCss関数
- **428-436行目**: parseLess関数
- **438-440行目**: parseScss関数
- **442-453行目**: パーサーオブジェクトのエクスポート

#### Step 3: ネスト構造の解析を理解する

parseNestedCSS関数の詳細を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | parser-postcss.js | `src/language-css/parser-postcss.js` | parseNestedCSS関数 |

**主要処理フロー**:
- **25-92行目**: カスタムプロパティの特別処理
- **94-163行目**: セレクタパース
- **165-196行目**: 値パース（SCSS指示子処理を含む）
- **198-231行目**: Less変数・mixin処理
- **289-376行目**: at-ruleの処理

#### Step 4: サブパーサーを理解する

セレクタ、メディアクエリ、値の詳細パースを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | parse-selector.js | `src/language-css/parse/parse-selector.js` | セレクタパーサー |
| 4-2 | parse-media-query.js | `src/language-css/parse/parse-media-query.js` | メディアクエリパーサー |
| 4-3 | parse-value.js | `src/language-css/parse/parse-value.js` | 値パーサー |

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

```
parser-postcss (src/language-css/parser-postcss.js)
    │
    ├─ parseCss / parseScss / parseLess
    │      │
    │      └─ parseWithParser
    │             │
    │             ├─ parseFrontMatter (Front Matter解析)
    │             │
    │             ├─ postcssParse / postcssScssParse / postcssLess.parse
    │             │
    │             ├─ addTypePrefix (型プレフィックス付与)
    │             │
    │             ├─ parseNestedCSS (再帰的解析)
    │             │      │
    │             │      ├─ parseSelector (セレクタ解析)
    │             │      ├─ parseValue (値解析)
    │             │      └─ parseMediaQuery (メディアクエリ解析)
    │             │
    │             └─ calculateLoc (位置情報計算)
    │
    └─ hasPragma / hasIgnorePragma (プラグマチェック)
```

### データフロー図

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

スタイルシート ─────────▶ Front Matter解析 ─────────────▶ コンテンツ分離
    │                                                         │
    │                                                         ▼
    │                    PostCSSパース ─────────────────▶ 生AST
    │                         │
    │                         ▼
    │                    parseNestedCSS ────────────────▶ 解析済みAST
    │                         │
    │                         ├─ parseSelector ─────────▶ セレクタAST
    │                         ├─ parseValue ────────────▶ 値AST
    │                         └─ parseMediaQuery ───────▶ メディアクエリAST
    │                                                         │
    │                                                         ▼
    │                                        calculateLoc ───▶ 位置情報付きAST
    │                                                         │
    │                                                         ▼
    └─────────────────────────────────────────────────────▶ 最終AST
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| postcss.js | `src/plugins/postcss.js` | ソース | PostCSSパーサープラグイン |
| index.js | `src/language-css/index.js` | ソース | 言語モジュールエクスポート |
| parser-postcss.js | `src/language-css/parser-postcss.js` | ソース | パーサー実装本体 |
| parse-selector.js | `src/language-css/parse/parse-selector.js` | ソース | セレクタパーサー |
| parse-media-query.js | `src/language-css/parse/parse-media-query.js` | ソース | メディアクエリパーサー |
| parse-value.js | `src/language-css/parse/parse-value.js` | ソース | 値パーサー |
| loc.js | `src/language-css/loc.js` | ソース | 位置情報関数 |
| pragma.js | `src/language-css/pragma.js` | ソース | プラグマ処理 |
| utilities/index.js | `src/language-css/utilities/index.js` | ソース | ユーティリティ関数 |
| printer-postcss.js | `src/language-css/printer-postcss.js` | ソース | CSSプリンター |
