使用上下文变量
Antora扩展的主要目标是允许您编写代码,以便在关键转换点将代码连接到生成过程,并在那时访问流经系统的变量。一旦开始访问这些上下文变量,扩展的乐趣就真正开始了。
访问上下文变量
上下文变量是在事件发出时处于作用域中的变量,并且生成器将其绑定到生成器上下文。通过从扩展中访问上下文变量,您可以:
-
从对象中读取属性,
-
在对象上调用方法,或
-
修改对象上的属性(前提是对象未被冻结)。
在更新上下文变量中,您将学习如何用对象的代理替换变量,这是另一种选择。
让我们继续扩展我们的扩展,以检索站点目录并添加一个.nojekyll文件作为替代方案,而不是使用补充UI来实现此目的。
module.exports.register = function () {
this.on('beforePublish', ({ siteCatalog }) => {
siteCatalog.addFile({ contents: Buffer.alloc(0), out: { path: '.nojekyll' } })
})
}
在示例 1中,使用{ siteCatalog }
从上下文中检索站点目录。要检索多个变量,请使用逗号分隔变量名称(例如,{ playbook, siteCatalog }
)。
还可以直接从生成器上下文中使用getVariables
方法检索上下文变量:
const { siteCatalog } = this.getVariables()
除了内置上下文变量之外,您的扩展还可以访问其他扩展文档和发布的上下文变量。
更新上下文变量
大多数扩展读取上下文变量并与引用对象的方法交互,但它们也可以添加或替换上下文变量。一个用例是定义其他扩展或同一扩展的监听器可以访问的新变量。这是通过生成器传递附加数据的一种方式。另一个用例是替换生成器使用的内置变量,也许通过代理。如果您需要大幅改变Antora的行为,并且无法通过向目录添加或删除文件来实现,您可能需要这样做。
让我们考虑一个用例,我们想要代理内容目录以防止其注册任何别名。在示例 2中,我们监听contentClassified
事件,检索contentCatalog
上下文变量,并用对象的代理替换变量。
module.exports.register = function () {
this.on('contentClassified', function ({ contentCatalog }) {
contentCatalog = new Proxy(contentCatalog, {
get(target, property) {
return property === 'registerPageAlias' ? () => undefined : target[property]
},
})
this.updateVariables({ contentCatalog })
})
}
示例 2为您提供了替换registerPageAlias 函数的起点。 |
请注意,前面的示例使用正式的function
关键字来声明监听器,而不是箭头函数。以这种方式定义函数使我们可以访问标准的this
关键字,它是对生成器上下文的引用。当监听器注册时,Antora将函数绑定到生成器上下文,使得在函数内部可以使用标准的this
关键字访问生成器上下文。
上下文变量锁定
一旦内置上下文变量被视为已建立,通常是在引入它的事件之后,该变量就会被锁定。这个规则有例外,但总体上是成立的。锁定的变量无法被替换。任何尝试这样做的操作都会导致错误。
已锁定的变量以及何时锁定它们在生成器事件参考页面上有指示。
内置变量被锁定的原因有两个。首先,它表示变量应该在必要时被替换。其次,它允许站点生成器和其他扩展存储对该变量的本地引用,而无需担心检查它是否被替换。
锁定的变量只阻止该变量本身被替换。仍然可以修改变量引用的对象,例如添加、更新或删除对象的属性。唯一的例外是playbook,它是一个冻结的对象。