# ドキュメント生成








katachi は `architecture { }` 定義から markdown ドキュメントを生成できます。

## 基本

build.gradle.kts に以下のように設定します。

```kts title="architecture-test/build.gradle.kts" {2-3}
katachi {
    // ⭐️ `architecture { }` を定義しているプロパティの FQCN を設定
    architecture = "com.example.projectArchitecture"
}
```

設定したら、Gradle タスク `katachiDocs` を実行すると、ドキュメントが生成されます。

```shell
./gradlew katachiDocs
```

### 生成例

次の定義を例にします。

```kt
architecture {
    title = "myapp"

    "domain".group {
        title = "Domain レイヤー"
        summary = "アプリ固有の振る舞いと、その対象になる値"

        "UseCase" {
            title = "ユースケース"
            summary = "各画面で発生するアプリ固有の1つの振る舞い"
            example("GetItemListUseCase", "商品の一覧")
            example("SignInUseCase", "サインイン")
            layout { "core/domain" / mainSourceSet / kotlin / "com/example/core/domain/useCase" / "*UseCase".ktFile() }
            "invoke メソッドだけを持つこと".konsist { /* ... */ }
        }

        "RepositoryInterface" {
            title = "リポジトリ"
            summary = "データの取得と保存の境界"
            layout { "core/domain" / mainSourceSet / kotlin / "com/example/core/domain/repository" / "*Repository".ktFile() }
        }
    }
}
```

<Tabs>
    <TabItem label="ディレクトリ構造">
        <FileTree>
        - build/katachi/docs/
          - README.md
          - domain/
            - README.md
            - UseCase.md
            - RepositoryInterface.md
        </FileTree>
    </TabItem>

    <TabItem label="README.md">
        ```md collapse
        # myapp documentation

        ## Document map

        ### [Domain レイヤー](./domain/README.md)

        アプリ固有の振る舞いと、その対象になる値

        - [ユースケース](./domain/UseCase.md)
        - [リポジトリ](./domain/RepositoryInterface.md)

        ## Domain レイヤー

        アプリ固有の振る舞いと、その対象になる値

        - [ユースケース](./domain/UseCase.md) ... 各画面で発生するアプリ固有の1つの振る舞い
        - [リポジトリ](./domain/RepositoryInterface.md) ... データの取得と保存の境界
        ```
    </TabItem>
    <TabItem label="domain/README.md">
        ````md collapse
        [myapp](../README.md)

        # Domain レイヤー

        アプリ固有の振る舞いと、その対象になる値

        | Role | Summary |
        |---|---|
        | [ユースケース](./UseCase.md) | 各画面で発生するアプリ固有の1つの振る舞い |
        | [リポジトリ](./RepositoryInterface.md) | データの取得と保存の境界 |

        ## Placement in this group

        ```
        core/domain/src/main/kotlin/com/example/core/domain/
          useCase/*UseCase.kt        ユースケース
          repository/*Repository.kt  リポジトリ
        ```
        ````
    </TabItem>
    <TabItem label="domain/UseCase.md">
        ```md collapse
        [myapp](../README.md) / [Domain レイヤー](README.md)

        # ユースケース

        各画面で発生するアプリ固有の1つの振る舞い

        ## Placement

        | Path | When to use |
        |---|---|
        | `core/domain/src/main/kotlin/com/example/core/domain/useCase/*UseCase.kt` |  |

        ## Constraints

        - invoke メソッドだけを持つこと

        ## Examples

        - `GetItemListUseCase` ... 商品の一覧
        - `SignInUseCase` ... サインイン
        ```
    </TabItem>
    <TabItem label="domain/RepositoryInterface.md">
        ```md collapse
        [myapp](../README.md) / [Domain レイヤー](README.md)

        # リポジトリ

        データの取得と保存の境界

        ## Placement

        | Path | When to use |
        |---|---|
        | `core/domain/src/main/kotlin/com/example/core/domain/repository/*Repository.kt` |  |
        ```
    </TabItem>
</Tabs>

katachi の GitHub リポジトリのサンプルでは、実際に生成したドキュメントを `sample/<name>/docs/` に置いています。具体例はこちらも参照してください。

<LinkCard title="katachi の sample" href="https://github.com/TBSten/katachi/tree/main/sample" />

## 出力先ディレクトリ

ドキュメントは、デフォルトでは `build/katachi/docs/` 配下に生成されます。

出力先は、build.gradle.kts で `katachi.processors.docs.outputDir` を設定すると変更できます。

```kts {6}
katachi {
    architecture = "com.example.projectArchitecture"

    processors {
        docs {
            outputDir = rootProject.layout.projectDirectory.dir("docs/architecture")
        }
    }
}
```

## 生成されるファイル

`architecture { }` 定義から生成されるファイルは以下のとおりです。

### 通常

<FileTree>
- \<出力先ディレクトリ>/
  - README.md
  - \<Role名>.md
</FileTree>

### グループがある場合

<FileTree>
- \<出力先ディレクトリ>/
  - README.md
  - \<Role名>.md
  - \<グループ名>/
    - README.md
    - \<Role名>.md
    - \<ネストしたグループ名>/
      - README.md
      - \<Role名>.md
</FileTree>

group は入れ子にでき、入れ子の group はその親の group のディレクトリの下に出ます。

ファイル名とディレクトリ名は、`title` ではなく**識別子**（`"UseCase" { }` の `UseCase`、`"domain".group { }` の `domain`）で決まります。`title` を変えても、ファイル名は変わりません。

## ドキュメント生成に利用されるプロパティ

ドキュメントは、Role と group に設定したプロパティから生成されます。

### Role

| プロパティ | 生成されるドキュメントでの役割 | 使用されるページ |
|---|---|---|
| [`title`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-role-scope/title.html) | Role のページの見出し。デフォルトは Role の識別子 | `<Role名>.md`、および索引・一覧のリンク文字列 |
| [`summary`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-role-scope/summary.html) | 一覧の表に入る1行 | `<Role名>.md`、親の `README.md` |
| [`description`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-role-scope/description.html) | Role のページの本文。書いた Markdown が改行も含めてそのまま入ります。katachi は構造を足さないので、**中の見出しは書き手が決めます** | `<Role名>.md` |
| [`example(name, description)`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-role-scope/example.html) | 具体例。1つの例につき1回呼びます。**呼んだ順**に並びます | `<Role名>.md` の `## Examples` |
| [`documented`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-role-scope/documented.html) | `false` にするとドキュメントに出ません。出ないだけで、**assert() などの検査には引き続き参加します** | --- |

<CodeComparison>
    <CodeComparison.Panel label="Role 定義">
        ```kt
        "UseCase" {
            title = "UseCase"
            summary = "各画面で発生するアプリ固有の1つの振る舞い"
            description = """
                UseCase はアプリ固有の1つの振る舞いを表すクラスです。
            """.trimIndent()

            example("GetItemListUseCase", "商品の一覧を取得する")
            example("SignInUseCase", "サインインする")

            layout {
                "src/main/kotlin/com/example/useCase" /
                    "*UseCase".ktFile()
            }

            "invoke メソッドだけを持つこと".konsist { /* ... */ }
        }
        ```
    </CodeComparison.Panel>
    <CodeComparison.Panel label="生成されるマークダウン">
        ```md title="UseCase.md"
        [Architecture](README.md)                    ← パンくず

        # UseCase                                      ← title

        各画面で発生するアプリ固有の1つの振る舞い        ← summary

        UseCase はアプリ固有の1つの振る舞いを表すクラスです。  ← description

        ## Placement                                    ← layout { }

        | Path | When to use |
        |---|---|
        | `src/main/kotlin/com/example/useCase/*UseCase.kt` |  |

        ## Constraints                                        ← konsist { } の名前

        - invoke メソッドだけを持つこと

        ## Examples                                          ← example()

        - `GetItemListUseCase` ... 商品の一覧を取得する
        - `SignInUseCase` ... サインインする
        ```
    </CodeComparison.Panel>
</CodeComparison>

### group

group に設定できるのは Role と同じ4つです。**`example()` だけがありません。**

| プロパティ | 生成されるドキュメントでの役割 | 使用されるページ |
|---|---|---|
| [`title`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-group-scope/title.html) | group の README の見出し。デフォルトは group の識別子 | `README.md`, `<グループ名>/README.md` |
| [`summary`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-group-scope/summary.html) | 親の Document map と group の節に出る1行 | `README.md`, `<グループ名>/README.md` |
| [`description`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-group-scope/description.html) | group の README の本文 | `<グループ名>/README.md` |
| [`documented`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-group-scope/documented.html) | `false` にすると group ごとドキュメントに出ません。検査には参加します | --- |

<details>
    <summary>注意: documented = false は group の中身ごと外します</summary>

    `documented = false` にした group は、**中の Role とネストした group もまとめてドキュメントに出なくなります。** 中の Role が自分で何と書いていても同じです。

    ```kt
    "build".group {
        documented = false
        "VersionCatalog" { }   // group と一緒にドキュメントから外れる
    }
    ```

    値そのものは中の Role や group に写されません（それぞれ自分が書いた値を持ちます）。自作の processor でこの値を見るときは、`Role.groupPath` をたどって親の group の値も見てください。

</details>

<CodeComparison>
    <CodeComparison.Panel label="group 定義">
        ```kt
        "domain".group {
            title = "Domain レイヤー"
            summary = "アプリ固有の振る舞いと、その対象になる値"
            description = """
                画面にも保存先にも依存しない層です。
            """.trimIndent()

            "UseCase" {
                title = "ユースケース"
                summary = "各画面で発生するアプリ固有の1つの振る舞い"
                layout { "src/main/kotlin/com/example/domain/useCase" / "*UseCase".ktFile() }
            }

            "RepositoryInterface" {
                title = "リポジトリ"
                summary = "データの取得と保存の境界"
                layout { "src/main/kotlin/com/example/domain/repository" / "*Repository".ktFile() }
            }
        }
        ```
    </CodeComparison.Panel>
    <CodeComparison.Panel label="生成されるマークダウン">
        ````md title="domain/README.md"
        [Architecture](../README.md)                  ← パンくず

        # Domain レイヤー                               ← title

        アプリ固有の振る舞いと、その対象になる値          ← summary

        画面にも保存先にも依存しない層です。              ← description

        | Role | Summary |                                 ← 配下の Role の title と summary
        |---|---|
        | [ユースケース](./UseCase.md) | 各画面で発生するアプリ固有の1つの振る舞い |
        | [リポジトリ](./RepositoryInterface.md) | データの取得と保存の境界 |

        ## Placement in this group                           ← 配下の Role の layout { }

        ```
        src/main/kotlin/com/example/domain/
          useCase/*UseCase.kt        ユースケース
          repository/*Repository.kt  リポジトリ
        ```
        ````
    </CodeComparison.Panel>
</CodeComparison>

### トップページ

トップページ（出力先の直下の `README.md`）の見出しと説明は、`architecture { }` の直下に `title` と `description` を書いて設定します。

| プロパティ | 生成されるドキュメントでの役割 | 使用されるページ |
|---|---|---|
| [`title`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-architecture-scope/title.html) | トップページの見出し | `README.md`、すべてのページのパンくず |
| [`description`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/-architecture-scope/description.html) | 見出しの直下の本文 | `README.md` |

<CodeComparison>
    <CodeComparison.Panel label="architecture 定義">
        ```kt
        val projectArchitecture = architecture {
            title = "myapp"
            description = """
                myapp のファイル構成です。

                myapp は **MVVM * Clean Architecture** ベースで設計されています。
            """.trimIndent()

            "domain".group {
                title = "Domain レイヤー"
                summary = "アプリ固有の振る舞いと、その対象になる値"
                "UseCase" { /* ... */ }
            }
        }
        ```
    </CodeComparison.Panel>
    <CodeComparison.Panel label="生成されるマークダウン">
        ```md title="README.md"
        # myapp documentation

        myapp のファイル構成です。

        myapp は **MVVM * Clean Architecture** ベースで設計されています。

        ## Document map

        ### [Domain レイヤー](./domain/README.md)

        アプリ固有の振る舞いと、その対象になる値
        ...
        ```
    </CodeComparison.Panel>
</CodeComparison>

### 独自のセクション

title などデフォルトで用意されているセクションのほかに、独自のセクションをドキュメントへ足したいときは、[`documentSection()`](/katachi/api-docs/katachi/me.tbsten.katachi.dsl/document-section.html) でセクションを定義します。

セクションは `documentSection("見出し")` で宣言し、書き込むためのプロパティを `by` で作ります。

```kt
val TestPolicy = documentSection("テスト方針")
var MetadataScope.testPolicy by TestPolicy
```

<details>
    <summary>セクションを入れ子にする</summary>

    セクションは入れ子にできます。`TestPolicy.documentSection("ユニットテスト")` のように、親のセクションに対して宣言します。
    **見出しのレベルは深さで決まります。** 最上位が `##` で、1段深くなるごとに `#` が1つ増えます。
    親に本文を書いていなくても、子に本文があれば親の見出しは出ます。

    <CodeComparison>
        <CodeComparison.Panel label="セクションの定義">
            ```kt
            val TestPolicy = documentSection("テスト方針")
            var MetadataScope.testPolicy by TestPolicy

            val UnitTest = TestPolicy.documentSection("ユニットテスト")
            var MetadataScope.unitTest by UnitTest

            val projectArchitecture = architecture {
                "UseCase" {
                    title = "ユースケース"
                    summary = "各画面で発生するアプリ固有の1つの振る舞い"
                    example("SignInUseCase", "サインイン")
                    layout { "src/main/kotlin/com/example/useCase" / "*UseCase".ktFile() }

                    unitTest = "Repository を偽物に差し替えて、戻り値を確かめる。"
                }
            }
            ```
        </CodeComparison.Panel>
        <CodeComparison.Panel label="生成されるマークダウン">
            ```md title="UseCase.md"
            [Architecture](README.md)

            # ユースケース

            各画面で発生するアプリ固有の1つの振る舞い

            ## Placement

            | Path | When to use |
            |---|---|
            | `src/main/kotlin/com/example/useCase/*UseCase.kt` |  |

            ## Examples

            - `SignInUseCase` ... サインイン

            ## テスト方針                                  ← 本文は無いが、子があるので出る

            ### ユニットテスト                             ← 1段深いので ###

            Repository を偽物に差し替えて、戻り値を確かめる。
            ```
        </CodeComparison.Panel>
    </CodeComparison>

    独自のセクションは、**組み込みのセクション（`## Placement` / `## Constraints` / `## Examples`）の後ろ**に、定義の中で書いた順に並びます。

</details>

## まとめ

- アーキテクチャ定義に title, summary, description, example などのプロパティを設定すると、ドキュメントを作成できます。

## 次のステップ

- [テンプレートからコード生成](/katachi/ja/guides/generate-code-from-template/) ... 同じ定義からドキュメントではなくコードを生成する方法を学びましょう。
- [ArchitectureProcessor とそのカスタマイズ](/katachi/ja/guides/processor/) ... ドキュメント生成も ArchitectureProcessor の1つです。自分で別の成果物を出す方法を学びましょう。