# Fumadocs (Framework Mode, Astro): 產生頁面
URL: /zh-TW/docs/astro/integrations/asyncapi/generate-files
Source: https://raw.githubusercontent.com/fuma-nama/fumadocs/refs/heads/main/apps/docs/content/docs/(framework)/[framework]/integrations/asyncapi/generate-files.zh-TW.mdx

從 AsyncAPI schema 產生頁面。

`staticSource()` 與 `dynamicSource()` 會為您的 [`loader()`](/docs/astro/integrations/asyncapi#generate-pages) 產生頁面，而 `generateFiles()` 則會將頁面以 MDX 檔案的形式寫入您的內容目錄。這幾個函式接受相同的選項。

頁面內容仍由 `<AsyncAPIPage />` 負責算繪，產生器只負責編排每個頁面中的 operation。

## 選項 [#options]

### `per` [#per]

自訂每個頁面包含的內容，預設為 `operation`。

<Callout>
Operation 指的是具有特定動作的 AsyncAPI operation，例如
`receiveLightMeasurement:receive`。
</Callout>

| 模式        | 內容                          | 檔案路徑                |
| --------- | --------------------------- | ------------------- |
| tag       | 具有相同標籤的 operation           | `{tag_name}.mdx`    |
| file      | 位於同一個 schema 檔案中的 operation | `{file_name}.mdx`   |
| operation | 每個 operation                | `{operationId}.mdx` |
| custom    | 請參閱下方說明                     | 不適用                 |

```ts
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  per: 'tag',
});
```

設為 `custom` 時，您可以傳入一個函式，完全自訂產生流程：

```ts title="Example"
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  per: 'custom',
  toPages(builder) {
    for (const [id, item] of Object.entries(builder.document.operations ?? {})) {
      const operation = builder.dereferenceShallow(item);

      builder.create({
        type: 'operation',
        schemaId: builder.id,
        item: { id, action: operation.action },
        path: `${id}.mdx`,
        info: {
          title: operation.title ?? id,
          description: operation.description,
        },
      });
    }
  },
});
```

設為 `tag` 時，會依名稱比對標籤。您可以在 `info.tags` 中定義標籤，為對應頁面加上描述，並透過 `x-displayName` 控制標題。沒有標籤的 operation 會歸類在 `unknown` 之下。

```yaml title="asyncapi.yaml"
info:
  tags:
    - name: lighting
      description: Operations related to streetlights.
      x-displayName: Lighting
```

### `groupBy` [#groupby]

在 `operation` 模式下，您可以用資料夾將輸出檔案分組。

| 值          | 輸出                                |
| ---------- | --------------------------------- |
| tag        | `{tag}/{operationId}.mdx`         |
| channel    | `{channel key}/{operationId}.mdx` |
| none (預設)  | `{operationId}.mdx`               |

```ts
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  per: 'operation',
  groupBy: 'tag',
});
```

### `name` [#name]

用來控制所產生頁面檔案名稱的函式。

```ts
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  name(output) {
    if (output.type === 'operation') {
      const operation = this.dereferenceShallow(this.document.operations?.[output.item.id]);
      console.log(operation);

      return `my-dir/${output.item.id}`;
    }

    return 'my-dir/filename';
  },
});
```

您也可以使用 `algorithm` 選項：

```ts
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  // v2（預設）：使用 operation ID
  // v1：使用 `{operationId}/{action}`
  name: { algorithm: 'v1' },
});
```

### `meta` [#meta]

自動產生 [`meta.json`](/docs/astro/page-conventions#meta) 檔案。

您隨時都可以手動定義 `meta.json` 檔案，以保有最大的彈性。

```ts
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  meta: true,
});
```

或是自訂資料夾的呈現方式：

```ts
import { asyncapi } from '@/lib/asyncapi';

await asyncapi.staticSource({
  meta: {
    folderStyle: 'separator',
  },
});
```

## MDX 檔案 [#mdx-files]

若要將頁面輸出為 MDX 檔案，請建立一個指令碼：

```ts title="scripts/generate-docs.ts"
import { generateFiles } from '@fumadocs/asyncapi';
import { asyncapi } from '@/lib/asyncapi';

void generateFiles({
  input: asyncapi,
  output: './content/docs',
  // 建議啟用此選項
  // 請確保 operation 的描述不會破壞 MDX 語法。
  includeDescription: true,
});
```

使用指令碼產生文件：

```bash
bun ./scripts/generate-docs.ts
```

將 `AsyncAPIPage` 元件加入您的 MDX 元件中。產生的檔案會使用 `<AsyncAPIPage />` 標籤。

```tsx title="src/components/mdx.tsx"
import { AsyncAPIPage } from '@/components/api-page'; // [!code ++]

export default getMDXComponents({
  wrapper: DocsBody,
  // [!code ++]
  AsyncAPIPage: (props) => <AsyncAPIPage {...props} preloaded={{ docs: {} }} />,
});
```

MDX 元件模組由所有頁面共用，因此無法逐頁預先載入文件。請改為傳入 [`loadDocument`](/docs/astro/integrations/asyncapi/server#loading-documents-once) 來載入文件。

將外掛加入您的 `loader()`：

```ts title="lib/source.ts"
import { asyncapi } from '@/lib/asyncapi';
import { loader } from 'fumadocs-core/source';

export const source = loader({
  // [!code ++:2] 選用：在頁面樹的每個頁面項目上加上訊息的傳遞方向
  plugins: [asyncapi.loaderPlugin()],
});
```

`generateFiles()` 也支援下列選項。

### `index` [#index]

產生索引檔案，以卡片形式連結至各個產生的頁面。

```ts
import { generateFiles } from '@fumadocs/asyncapi';

void generateFiles({
  index: {
    // 用於產生 `href`
    url: {
      baseUrl: '/docs',
      contentDir: './content/docs',
    },
    items: [
      {
        // 輸出路徑
        path: 'index.mdx',
        // 選用：限制輸入檔案（與伺服器端的 `input` 欄位相同）
        only: ['streetlights.yaml'],
        // 選用：設定 frontmatter
        description: 'All available pages',
      },
    ],
  },
});
```

### `imports` [#imports]

在產生的 MDX 檔案中加入自訂匯入。若要在產生的文件中引入元件、工具函式或其他相依套件，這個選項就很實用。

```ts
import { generateFiles } from '@fumadocs/asyncapi';

void generateFiles({
  imports: [
    {
      names: ['API_BASE_URL'],
      from: '@/constants',
    },
  ],
});
```

這會在所有產生的 MDX 檔案中加入以下匯入語句：

```ts
import { API_BASE_URL } from '@/constants';
```

### `frontmatter` [#frontmatter]

自訂 MDX 檔案的 frontmatter。

預設包含以下欄位：

| 屬性            | 說明                         |
| ------------- | -------------------------- |
| `title`       | 頁面標題                       |
| `description` | 頁面描述                       |
| `full`        | 一律為 true，專為 Fumadocs UI 加入 |
| `_asyncapi`   | 內部屬性                       |

```ts
import { generateFiles } from '@fumadocs/asyncapi';

void generateFiles({
  frontmatter: (title, description) => ({
    myProperty: 'hello',
  }),
});
```

### `addGeneratedComment` [#addgeneratedcomment]

在產生的檔案開頭加入註解，標示該檔案為自動產生。

```ts
import { generateFiles } from '@fumadocs/asyncapi';

void generateFiles({
  // 加入預設註解
  addGeneratedComment: true,

  // 或提供自訂註解
  addGeneratedComment: 'Custom auto-generated comment',

  // 或停用註解
  addGeneratedComment: false,
});
```