Extract core extensions into a Utils module

Fixes #2111
This commit is contained in:
Parker Moore 2014-03-03 22:13:03 -05:00
parent 171452095f
commit e2af1b547b
16 changed files with 116 additions and 95 deletions

View File

@ -39,7 +39,7 @@ Gem::Specification.new do |s|
s.add_runtime_dependency('redcarpet', "~> 3.1")
s.add_runtime_dependency('toml', '~> 0.1.0')
s.add_runtime_dependency('jekyll-coffeescript', '~> 1.0')
s.add_runtime_dependency('jekyll-sass-converter', '~> 1.0.0.rc1')
s.add_runtime_dependency('jekyll-sass-converter', '~> 1.0.0.rc2')
s.add_development_dependency('rake', "~> 10.1")
s.add_development_dependency('rdoc', "~> 3.11")

View File

@ -30,7 +30,7 @@ require 'toml'
# internal requires
require 'jekyll/version'
require 'jekyll/core_ext'
require 'jekyll/utils'
require 'jekyll/stevenson'
require 'jekyll/deprecator'
require 'jekyll/configuration'
@ -83,7 +83,9 @@ module Jekyll
config = config.read_config_files(config.config_files(override))
# Merge DEFAULTS < _config.yml < override
config = config.deep_merge(override).stringify_keys
config = Utils.hash_stringify_keys(
Utils.hash_deep_merge(config, override)
)
set_timezone(config['timezone']) if config['timezone']
config

View File

@ -159,7 +159,7 @@ module Jekyll
begin
files.each do |config_file|
new_config = read_config_file(config_file)
configuration = configuration.deep_merge(new_config)
configuration = Utils.hash_deep_merge(configuration, new_config)
end
rescue ArgumentError => err
Jekyll.logger.warn "WARNING:", "Error reading configuration. " +
@ -229,7 +229,7 @@ module Jekyll
config[option] = csv_to_array(config[option])
end
end
if config.fetch('markdown', 'kramdown').to_s.downcase.eql?("maruku")
Jekyll::Deprecator.deprecation_message "You're using the 'maruku' " +
"Markdown processor. Maruku support has been deprecated and will " +

View File

@ -20,7 +20,7 @@ module Jekyll
end
end
Kramdown::Document.new(content, @config["kramdown"].symbolize_keys).to_html
Kramdown::Document.new(content, Utils.hash_symbolize_keys(@config["kramdown"])).to_html
end
end

View File

@ -107,7 +107,7 @@ module Jekyll
further_data = Hash[(attrs || self.class::ATTRIBUTES_FOR_LIQUID).map { |attribute|
[attribute, send(attribute)]
}]
data.deep_merge(further_data)
Utils.hash_deep_merge(data, further_data)
end
# Recursively render layouts
@ -123,7 +123,7 @@ module Jekyll
used = Set.new([layout])
while layout
payload = payload.deep_merge({"content" => output, "page" => layout.data})
payload = Utils.hash_deep_merge(payload, {"content" => output, "page" => layout.data})
self.output = render_liquid(layout.content,
payload,

View File

@ -1,55 +0,0 @@
class Hash
# Merges self with another hash, recursively.
#
# This code was lovingly stolen from some random gem:
# http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html
#
# Thanks to whoever made it.
def deep_merge(hash)
target = dup
hash.keys.each do |key|
if hash[key].is_a? Hash and self[key].is_a? Hash
target[key] = target[key].deep_merge(hash[key])
next
end
target[key] = hash[key]
end
target
end
# Read array from the supplied hash favouring the singular key
# and then the plural key, and handling any nil entries.
# +hash+ the hash to read from
# +singular_key+ the singular key
# +plural_key+ the plural key
#
# Returns an array
def pluralized_array(singular_key, plural_key)
hash = self
if hash.has_key?(singular_key)
array = [hash[singular_key]] if hash[singular_key]
elsif hash.has_key?(plural_key)
case hash[plural_key]
when String
array = hash[plural_key].split
when Array
array = hash[plural_key].compact
end
end
array || []
end
def symbolize_keys!
keys.each do |key|
self[(key.to_sym rescue key) || key] = delete(key)
end
self
end
def symbolize_keys
dup.symbolize_keys!
end
end

View File

@ -109,10 +109,10 @@ module Jekyll
#
# Returns nothing.
def render(layouts, site_payload)
payload = {
payload = Utils.hash_deep_merge({
"page" => to_liquid,
'paginator' => pager.to_liquid
}.deep_merge(site_payload)
}, site_payload)
do_layout(payload, layouts)
end

View File

@ -66,13 +66,13 @@ module Jekyll
def populate_categories
if categories.empty?
self.categories = data.pluralized_array('category', 'categories').map {|c| c.to_s.downcase}
self.categories = Utils.hash_pluralized_array(data, 'category', 'categories').map {|c| c.to_s.downcase}
end
categories.flatten!
end
def populate_tags
self.tags = data.pluralized_array("tag", "tags").flatten
self.tags = Utils.hash_pluralized_array(data, "tag", "tags").flatten
end
# Get the full path to the directory containing the post files
@ -241,10 +241,10 @@ module Jekyll
# Returns nothing.
def render(layouts, site_payload)
# construct payload
payload = {
payload = Utils.hash_deep_merge({
"site" => { "related_posts" => related_posts(site_payload["site"]["posts"]) },
"page" => to_liquid(EXCERPT_ATTRIBUTES_FOR_LIQUID)
}.deep_merge(site_payload)
}, site_payload)
if generate_excerpt?
extracted_excerpt.do_layout(payload, {})

66
lib/jekyll/utils.rb Normal file
View File

@ -0,0 +1,66 @@
module Jekyll
module Utils
class << self
# Merges a master hash with another hash, recursively.
#
# master_hash - the "parent" hash whose values will be overridden
# other_hash - the other hash whose values will be persisted after the merge
#
# This code was lovingly stolen from some random gem:
# http://gemjack.com/gems/tartan-0.1.1/classes/Hash.html
#
# Thanks to whoever made it.
def hash_deep_merge(master_hash, other_hash)
target = master_hash.dup
other_hash.keys.each do |key|
if other_hash[key].is_a? Hash and target[key].is_a? Hash
target[key] = Utils.hash_deep_merge(target[key], other_hash[key])
next
end
target[key] = other_hash[key]
end
target
end
# Read array from the supplied hash favouring the singular key
# and then the plural key, and handling any nil entries.
#
# hash - the hash to read from
# singular_key - the singular key
# plural_key - the plural key
#
# Returns an array
def hash_pluralized_array(hash, singular_key, plural_key)
if hash.has_key?(singular_key)
array = [hash[singular_key]] if hash[singular_key]
elsif hash.has_key?(plural_key)
case hash[plural_key]
when String
array = hash[plural_key].split
when Array
array = hash[plural_key].compact
end
end
array || []
end
# Apply #to_sym to all keys in the hash
#
# hash - the hash to which to apply this transformation
#
# Returns a new hash with symbolized keys
def hash_symbolize_keys(hash)
target = hash.dup
target.keys.each do |key|
target[(key.to_sym rescue key) || key] = target.delete(key)
end
target
end
end
end
end

View File

@ -28,6 +28,17 @@ STDERR.reopen(test(?e, '/dev/null') ? '/dev/null' : 'NUL:')
class Test::Unit::TestCase
include RR::Adapters::TestUnit
def build_configs(overrides, base_hash = Jekyll::Configuration::DEFAULTS)
Utils.hash_deep_merge(base_hash, overrides)
end
def site_configuration(overrides = {})
build_configs({
"source" => source_dir,
"destination" => dest_dir
}, build_configs(overrides))
end
def dest_dir(*subdirs)
test_dir('dest', *subdirs)
end

View File

@ -156,7 +156,7 @@ class TestConfiguration < Test::Unit::TestCase
should "load different config if specified" do
mock(SafeYAML).load_file(@paths[:other]) { {"baseurl" => "http://wahoo.dev"} }
mock($stdout).puts("Configuration file: #{@paths[:other]}")
assert_equal Jekyll::Configuration::DEFAULTS.deep_merge({ "baseurl" => "http://wahoo.dev" }), Jekyll.configuration({ "config" => @paths[:other] })
assert_equal Utils.hash_deep_merge(Jekyll::Configuration::DEFAULTS, { "baseurl" => "http://wahoo.dev" }), Jekyll.configuration({ "config" => @paths[:other] })
end
should "load default config if path passed is empty" do
@ -186,7 +186,7 @@ class TestConfiguration < Test::Unit::TestCase
mock(SafeYAML).load_file(@paths[:other]) { {"baseurl" => "http://wahoo.dev"} }
mock($stdout).puts("Configuration file: #{@paths[:default]}")
mock($stdout).puts("Configuration file: #{@paths[:other]}")
assert_equal Jekyll::Configuration::DEFAULTS.deep_merge({ "baseurl" => "http://wahoo.dev" }), Jekyll.configuration({ "config" => [@paths[:default], @paths[:other]] })
assert_equal Utils.hash_deep_merge(Jekyll::Configuration::DEFAULTS, { "baseurl" => "http://wahoo.dev" }), Jekyll.configuration({ "config" => [@paths[:default], @paths[:other]] })
end
end
end

View File

@ -35,7 +35,7 @@ class TestKramdown < Test::Unit::TestCase
assert_match /<p>(&#8220;|“)Pit(&#8217;|)hy(&#8221;|”)<\/p>/, @markdown.convert(%{"Pit'hy"}).strip
override = { 'kramdown' => { 'smart_quotes' => 'lsaquo,rsaquo,laquo,raquo' } }
markdown = Converters::Markdown.new(@config.deep_merge(override))
markdown = Converters::Markdown.new(Utils.hash_deep_merge(@config, override))
assert_match /<p>(&#171;|«)Pit(&#8250;|)hy(&#187;|»)<\/p>/, markdown.convert(%{"Pit'hy"}).strip
end

View File

@ -3,12 +3,14 @@ require 'helper'
class TestPager < Test::Unit::TestCase
def build_site(config = {})
base = Jekyll::Configuration::DEFAULTS.deep_merge({
base = build_configs({
'source' => source_dir,
'destination' => dest_dir,
'paginate' => 1
})
site = Jekyll::Site.new(base.deep_merge(config))
site = Jekyll::Site.new(site_configuration(
{"paginate" => 1}.merge(config)
))
site.process
site
end

View File

@ -1,13 +1,6 @@
require 'helper'
class TestSass < Test::Unit::TestCase
def site_configuration(overrides = {})
Jekyll::Configuration::DEFAULTS.deep_merge(overrides).deep_merge({
"source" => source_dir,
"destination" => dest_dir
})
end
def converter(overrides = {})
Jekyll::Converters::Sass.new(site_configuration({"sass" => overrides}))
end

View File

@ -6,7 +6,9 @@ class TestTags < Test::Unit::TestCase
def create_post(content, override = {}, converter_class = Jekyll::Converters::Markdown)
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.deep_merge({'highlighter' => 'pygments'}).deep_merge(override)
site_configuration({
"highlighter" => "pygments"
}.merge(override))
end
site = Site.new(Jekyll.configuration)
@ -545,7 +547,7 @@ CONTENT
context "include tag with variable and liquid filters" do
setup do
stub(Jekyll).configuration do
Jekyll::Configuration::DEFAULTS.deep_merge({'pygments' => true}).deep_merge({'source' => source_dir, 'destination' => dest_dir})
site_configuration({'pygments' => true})
end
site = Site.new(Jekyll.configuration)

View File

@ -1,63 +1,63 @@
require 'helper'
class TestCoreExt < Test::Unit::TestCase
class TestUtils < Test::Unit::TestCase
context "hash" do
context "pluralized_array" do
should "return empty array with no values" do
data = {}
assert_equal [], data.pluralized_array('tag', 'tags')
assert_equal [], Utils.hash_pluralized_array(data, 'tag', 'tags')
end
should "return empty array with no matching values" do
data = { 'foo' => 'bar' }
assert_equal [], data.pluralized_array('tag', 'tags')
assert_equal [], Utils.hash_pluralized_array(data, 'tag', 'tags')
end
should "return empty array with matching nil singular" do
data = { 'foo' => 'bar', 'tag' => nil, 'tags' => ['dog', 'cat'] }
assert_equal [], data.pluralized_array('tag', 'tags')
assert_equal [], Utils.hash_pluralized_array(data, 'tag', 'tags')
end
should "return single value array with matching singular" do
data = { 'foo' => 'bar', 'tag' => 'dog', 'tags' => ['dog', 'cat'] }
assert_equal ['dog'], data.pluralized_array('tag', 'tags')
assert_equal ['dog'], Utils.hash_pluralized_array(data, 'tag', 'tags')
end
should "return single value array with matching singular with spaces" do
data = { 'foo' => 'bar', 'tag' => 'dog cat', 'tags' => ['dog', 'cat'] }
assert_equal ['dog cat'], data.pluralized_array('tag', 'tags')
assert_equal ['dog cat'], Utils.hash_pluralized_array(data, 'tag', 'tags')
end
should "return empty array with matching nil plural" do
data = { 'foo' => 'bar', 'tags' => nil }
assert_equal [], data.pluralized_array('tag', 'tags')
assert_equal [], Utils.hash_pluralized_array(data, 'tag', 'tags')
end
should "return empty array with matching empty array" do
data = { 'foo' => 'bar', 'tags' => [] }
assert_equal [], data.pluralized_array('tag', 'tags')
assert_equal [], Utils.hash_pluralized_array(data, 'tag', 'tags')
end
should "return single value array with matching plural with single string value" do
data = { 'foo' => 'bar', 'tags' => 'dog' }
assert_equal ['dog'], data.pluralized_array('tag', 'tags')
assert_equal ['dog'], Utils.hash_pluralized_array(data, 'tag', 'tags')
end
should "return multiple value array with matching plural with single string value with spaces" do
data = { 'foo' => 'bar', 'tags' => 'dog cat' }
assert_equal ['dog', 'cat'], data.pluralized_array('tag', 'tags')
assert_equal ['dog', 'cat'], Utils.hash_pluralized_array(data, 'tag', 'tags')
end
should "return single value array with matching plural with single value array" do
data = { 'foo' => 'bar', 'tags' => ['dog'] }
assert_equal ['dog'], data.pluralized_array('tag', 'tags')
assert_equal ['dog'], Utils.hash_pluralized_array(data, 'tag', 'tags')
end
should "return multiple value array with matching plural with multiple value array" do
data = { 'foo' => 'bar', 'tags' => ['dog', 'cat'] }
assert_equal ['dog', 'cat'], data.pluralized_array('tag', 'tags')
assert_equal ['dog', 'cat'], Utils.hash_pluralized_array(data, 'tag', 'tags')
end
end