钩子

使用钩子,你的插件可以对构建流程的各个方面进行精细控制。如果你的插件定义了任何钩子,Jekyll 将在预定义的点调用它们。

钩子注册到所有者和事件名称。要注册一个,你需要调用 Jekyll::Hooks.register,并传递钩子所有者、事件名称以及在触发钩子时要调用的代码。例如,如果你想在 Jekyll 每次渲染页面时执行一些自定义功能,你可以这样注册一个钩子

Jekyll::Hooks.register :pages, :post_render do |page|
  # code to call after Jekyll renders a page
end

注意:此处提到的 :post_convert 事件是 v4.2.0 中引入的一项功能。

开箱即用,Jekyll 为所有者预定义了挂钩点 :site:pages:documents:clean。此外,为 :documents 定义的挂钩点仅可通过调用集合类型来用于单个集合。即 :posts 用于集合 _posts 中的文档,:movies 用于集合 _movies 中的文档。在所有情况下,Jekyll 使用所有者对象作为第一个回调参数来调用挂钩。

每个注册的挂钩所有者都支持以下事件 — :post_init:pre_render:post_convert:post_render:post_write — 但是,:site 所有者被设置为响应特殊事件名称。有关详细信息,请参阅后续部分。

所有 :pre_render 挂钩和 :site, :post_render 挂钩还将提供一个 payload 哈希作为第二个参数。虽然在 :pre_render 事件的情况下,payload 可以让你完全控制渲染期间可用的变量,但在 :site, :post_render 事件中,payload 包含渲染整个网站后的最终值(对网站地图、源等很有用)。

内置挂钩所有者和事件

可用挂钩的完整列表

所有者 事件 触发于

:site

涵盖整个网站

:after_init

网站初始化后。适合修改网站的配置。每个构建/服务会话触发一次

:after_reset

网站在重新生成期间重置后

:post_read

从磁盘读取并加载所有源文件后

:pre_render

渲染整个网站之前

:post_render

渲染整个网站后,但在写入任何文件之前

:post_write

将所有已渲染文件写入磁盘后

:pages

允许对网站中的所有页面进行细粒度控制

:post_init

每当初始化页面时

:pre_render

在渲染页面之前

:post_convert

在转换页面内容后,但在渲染页面布局之前

:post_render

在渲染页面后,但在将其写入磁盘之前

:post_write

在将页面写入磁盘后

:documents

允许对网站中的所有文档进行细粒度控制,包括文章和用户定义集合中的文档

:post_init

每当初始化任何文档时

:pre_render

在渲染文档之前

:post_convert

在转换文档内容后,但在渲染文档布局之前

:post_render

在渲染文档后,但在将其写入磁盘之前

:post_write

在将文档写入磁盘后

:posts

允许对网站中的所有文章进行细粒度控制,而不影响用户定义集合中的文档

:post_init

每当初始化文章时

:pre_render

在渲染文章之前

:post_convert

在转换文章内容后,但在渲染文章布局之前

在转换文章内容后,但在渲染文章布局之前

:post_render

在渲染文章后,但在将其写入磁盘之前

:post_write

在将文章写入磁盘后

:clean

在网站清理阶段确定要删除的过时文件列表上的细粒度控制。

:on_obsolete

在构建网站的目标之前清理该目标

自定义 Jekyll 对象的挂钩

你还可以注册和触发插件引入的 Jekyll 对象的挂钩。只需在所需的自定义类中的位置将 trigger 调用放在合适的 owner 名称下,并通过插件注册 owner 即可。

为了说明,考虑以下插件,它为每个初始化的自定义 Excerpt 对象实现了自定义功能

module Foobar
  class HookedExcerpt < Jekyll::Excerpt
    def initialize(doc)
      super
      trigger_hooks(:post_init)
    end

    def output
      @output ||= trigger_hooks(:post_render, renderer.run)
    end

    def renderer
      @renderer ||= Jekyll::Renderer.new(
        doc.site, self, site.site_payload
      )
    end

    def trigger_hooks(hook_name, *args)
      Jekyll::Hooks.trigger :excerpts, hook_name, self, *args
    end
  end
end

Jekyll::Hooks.register :excerpts, :post_init do |excerpt|
  Jekyll.logger.debug "Initialized:",
                      "Hooked Excerpt for #{excerpt.doc.inspect}"
end

Jekyll::Hooks.register :excerpts, :post_render do |excerpt, output|
  return output unless excerpt.doc.type == :posts
  Foobar.transform(output)
end