Skip to content

Hook 插件 ​

这种类型的插件主要特点是可以介入 Paperlib 的运行流程,修改流程里面的参数,数据流等。比如,当用户拖入一个论文 PDF 时,Paperlib 会搜索该文件的元数据,生成一个 PaperEntity 存在数据库中。我们可以通过 Hook 插件来介入这个过程,比如在生成 PaperEntity 之后,我们将元数据中的某部分进行修改。

实际上,在 Paperlib 3.0 中,官方所有的 Metadata Scraper 都是用插件来实现的。

插件类结构 ​

在这里我们给出一个示例结构,当然你可以根据自己的需要进行修改。

typescript
class HookExtension extends PLExtension {
  constructor() {
    // 你可以在这里设置插件的 id,默认设置
    super(...)
  }

  async initialize() {
    // 在这里注册 Hook 点
    this.disposeCallbacks.push(
      PLAPI.hookService.hookModify(
        "scrapeEntryBefore",
        this.id,
        "modifyPayloads",
      ),
    );

    ...
  }

  async dispose() {
    // 在这里取消注册,事件监听
    for (const disposeCallback of this.disposeCallbacks) {
      disposeCallback();
    }
  }

  async modifyPayloads(payloads: SourcePayload[]) {
    // 在这里修改 payloads
    ...

    return [payloads]
  }
}

钩子点 ​

在 Paperlib 中,我们在不同的地方,放置了不同名字的钩子点。一个钩子插件可以注册到对应的钩子点来介入 Paperlib 的运行流程。一共有两种类型的钩子点。

Modify 钩子点 ​

  • 目的:这种类型的钩子点,用于修改钩子点传来的参数,或者参数内的变量,而不能改变类型,最后返回修改后的参数。

  • 回调返回值类型:该类钩子要求回调函数的返回值必须是一个数组,数组的每个元素,对应着传入的参数数组。比如,钩子点传入的参数为 (arg1: string, arg2: {value: number}),在钩子的回调函数中可以修改 arg1 为别的字符串,修改 arg2.value 为别的数字,但是不能修改 arg1 的类型为数字,或者修改 arg2 的类型为别的类型。回调函数的返回值必须为修改后的参数组成的数组:[arg1, arg2]。注意,即使传入参数仅为一个,也需要返回元素数量为1的数组。因为传入参数永远被视作一个数组

Transform 钩子点 ​

  • 目的:这种类型的钩子点,可以修改 Paperlib 的运行流程中的数据流。用于把传入参数转换为其他形式的数据,然后返回。
  • 回调返回值类型:可以为其他类型,但是通常不同钩子点有期望的返回值类型。比如,scrapeEntry 钩子点,期望的返回值类型为 PaperEntity 数组。

可用钩子点 ​

  • modifyHookPoint

    • beforeScrapeEntry - 在论文 payload 进入 scrape 流程之前。
    • afterScrapeEntry - 在论文 payload 完成 scrape 流程转换为了 PaperEntity 草稿之后。
    • beforeScrapeMetadata - 在论文草稿进入 scrape metadata 流程之前。
    • scrapeMetadata - 在论文草稿进行 scrape metadata 流程时。
    • afterScrapeMetadata - 在论文草稿完成 scrape metadata 流程之后。
    • locateFile - 在论文草稿进行 locate file 流程时。
  • transformhookPoint

    • scrapeEntry - 在论文 payload 进入 scrape 流程,转换为 PaperEntity 时。

Paperlib 的详细流程和钩子点的详细介绍,请参考 运行流程与钩子。

钩子注册 ​

我们可以通过 PLAPI.hookService.hookModify 方法来注册插件所使用的 Modify 钩子点,或者使用 PLAPI.hookService.hookTransform 方法来注册插件所使用的 Transform 钩子点:

typescript
PLAPI.hookService.hookModify(
  hookPoint: string,
  extensionId: string,
  callbackFuncName: string,
)

PLAPI.hookService.hookTransform(
  hookPoint: string,
  extensionId: string,
  callbackFuncName: string,
)
  • hookPoint:Paperlib 提供的钩子点的 id,想要设置钩子的位置。
  • extensionId:插件的 id,用于标识插件。
  • callbackFuncName:插件中的回调函数的名称,用于在钩子点触发时调用。

钩子回调函数 ​

钩子回掉函数的名字,需要和注册时的 callbackFuncName 保持一致。钩子回调函数的参数,以及返回值的形式,根据钩子位置不同,以及钩子类型不同,会有所不同。详细介绍请参考 运行流程与钩子。

在钩子点小节中我们总体上描述了两类钩子回调函数的形式。在此不再赘述。

超时限制 ​

因为钩子类插件会侵入 Paperlib 的运行流程,所以我们需要对钩子回调函数的运行时间进行限制。如果钩子回调函数运行时间超过了预设时间,Paperlib 会强制绕过该回调函数的运行:

  • modifyHookPoint:默认超时时间为 5 秒。
  • transformHookPoint:默认超时时间为 15 秒。

额外钩子点 ​

尽管我们的钩子机制支持我们几乎在任何地方放置钩子,但是因为钩子类插件的侵入性,我们非常谨慎的开放钩子点。如果目前的钩子点无法满足您插件的开发需求,请前往 GitHub Discussions 提出您的需求,我们会考虑在未来的版本中添加新的钩子点。

Created by Future Scholars. Contact: hi@paperlib.app