配置扩展

您编写或使用的扩展可能需要额外的设置来配置其行为。虽然扩展可以利用 playbook 或 Antora 正在构建的内容源中已有的信息,但也可能需要直接配置扩展。扩展可以接受任意数量的属性,这些属性可以是嵌套的,并在 playbook 文件的条目中指定。这些属性可通过名为 config 的上下文变量访问,该变量将传递给扩展的注册函数。

基本配置

假设我们要发布一个名为 humans.txt 的文件,以感谢文档网站的创建者。我们将扩展命名为 humans-txt-extension.js。当然,扩展不知道该归功于谁,所以我们需要向它传递一些配置。

首先,让我们在 playbook 中注册我们的新扩展,并使用 names 关键字传入人员列表。该键的值将是一个包含姓名的数组。

antora:
  extensions:
  - require: ./humans-txt-extension.js
    names:
    - Doc Writer
    - Dr. Austen
    - Emily Story

为了给额外的键留出空间,我们将扩展名的条目从单个(字符串)值转换为映射。require 请求值滑入 require 关键字。这就为定义其他键(在本例中为 name )留出了空间。

现在,让我们编写一个扩展,接受这一配置并用它来创建 humans.txt 文件:

Example 1. humans-txt-extension.js
module.exports.register = function ({ config }) {
  this.on('beforePublish', ({ siteCatalog }) => {
    const teamInfo = '/* TEAM */\n' + config.names.map((name) => `Name: ${name}`).join('\n')
    const contents = Buffer.from(teamInfo + '\n')
    siteCatalog.addFile({ contents, out: { path: 'humans.txt' } })
  })
}

与其他上下文变量一样,扩展的 config 对象也是通过对象重构来访问的。得益于 JavaScript 中的变量作用域,我们仍然可以在 beforePublish 事件的监听器中访问该变量。我们使用它提供的信息来填充 humans.txt 文件的内容,并将其添加到网站目录中。然后,Antora 将在发布的网站中包含 humans.txt 文件。

配置键变换

在 YAML 中,键名使用 snake_case 命名规则。在 JavaScript 中,属性名使用 camelCase 命名约定。为了弥补 YAML 和 JavaScript 命名规则的不匹配,Antora 会自动将 playbook 文件中的 snake_case 键名转换为配置对象上的 camelCase 属性。例如,Antora 会将 cache_dir 转换为 cacheDir。大多数情况下,这不是问题。但是,如果您的扩展将配置或数据传递给其他应用程序,这种转换就会产生问题。

配置数据

要绕过这种配置,可以将键隐藏在 data 键内。数据键内的任何键(任何深度)都会通过,不会被修改。

假设我们要为 humans.txt 文件指定结构化内容。我们不需要 Antora 转换这些结构化内容,因此可以将其存储在名为 data 的键中。

antora:
  extensions:
  - require: ./humans-txt-extension.js
    data:
      TEAM:
      - Lead Writer: Doc Writer
        Contact: doc [at] example.org
        Location: Denver, CO
      - Information Architect: Dr. Austen
        Location: Winchester, Hampshire, England
      - Narrator: Emily Story
        Location: Antwerp, Belgium

现在,扩展可以遍历 config.data 中的键,并布局 humans.txt 文件的内容。

const contents = Buffer.from(
  Object.entries(config.data).reduce((accum, [category, entries]) => {
    if (accum.length) accum.push('')
    accum.push(`/* ${category} */`)
    entries.forEach((entry) => {
      accum.push('')
      for (const [key, val] of Object.entries(entry)) accum.push(`${key}: ${val}`)
    })
    return accum
  }, []).join('\n')
)