返回介绍

插件

发布于 2020-10-18 07:35:24 字数 26798 浏览 1053 评论 0 收藏 0

Jekyll 支持插件功能,你可以很容易的加入自己的代码。

在 GitHub Pages 使用插件

GitHub Pages 是由 Jekyll 提供技术支持的,考虑到安全因素,所有的 Pages 通过 --safe 选项禁用了插件功能,因此如果你的网站部署在 Github Pages ,那么你的插件不会工作。

不过仍然有办法发布到 GitHub Pages,你只需在本地做一些转换,并把生成好的文件上传到 Github 替代 Jekyll 就可以了。

安装插件

可以使用以下三种方式安装插件:

  1. 在网站根下目录建立 _plugins 文件夹,插件放在这里即可。 Jekyll 运行之前,会加载此目录下所有以 *.rb 结尾的文件。
  2. 在你的_config.yml文件,添加一个键为gems的新数组,其值为你想要使用的gem插件的名字,例如:

     gems: [jekyll-coffeescript, jekyll-watch, jekyll-assets]
     # This will require each of these gems automatically.
    

    然后安装插件使用命令 gem install jekyll-coffeescript jekyll-watch jekyll-assets

  3. Gemfile 中的一个Bundler组里添加相关的插件,例如:

     group :jekyll_plugins do
       gem "my-jekyll-plugin"
       gem "another-jekyll-plugin"
     end
    

    然后需要从Bundler组中安装所有插件,使用命令bundle install

_plugins, _config.yml and Gemfile 可以同时使用

如果你愿意,可以在网站中同时使用上述安装插件的方法,使用一种安装方法并不会影响别的方法生效。

通常,插件最终会被放在以下的目录中:

  1. 生成器 - Generators
  2. 转换器 - Converters
  3. 命令 - Commands
  4. 标记 - Tags
  5. 钩子 - Hooks

生成器 - Generators

当你需要Jekyll根据你自己的规则来添加额外的内容时,你可以创建一个生成器。

生成器是 Jekyll:Generator 的子类,定义了一个 generate 方法, 接收一个Jekyll::Site类型的实例, 方法的返回值会被忽略。

生成器在Jekyll生成现存内容详细目录之后,网站生成之前运行, 含有YAML头信息的页面储存为Jekyll::Page实例,可以通过site.pages变量获取, 静态文件储存为Jekyll::StaticFile实例,可以通过site.static_files变量获取, 详情见变量文档Jekyll::Site

比如,生成器可以为模板变量注入构建过程中计算出的变量值,在下面的例子中, 我们在生成器中为模板reading.html的两个变量ongoingdone赋了值:

module Reading
  class Generator < Jekyll::Generator
    def generate(site)
      ongoing, done = Book.all.partition(&:ongoing?)

      reading = site.pages.detect {|page| page.name == 'reading.html'}
      reading.data['ongoing'] = ongoing
      reading.data['done'] = done
    end
  end
end

下面是一个更复杂的生成器例子,可以生成新的页面:

module Jekyll

  class CategoryPage < Page
    def initialize(site, base, dir, category)
      @site = site
      @base = base
      @dir = dir
      @name = 'index.html'
      self.process(@name)
      self.read_yaml(File.join(base, '_layouts'), 'category_index.html')
      self.data['category'] = category

      category_title_prefix = site.config['category_title_prefix'] || 'Category: '      self.data['title'] = "#{category_title_prefix}#{category}"
    end
  end

  class CategoryPageGenerator < Generator
    safe true

    def generate(site)
      if site.layouts.key? 'category_index'        dir = site.config['category_dir'] || 'categories'        site.categories.keys.each do |category|
site.pages << CategoryPage.new(site, site.source, File.join(dir, category), category)
        end
      end
    end
  end

end

本例中,生成器在 categories 下生成了一系列文件。并使用布局 category_index.html 列出所有的文章。

生成器只需要实现一个方法:

MethodDescription

generate

String output of the content being generated.

转换器 - Converters

如果想使用一个新的标记语言,可以用你自己的转换器实现,Markdown 和 Textile 就是这样实现的。

记住你的 YAML 头信息

Jekyll 只会转换带有 YAML 头信息的文件,即使你使用了插件也不行。

下边的例子实现了一个转换器,他会用 UpcaseConverter 来转换所有以 .upcase 结尾的文件。

module Jekyll
  class UpcaseConverter < Converter
    safe true
    priority :low

    def matches(ext)
      ext =~ /^\.upcase$/i
    end

    def output_ext(ext)
      ".html"
    end

    def convert(content)
      content.upcase
    end
  end
end

转换器需要最少实现以下 3 个方法:

方法描述

matches

检查文件后缀名是否是所要的,传入的参数是文件的后缀名(包括点号),接受的返回值是 truefalse

output_ext

生成文件的后缀名(包括点号),通常是 ".html"

convert

转换逻辑,传入原始文件内容(不包含YAML头信息),返回值需要是 String 。

在上边的例子中, UpcaseConverter#matches 检查文件后缀名是不是 .upcase ;UpcaseConverter#convert 会处理检查成功文件的内容,即将所有的字符串变成大写;最终,保存的结果将以作为后缀名 .html

命令 - Commands

从2.5.0版本开始,Jekyll可以使用插件提供的子命令来扩展jekyll命令。 可以通过在Gemfile:jekyll_plugins组中包括相关的插件来实现:

group :jekyll_plugins do
  gem "my_fancy_jekyll_plugin"
end

每个Command必须是Jekyll::Command类的子类,而且必须要包含类方法init_with_program,例如:

class MyNewCommand < Jekyll::Command
  class << self
    def init_with_program(prog)
      prog.command(:new) do |c|
        c.syntax "new [options]"
        c.description 'Create a new Jekyll site.'
        c.option 'dest', '-d DEST', 'Where the site should go.'
        c.action do |args, options|
Jekyll::Site.new_site_at(options['dest'])
        end
      end
    end
  end
end

命令应该实现这个单例方法:

方法描述

init_with_program

这个方法接受一个参数, Mercenary::Program 实例,表示Jekyll程序本身,程序之上,命令可以通过上述方式创建,详情可以参见Github.com上的Mercenary库。

标记 - Tags

如果你想使用 liquid 标记,你可以这样做。 Jekyll 官方的例子有 highlightinclude 等标记。下边的例子中,自定义了一个 liquid 标记,用来输出当前时间:

module Jekyll
  class RenderTimeTag < Liquid::Tag

    def initialize(tag_name, text, tokens)
      super
      @text = text
    end

    def render(context)
      "#{@text} #{Time.now}"
    end
  end
end

Liquid::Template.register_tag('render_time', Jekyll::RenderTimeTag)

liquid 标记最少需要实现如下方法:

方法描述

render

输出标记的内容。

你必须同时用 Liquid 模板引擎注册自定义标记,比如:

Liquid::Template.register_tag('render_time', Jekyll::RenderTimeTag)

对于上边的例子,你可以把如下标记放在页面的任何位置:

<p>{% render_time page rendered at: %}</p>

我们在页面上会得到如下内容:

<p>page rendered at: Tue June 22 23:38:47 –0500 2010</p>

Liquid 过滤器

你可以像上边那样在 Liquid 模板中加入自己的过滤器。过滤器会把自己的方法暴露给 liquid。所有的方法都必须至少接收一个参数,用来传输入内容;返回值是过滤的结果。

module Jekyll
  module AssetFilter
    def asset_url(input)
      "http://www.example.com/#{input}?#{Time.now.to_i}"
    end
  end
end

Liquid::Template.register_filter(Jekyll::AssetFilter)
提示:用 Liquid 访问 site 对象

Jekyll 允许通过 Liquid 的context.registers 特性来访问 site 对象。比如可以用 context.registers.config 访问配置文件 _config.yml

Flags

当写插件时,有两个标记需要注意:

标记描述

safe

告诉 Jekyll 此插件是否可以安全的执行任意代码。 GitHub Pages 用他来决定那个插件可以使用,哪些不可以使用。如果你的插件不允许执行任意代码,把它设为 true 即可。 GitHub Pages 仍然不会加载你的插件,但是如果你把他夹杂到核心中,最后保证此值设置的正确!

priority

此标记决定加载插件的顺序。可以是这些值::lowest, :low, :normal, :high, 还有 :highest。优先级高的先执行,优先级低的后执行。

以上边例子的插件为例,应该这样设置这两个标记:

module Jekyll
  class UpcaseConverter < Converter
    safe true
    priority :low
    ...
  end
end

钩子 - Hooks

通过使用钩子,你的插件可以精细控制构建过程中的各个方面。 如果你的插件定义了钩子,Jekyll就会在预定义时调用钩子。

钩子需要注册一个容器名称和事件名称,可以使用 Jekyll::Hooks.register 来注册, 传递一个容器名称、事件名称,以及钩子触发时调用的代码。 比如,假设你想要在 Jekyll 每次渲染博客时执行一些自定义的功能代码,你可以这样注册钩子:

Jekyll::Hooks.register :posts, :post_render do |post|
  # Jekyll 渲染博客后要调用的代码
end

Jekyll 分别为 :site:pages:posts:documents 提供了钩子。 在任何情况下,Jekyll 都会以容器对象作为第一个回调参数来调用你的钩子, 但是所有的 :pre_render:site, :post_render钩子都会提供一个负载哈希值作为第二个参数。 如果是 :pre_render,负载可以让你完全掌控渲染过程中的变量。 若是 :site, :pre_render,负载包括渲染所有网站的最后值(可以用于站点地图,订阅等)

完整的钩子列表如下:

容器名事件名调用时机

:site

:after_init

在网站初始化时,但是在设置和渲染之前,适合用来修改网站的配置项

:site

:after_reset

网站重置之后

:site

:post_read

在网站数据从磁盘中读取并加载之后

:site

:pre_render

在渲染整个网站之前

:site

:post_render

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

:site

:post_write

在将整个网站写入磁盘之后

:pages

:post_init

每次页面被初始化的时候

:pages

:pre_render

在渲染页面之前

:pages

:post_render

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

:pages

:post_write

在页面写入磁盘之后

:posts

:post_init

每次博客被初始化的时候

:posts

:pre_render

在博客被渲染之前

:posts

:post_render

在博客渲染之后,但是在被写入磁盘之前

:posts

:post_write

在博客被写入磁盘之后

:documents

:post_init

每次文档被初始化的时候

:documents

:pre_render

在渲染文档之前

:documents

:post_render

在渲染文档之后,但是在被写入磁盘之前

:documents

:post_write

在文档被写入磁盘之后

可用的插件

下边的插件,你可以按需索取:

生成器

转换器

过滤器

标签

集合

其他

期待你的作品

如果你有一个 Jekyll 插件并且愿意加到这个列表中来,可以阅读此须知,并参照着来做。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文