---
title: "自定义扩展"
canonical_url: "https://tiptap.zhcndoc.com/hocuspocus/guides/custom-extensions"
---

# 自定义扩展

## 官方扩展

你可以在[这里](https://tiptap.zhcndoc.com/hocuspocus/server/extensions/overview.md)查看我们已经创建的扩展。

## 创建你自己的扩展

Hocuspocus 是用 TypeScript 编写的。你不必一定使用 TypeScript 来编写扩展，但强烈推荐。本文档中我们只介绍 TypeScript 部分。

第一步：创建一个实现 [`Extension`](https://github.com/ueberdosis/hocuspocus/blob/14e5676ff685a1432d87fed780b6cbead12c8122/packages/server/src/types.ts#L35-L57) 接口的新类，并添加所需的钩子。

由于每个钩子都需要返回一个 Promise，最简单的方式是将它们标记为 `async`。

```js
import {
  Extension,
  onChangePayload,
  onConnectPayload,
  onAuthenticatePayload,
  onLoadDocumentPayload,
  onDisconnectPayload,
} from "@hocuspocus/server";

export class MyHocuspocusExtension implements Extension {
  async onLoadDocument(data: onLoadDocumentPayload): Promise<void> {}

  async onChange(data: onChangePayload): Promise<void> {}

  async onConnect(data: onConnectPayload): Promise<void> {}

  async onAuthenticate(data: onAuthenticatePayload): Promise<void> {}

  async onDisconnect(data: onDisconnectPayload): Promise<void> {}

  async onRequest(data: onRequestPayload): Promise<void> {}

  async onUpgrade(data: onUpgradePayload): Promise<void> {}

  async onListen(data: onListenPayload): Promise<void> {}

  async onDestroy(data: onDestroyPayload): Promise<void> {}

  async onConfigure(data: onConfigurePayload): Promise<void> {}
}
```

注意到了吗？这些钩子看起来和我们在之前章节中介绍的钩子非常相似。没错：它们的工作方式也是一样的。所以你应该已经知道它们的作用以及如何使用它们。如果你仍然不确定，可以查看本教程中更详细介绍这些钩子的[钩子章节](https://tiptap.zhcndoc.com/hocuspocus/server/hooks.md)。

现在你可以添加一个构造函数，接受你的扩展配置并合并默认配置。此时创建一个配置接口是个好习惯。

```js
import {
  Extension,
  onChangePayload,
  onConnectPayload,
  onAuthenticatePayload,
  onLoadDocumentPayload,
  onDisconnectPayload,
} from "@hocuspocus/server";

export interface Configuration {
  myConfigurationOption: string;
  myOptionalConfigurationOption: number | undefined;
}

export class MyHocuspocusExtension implements Extension {
  configuration: Configuration = {
    myConfigurationOption: "foobar",
    myOptionalConfigurationOption: 42,
  };

  constructor(configuration?: Partial<Configuration>) {
    this.configuration = { ...this.configuration, ...configuration };
  }

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onLoadDocument(data: onLoadDocumentPayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onChange(data: onChangePayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onConnect(data: onConnectPayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onAuthenticate(data: onAuthenticatePayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onDisconnect(data: onDisconnectPayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onRequest(data: onRequestPayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onUpgrade(data: onUpgradePayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onListen(data: onListenPayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onDestroy(data: onDestroyPayload): Promise<void> {}

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async onConfigure(data: onConfigurePayload): Promise<void> {}
}
```

就是这样。现在只差你写代码了。祝你扩展开发愉快！完成后，你可以像导入其他扩展一样导入并注册你的扩展：

```js
import { Server } from "@hocuspocus/server";
import { MyHocuspocusExtension } from "./extensions/my-hocuspocus-extension";

const server = new Server({
  extensions: [
    new MyHocuspocusExtension({
      myConfigurationOption: "baz",
      myOptionalConfigurationOption: 1337,
    }),
  ],
});

server.listen();
```
