Merge pull request #3553 from stevecrozz/jekyll-hooks
Merge pull request 3553
This commit is contained in:
commit
ce9fcfaebb
|
@ -0,0 +1,327 @@
|
||||||
|
Feature: Hooks
|
||||||
|
As a plugin author
|
||||||
|
I want to be able to run code during various stages of the build process
|
||||||
|
|
||||||
|
Scenario: Run some code after site reset
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register :site, :after_reset do |site|
|
||||||
|
pageklass = Class.new(Jekyll::Page) do
|
||||||
|
def initialize(site, base)
|
||||||
|
@site = site
|
||||||
|
@base = base
|
||||||
|
@data = {}
|
||||||
|
@dir = '/'
|
||||||
|
@name = 'foo.html'
|
||||||
|
@content = 'mytinypage'
|
||||||
|
|
||||||
|
self.process(@name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
site.pages << pageklass.new(site, site.source)
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
When I run jekyll build
|
||||||
|
Then the _site directory should exist
|
||||||
|
And I should see "mytinypage" in "_site/foo.html"
|
||||||
|
|
||||||
|
Scenario: Modify the payload before rendering the site
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "index.html" page that contains "{{ site.injected }}!"
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register :site, :pre_render do |site, payload|
|
||||||
|
payload['site']['injected'] = 'myparam'
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
When I run jekyll build
|
||||||
|
Then the _site directory should exist
|
||||||
|
And I should see "myparam!" in "_site/index.html"
|
||||||
|
|
||||||
|
Scenario: Modify the site contents after reading
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "page1.html" page that contains "page1"
|
||||||
|
And I have a "page2.html" page that contains "page2"
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register :site, :post_read do |site|
|
||||||
|
site.pages.delete_if { |p| p.name == 'page1.html' }
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
When I run jekyll build
|
||||||
|
Then the _site directory should exist
|
||||||
|
And the "_site/page1.html" file should not exist
|
||||||
|
And I should see "page2" in "_site/page2.html"
|
||||||
|
|
||||||
|
Scenario: Work with the site files after they've been written to disk
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register :site, :post_write do |site|
|
||||||
|
firstpage = site.pages.first
|
||||||
|
content = File.read firstpage.destination(site.dest)
|
||||||
|
File.write(File.join(site.dest, 'firstpage.html'), content)
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And I have a "page1.html" page that contains "page1"
|
||||||
|
When I run jekyll build
|
||||||
|
Then the _site directory should exist
|
||||||
|
And I should see "page1" in "_site/firstpage.html"
|
||||||
|
|
||||||
|
Scenario: Alter a page right after it is initialized
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register :page, :post_init do |page|
|
||||||
|
page.name = 'renamed.html'
|
||||||
|
page.process(page.name)
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And I have a "page1.html" page that contains "page1"
|
||||||
|
When I run jekyll build
|
||||||
|
Then the _site directory should exist
|
||||||
|
And I should see "page1" in "_site/renamed.html"
|
||||||
|
|
||||||
|
Scenario: Alter the payload for one page but not another
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register :page, :pre_render do |page, payload|
|
||||||
|
payload['myparam'] = 'special' if page.name == 'page1.html'
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And I have a "page1.html" page that contains "{{ myparam }}"
|
||||||
|
And I have a "page2.html" page that contains "{{ myparam }}"
|
||||||
|
When I run jekyll build
|
||||||
|
Then I should see "special" in "_site/page1.html"
|
||||||
|
And I should not see "special" in "_site/page2.html"
|
||||||
|
|
||||||
|
Scenario: Modify page contents before writing to disk
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "index.html" page that contains "WRAP ME"
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register :page, :post_render do |page|
|
||||||
|
page.output = "{{{{{ #{page.output.chomp} }}}}}"
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
When I run jekyll build
|
||||||
|
Then I should see "{{{{{ WRAP ME }}}}}" in "_site/index.html"
|
||||||
|
|
||||||
|
Scenario: Work with a page after writing it to disk
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "index.html" page that contains "HELLO FROM A PAGE"
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register :page, :post_write do |page|
|
||||||
|
require 'fileutils'
|
||||||
|
filename = page.destination(page.site.dest)
|
||||||
|
FileUtils.mv(filename, "#{filename}.moved")
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
When I run jekyll build
|
||||||
|
Then I should see "HELLO FROM A PAGE" in "_site/index.html.moved"
|
||||||
|
|
||||||
|
Scenario: Alter a post right after it is initialized
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
# rot13 translate
|
||||||
|
Jekyll::Hooks.register :post, :post_init do |post|
|
||||||
|
post.content.tr!('abcdefghijklmnopqrstuvwxyz',
|
||||||
|
'nopqrstuvwxyzabcdefghijklm')
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And I have a _posts directory
|
||||||
|
And I have the following posts:
|
||||||
|
| title | date | layout | content |
|
||||||
|
| entry1 | 2015-03-14 | nil | content for entry1. |
|
||||||
|
When I run jekyll build
|
||||||
|
Then the _site directory should exist
|
||||||
|
And I should see "pbagrag sbe ragel1." in "_site/2015/03/14/entry1.html"
|
||||||
|
|
||||||
|
Scenario: Alter the payload for certain posts
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
# Add myvar = 'old' to posts before 2015-03-15, and myvar = 'new' for
|
||||||
|
# others
|
||||||
|
Jekyll::Hooks.register :post, :pre_render do |post, payload|
|
||||||
|
if post.date < Time.new(2015, 3, 15)
|
||||||
|
payload['myvar'] = 'old'
|
||||||
|
else
|
||||||
|
payload['myvar'] = 'new'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And I have a _posts directory
|
||||||
|
And I have the following posts:
|
||||||
|
| title | date | layout | content |
|
||||||
|
| entry1 | 2015-03-14 | nil | {{ myvar }} post |
|
||||||
|
| entry2 | 2015-03-15 | nil | {{ myvar }} post |
|
||||||
|
When I run jekyll build
|
||||||
|
Then I should see "old post" in "_site/2015/03/14/entry1.html"
|
||||||
|
And I should see "new post" in "_site/2015/03/15/entry2.html"
|
||||||
|
|
||||||
|
Scenario: Modify post contents before writing to disk
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
# Replace content after rendering
|
||||||
|
Jekyll::Hooks.register :post, :post_render do |post|
|
||||||
|
post.output.gsub! /42/, 'the answer to life, the universe and everything'
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And I have a _posts directory
|
||||||
|
And I have the following posts:
|
||||||
|
| title | date | layout | content |
|
||||||
|
| entry1 | 2015-03-14 | nil | {{ 6 \| times: 7 }} |
|
||||||
|
| entry2 | 2015-03-15 | nil | {{ 6 \| times: 8 }} |
|
||||||
|
When I run jekyll build
|
||||||
|
Then I should see "the answer to life, the universe and everything" in "_site/2015/03/14/entry1.html"
|
||||||
|
And I should see "48" in "_site/2015/03/15/entry2.html"
|
||||||
|
|
||||||
|
Scenario: Work with a post after writing it to disk
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
# Log all post filesystem writes
|
||||||
|
Jekyll::Hooks.register :post, :post_write do |post|
|
||||||
|
filename = post.destination(post.site.dest)
|
||||||
|
open('_site/post-build.log', 'a') do |f|
|
||||||
|
f.puts "Wrote #{filename} at #{Time.now}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And I have a _posts directory
|
||||||
|
And I have the following posts:
|
||||||
|
| title | date | layout | content |
|
||||||
|
| entry1 | 2015-03-14 | nil | entry one |
|
||||||
|
| entry2 | 2015-03-15 | nil | entry two |
|
||||||
|
When I run jekyll build
|
||||||
|
Then I should see "_site/2015/03/14/entry1.html at" in "_site/post-build.log"
|
||||||
|
Then I should see "_site/2015/03/15/entry2.html at" in "_site/post-build.log"
|
||||||
|
|
||||||
|
Scenario: Register a hook on multiple owners at the same time
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register [:page, :post], :post_render do |owner|
|
||||||
|
owner.output = "{{{{{ #{owner.output.chomp} }}}}}"
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And I have a "index.html" page that contains "WRAP ME"
|
||||||
|
And I have a _posts directory
|
||||||
|
And I have the following posts:
|
||||||
|
| title | date | layout | content |
|
||||||
|
| entry1 | 2015-03-14 | nil | entry one |
|
||||||
|
When I run jekyll build
|
||||||
|
Then I should see "{{{{{ WRAP ME }}}}}" in "_site/index.html"
|
||||||
|
And I should see "{{{{{ <p>entry one</p> }}}}}" in "_site/2015/03/14/entry1.html"
|
||||||
|
|
||||||
|
Scenario: Allow hooks to have a named priority
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register :page, :post_render, priority: :normal do |owner|
|
||||||
|
# first normal runs second
|
||||||
|
owner.output = "1 #{owner.output.chomp}"
|
||||||
|
end
|
||||||
|
Jekyll::Hooks.register :page, :post_render, priority: :high do |owner|
|
||||||
|
# high runs last
|
||||||
|
owner.output = "2 #{owner.output.chomp}"
|
||||||
|
end
|
||||||
|
Jekyll::Hooks.register :page, :post_render do |owner|
|
||||||
|
# second normal runs third (normal is default)
|
||||||
|
owner.output = "3 #{owner.output.chomp}"
|
||||||
|
end
|
||||||
|
Jekyll::Hooks.register :page, :post_render, priority: :low do |owner|
|
||||||
|
# low runs first
|
||||||
|
owner.output = "4 #{owner.output.chomp}"
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And I have a "index.html" page that contains "WRAP ME"
|
||||||
|
When I run jekyll build
|
||||||
|
Then I should see "2 3 1 4 WRAP ME" in "_site/index.html"
|
||||||
|
|
||||||
|
Scenario: Alter a document right after it is initialized
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register :document, :pre_render do |doc, payload|
|
||||||
|
doc.data['text'] = doc.data['text'] << ' are belong to us'
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And I have a "_config.yml" file that contains "collections: [ memes ]"
|
||||||
|
And I have a _memes directory
|
||||||
|
And I have a "_memes/doc1.md" file with content:
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
text: all your base
|
||||||
|
---
|
||||||
|
"""
|
||||||
|
And I have an "index.md" file with content:
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
---
|
||||||
|
{{ site.memes.first.text }}
|
||||||
|
"""
|
||||||
|
When I run jekyll build
|
||||||
|
Then the _site directory should exist
|
||||||
|
And I should see "all your base are belong to us" in "_site/index.html"
|
||||||
|
|
||||||
|
Scenario: Update a document after rendering it, but before writing it to disk
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register :document, :post_render do |doc|
|
||||||
|
doc.output.gsub! /<p>/, '<p class="meme">'
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And I have a "_config.yml" file with content:
|
||||||
|
"""
|
||||||
|
collections:
|
||||||
|
memes:
|
||||||
|
output: true
|
||||||
|
"""
|
||||||
|
And I have a _memes directory
|
||||||
|
And I have a "_memes/doc1.md" file with content:
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
text: all your base are belong to us
|
||||||
|
---
|
||||||
|
{{ page.text }}
|
||||||
|
"""
|
||||||
|
When I run jekyll build
|
||||||
|
Then the _site directory should exist
|
||||||
|
And I should see "<p class=\"meme\">all your base are belong to us" in "_site/memes/doc1.html"
|
||||||
|
|
||||||
|
Scenario: Perform an action after every document is written
|
||||||
|
Given I have a _plugins directory
|
||||||
|
And I have a "_plugins/ext.rb" file with content:
|
||||||
|
"""
|
||||||
|
Jekyll::Hooks.register :document, :post_write do |doc|
|
||||||
|
open('_site/document-build.log', 'a') do |f|
|
||||||
|
f.puts "Wrote document #{doc.collection.docs.index doc} at #{Time.now}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And I have a "_config.yml" file with content:
|
||||||
|
"""
|
||||||
|
collections:
|
||||||
|
memes:
|
||||||
|
output: true
|
||||||
|
"""
|
||||||
|
And I have a _memes directory
|
||||||
|
And I have a "_memes/doc1.md" file with content:
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
text: all your base are belong to us
|
||||||
|
---
|
||||||
|
{{ page.text }}
|
||||||
|
"""
|
||||||
|
When I run jekyll build
|
||||||
|
Then the _site directory should exist
|
||||||
|
And I should see "Wrote document 0" in "_site/document-build.log"
|
|
@ -48,6 +48,7 @@ module Jekyll
|
||||||
autoload :External, 'jekyll/external'
|
autoload :External, 'jekyll/external'
|
||||||
autoload :Filters, 'jekyll/filters'
|
autoload :Filters, 'jekyll/filters'
|
||||||
autoload :FrontmatterDefaults, 'jekyll/frontmatter_defaults'
|
autoload :FrontmatterDefaults, 'jekyll/frontmatter_defaults'
|
||||||
|
autoload :Hooks, 'jekyll/hooks'
|
||||||
autoload :Layout, 'jekyll/layout'
|
autoload :Layout, 'jekyll/layout'
|
||||||
autoload :CollectionReader, 'jekyll/readers/collection_reader'
|
autoload :CollectionReader, 'jekyll/readers/collection_reader'
|
||||||
autoload :DataReader, 'jekyll/readers/data_reader'
|
autoload :DataReader, 'jekyll/readers/data_reader'
|
||||||
|
|
|
@ -236,6 +236,7 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns nothing.
|
# Returns nothing.
|
||||||
def do_layout(payload, layouts)
|
def do_layout(payload, layouts)
|
||||||
|
Jekyll::Hooks.trigger self, :pre_render, payload
|
||||||
info = { :filters => [Jekyll::Filters], :registers => { :site => site, :page => payload['page'] } }
|
info = { :filters => [Jekyll::Filters], :registers => { :site => site, :page => payload['page'] } }
|
||||||
|
|
||||||
# render and transform content (this becomes the final content of the object)
|
# render and transform content (this becomes the final content of the object)
|
||||||
|
@ -249,6 +250,7 @@ module Jekyll
|
||||||
self.output = content
|
self.output = content
|
||||||
|
|
||||||
render_all_layouts(layouts, payload, info) if place_in_layout?
|
render_all_layouts(layouts, payload, info) if place_in_layout?
|
||||||
|
Jekyll::Hooks.trigger self, :post_render
|
||||||
end
|
end
|
||||||
|
|
||||||
# Write the generated page file to the destination directory.
|
# Write the generated page file to the destination directory.
|
||||||
|
@ -262,6 +264,7 @@ module Jekyll
|
||||||
File.open(path, 'wb') do |f|
|
File.open(path, 'wb') do |f|
|
||||||
f.write(output)
|
f.write(output)
|
||||||
end
|
end
|
||||||
|
Jekyll::Hooks.trigger self, :post_write
|
||||||
end
|
end
|
||||||
|
|
||||||
# Accessor for data properties by Liquid.
|
# Accessor for data properties by Liquid.
|
||||||
|
|
|
@ -189,6 +189,8 @@ module Jekyll
|
||||||
File.open(path, 'wb') do |f|
|
File.open(path, 'wb') do |f|
|
||||||
f.write(output)
|
f.write(output)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Jekyll::Hooks.trigger self, :post_write
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns merged option hash for File.read of self.site (if exists)
|
# Returns merged option hash for File.read of self.site (if exists)
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
module Jekyll
|
||||||
|
module Hooks
|
||||||
|
# Helps look up hooks from the registry by owner's class
|
||||||
|
OWNER_MAP = {
|
||||||
|
Jekyll::Site => :site,
|
||||||
|
Jekyll::Page => :page,
|
||||||
|
Jekyll::Post => :post,
|
||||||
|
Jekyll::Document => :document,
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
DEFAULT_PRIORITY = 20
|
||||||
|
|
||||||
|
# compatibility layer for octopress-hooks users
|
||||||
|
PRIORITY_MAP = {
|
||||||
|
low: 10,
|
||||||
|
normal: 20,
|
||||||
|
high: 30,
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
# initial empty hooks
|
||||||
|
@registry = {
|
||||||
|
:site => {
|
||||||
|
after_reset: [],
|
||||||
|
post_read: [],
|
||||||
|
pre_render: [],
|
||||||
|
post_write: [],
|
||||||
|
},
|
||||||
|
:page => {
|
||||||
|
post_init: [],
|
||||||
|
pre_render: [],
|
||||||
|
post_render: [],
|
||||||
|
post_write: [],
|
||||||
|
},
|
||||||
|
:post => {
|
||||||
|
post_init: [],
|
||||||
|
pre_render: [],
|
||||||
|
post_render: [],
|
||||||
|
post_write: [],
|
||||||
|
},
|
||||||
|
:document => {
|
||||||
|
pre_render: [],
|
||||||
|
post_render: [],
|
||||||
|
post_write: [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# map of all hooks and their priorities
|
||||||
|
@hook_priority = {}
|
||||||
|
|
||||||
|
NotAvailable = Class.new(RuntimeError)
|
||||||
|
Uncallable = Class.new(RuntimeError)
|
||||||
|
|
||||||
|
# register hook(s) to be called later, public API
|
||||||
|
def self.register(owners, event, priority: DEFAULT_PRIORITY, &block)
|
||||||
|
Array(owners).each do |owner|
|
||||||
|
register_one(owner, event, priority_value(priority), &block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Ensure the priority is a Fixnum
|
||||||
|
def self.priority_value(priority)
|
||||||
|
return priority if priority.is_a?(Fixnum)
|
||||||
|
PRIORITY_MAP[priority] || DEFAULT_PRIORITY
|
||||||
|
end
|
||||||
|
|
||||||
|
# register a single hook to be called later, internal API
|
||||||
|
def self.register_one(owner, event, priority, &block)
|
||||||
|
unless @registry[owner]
|
||||||
|
raise NotAvailable, "Hooks are only available for the following " <<
|
||||||
|
"classes: #{@registry.keys.inspect}"
|
||||||
|
end
|
||||||
|
|
||||||
|
unless @registry[owner][event]
|
||||||
|
raise NotAvailable, "Invalid hook. #{owner} supports only the " <<
|
||||||
|
"following hooks #{@registry[owner].keys.inspect}"
|
||||||
|
end
|
||||||
|
|
||||||
|
unless block.respond_to? :call
|
||||||
|
raise Uncallable, "Hooks must respond to :call"
|
||||||
|
end
|
||||||
|
|
||||||
|
insert_hook owner, event, priority, &block
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.insert_hook(owner, event, priority, &block)
|
||||||
|
@hook_priority[block] = "#{priority}.#{@hook_priority.size}".to_f
|
||||||
|
@registry[owner][event] << block
|
||||||
|
end
|
||||||
|
|
||||||
|
# interface for Jekyll core components to trigger hooks
|
||||||
|
def self.trigger(instance, event, *args)
|
||||||
|
owner_symbol = OWNER_MAP[instance.class]
|
||||||
|
|
||||||
|
# proceed only if there are hooks to call
|
||||||
|
return unless @registry[owner_symbol]
|
||||||
|
return unless @registry[owner_symbol][event]
|
||||||
|
|
||||||
|
# hooks to call for this owner and event
|
||||||
|
hooks = @registry[owner_symbol][event]
|
||||||
|
|
||||||
|
# sort and call hooks according to priority and load order
|
||||||
|
hooks.sort_by { |h| @hook_priority[h] }.each do |hook|
|
||||||
|
hook.call(instance, *args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -35,6 +35,8 @@ module Jekyll
|
||||||
data.default_proc = proc do |hash, key|
|
data.default_proc = proc do |hash, key|
|
||||||
site.frontmatter_defaults.find(File.join(dir, name), type, key)
|
site.frontmatter_defaults.find(File.join(dir, name), type, key)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Jekyll::Hooks.trigger self, :post_init
|
||||||
end
|
end
|
||||||
|
|
||||||
# The generated directory into which the page will be placed
|
# The generated directory into which the page will be placed
|
||||||
|
|
|
@ -68,6 +68,8 @@ module Jekyll
|
||||||
|
|
||||||
populate_categories
|
populate_categories
|
||||||
populate_tags
|
populate_tags
|
||||||
|
|
||||||
|
Jekyll::Hooks.trigger self, :post_init
|
||||||
end
|
end
|
||||||
|
|
||||||
def published?
|
def published?
|
||||||
|
|
|
@ -35,6 +35,8 @@ module Jekyll
|
||||||
"page" => document.to_liquid
|
"page" => document.to_liquid
|
||||||
}, site_payload || site.site_payload)
|
}, site_payload || site.site_payload)
|
||||||
|
|
||||||
|
Jekyll::Hooks.trigger document, :pre_render, payload
|
||||||
|
|
||||||
info = {
|
info = {
|
||||||
filters: [Jekyll::Filters],
|
filters: [Jekyll::Filters],
|
||||||
registers: { :site => site, :page => payload['page'] }
|
registers: { :site => site, :page => payload['page'] }
|
||||||
|
|
|
@ -75,6 +75,8 @@ module Jekyll
|
||||||
if limit_posts < 0
|
if limit_posts < 0
|
||||||
raise ArgumentError, "limit_posts must be a non-negative number"
|
raise ArgumentError, "limit_posts must be a non-negative number"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Jekyll::Hooks.trigger self, :after_reset
|
||||||
end
|
end
|
||||||
|
|
||||||
# Load necessary libraries, plugins, converters, and generators.
|
# Load necessary libraries, plugins, converters, and generators.
|
||||||
|
@ -132,6 +134,7 @@ module Jekyll
|
||||||
def read
|
def read
|
||||||
reader.read
|
reader.read
|
||||||
limit_posts!
|
limit_posts!
|
||||||
|
Jekyll::Hooks.trigger self, :post_read
|
||||||
end
|
end
|
||||||
|
|
||||||
# Run each of the Generators.
|
# Run each of the Generators.
|
||||||
|
@ -150,15 +153,18 @@ module Jekyll
|
||||||
relative_permalinks_are_deprecated
|
relative_permalinks_are_deprecated
|
||||||
|
|
||||||
payload = site_payload
|
payload = site_payload
|
||||||
|
|
||||||
|
Jekyll::Hooks.trigger self, :pre_render, payload
|
||||||
|
|
||||||
collections.each do |label, collection|
|
collections.each do |label, collection|
|
||||||
collection.docs.each do |document|
|
collection.docs.each do |document|
|
||||||
if regenerator.regenerate?(document)
|
if regenerator.regenerate?(document)
|
||||||
document.output = Jekyll::Renderer.new(self, document, payload).run
|
document.output = Jekyll::Renderer.new(self, document, payload).run
|
||||||
|
Jekyll::Hooks.trigger document, :post_render
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
payload = site_payload
|
|
||||||
[posts, pages].flatten.each do |page_or_post|
|
[posts, pages].flatten.each do |page_or_post|
|
||||||
if regenerator.regenerate?(page_or_post)
|
if regenerator.regenerate?(page_or_post)
|
||||||
page_or_post.render(layouts, payload)
|
page_or_post.render(layouts, payload)
|
||||||
|
@ -183,6 +189,7 @@ module Jekyll
|
||||||
item.write(dest) if regenerator.regenerate?(item)
|
item.write(dest) if regenerator.regenerate?(item)
|
||||||
}
|
}
|
||||||
regenerator.write_metadata
|
regenerator.write_metadata
|
||||||
|
Jekyll::Hooks.trigger self, :post_write
|
||||||
end
|
end
|
||||||
|
|
||||||
# Construct a Hash of Posts indexed by the specified Post attribute.
|
# Construct a Hash of Posts indexed by the specified Post attribute.
|
||||||
|
|
|
@ -470,6 +470,220 @@ module Jekyll
|
||||||
end
|
end
|
||||||
{% endhighlight %}
|
{% endhighlight %}
|
||||||
|
|
||||||
|
## Hooks
|
||||||
|
|
||||||
|
<div class="note unreleased">
|
||||||
|
<h5>Support for hooks is currently unreleased.</h5>
|
||||||
|
<p>
|
||||||
|
In order to use this feature, <a href="/docs/installation/#pre-releases">
|
||||||
|
install the latest development version of Jekyll</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Using hooks, your plugin can exercise fine-grained control over various aspects
|
||||||
|
of the build process. If your plugin defines any hooks, Jekyll will call them
|
||||||
|
at pre-defined points.
|
||||||
|
|
||||||
|
Hooks are registered to a container and an event name. To register one, you
|
||||||
|
call Jekyll::Hooks.register, and pass the container, event name, and code to
|
||||||
|
call whenever the hook is triggered. For example, if you want to execute some
|
||||||
|
custom functionality every time Jekyll renders a post, you could register a
|
||||||
|
hook like this:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
Jekyll::Hooks.register :post, :post_render do |post|
|
||||||
|
# code to call after Jekyll renders a post
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Jekyll provides hooks for <code>:site</code>, <code>:page</code>,
|
||||||
|
<code>:post</code>, and <code>:document</code>. In all cases, Jekyll calls your
|
||||||
|
hooks with the container object as the first callback parameter. But in the
|
||||||
|
case of <code>:pre_render</code>, your hook will also receive a payload hash as
|
||||||
|
a second parameter which allows you full control over the variables that are
|
||||||
|
available while rendering.
|
||||||
|
|
||||||
|
The complete list of available hooks is below:
|
||||||
|
|
||||||
|
<div class="mobile-side-scroller">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Container</th>
|
||||||
|
<th>Event</th>
|
||||||
|
<th>Called</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:site</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:after_reset</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Just after site reset</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:site</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:pre_render</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Just before rendering the whole site</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:site</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:post_render</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>After rendering the whole site, but before writing any files</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:site</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:post_write</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>After writing the whole site to disk</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:page</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:post_init</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Whenever a page is initialized</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:page</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:pre_render</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Just before rendering a page</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:page</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:post_render</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>After rendering a page, but before writing it to disk</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:page</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:post_write</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>After writing a page to disk</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:post</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:post_init</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Whenever a post is initialized</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:post</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:pre_render</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Just before rendering a post</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:post</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:post_render</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>After rendering a post, but before writing it to disk</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:post</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:post_write</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>After writing a post to disk</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:document</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:pre_render</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>Just before rendering a document</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:document</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:post_render</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>After rendering a document, but before writing it to disk</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p><code>:document</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><code>:post_write</code></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>After writing a document to disk</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
## Available Plugins
|
## Available Plugins
|
||||||
|
|
||||||
You can find a few useful plugins at the following locations:
|
You can find a few useful plugins at the following locations:
|
||||||
|
|
Loading…
Reference in New Issue