Merge pull request #2419 from jens-na/collection-defaults

This commit is contained in:
Parker Moore 2014-06-12 20:38:21 -04:00
commit d59b2c3ef6
6 changed files with 209 additions and 2 deletions

View File

@ -77,3 +77,54 @@ Feature: frontmatter defaults
Then I should see "a blog by some guy" in "_site/frontmatter.html" Then I should see "a blog by some guy" in "_site/frontmatter.html"
And I should see "nothing" in "_site/override.html" And I should see "nothing" in "_site/override.html"
But the "_site/perma.html" file should not exist But the "_site/perma.html" file should not exist
Scenario: Use frontmatter defaults in collections
Given I have a _slides directory
And I have a "index.html" file that contains "nothing"
And I have a "_slides/slide1.html" file with content:
"""
Value: {{ page.myval }}
"""
And I have a "_config.yml" file with content:
"""
collections:
slides:
output: true
defaults:
-
scope:
path: ""
type: slides
values:
myval: "Test"
"""
When I run jekyll build
Then the _site directory should exist
And I should see "Value: Test" in "_site/slides/slide1.html"
Scenario: Override frontmatter defaults inside a collection
Given I have a _slides directory
And I have a "index.html" file that contains "nothing"
And I have a "_slides/slide2.html" file with content:
"""
---
myval: Override
---
Value: {{ page.myval }}
"""
And I have a "_config.yml" file with content:
"""
collections:
slides:
output: true
defaults:
-
scope:
path: ""
type: slides
values:
myval: "Test"
"""
When I run jekyll build
Then the _site directory should exist
And I should see "Value: Override" in "_site/slides/slide2.html"

View File

@ -176,6 +176,8 @@ module Jekyll
end end
# Read in the file and assign the content and data based on the file contents. # Read in the file and assign the content and data based on the file contents.
# Merge the frontmatter of the file with the frontmatter default
# values
# #
# Returns nothing. # Returns nothing.
def read(opts = {}) def read(opts = {})
@ -183,10 +185,17 @@ module Jekyll
@data = SafeYAML.load_file(path) @data = SafeYAML.load_file(path)
else else
begin begin
defaults = @site.frontmatter_defaults.all(url, collection.label.to_sym)
unless defaults.empty?
@data = defaults
end
@content = File.read(path, merged_file_read_opts(opts)) @content = File.read(path, merged_file_read_opts(opts))
if content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m if content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
@content = $POSTMATCH @content = $POSTMATCH
@data = SafeYAML.load($1) data_file = SafeYAML.load($1)
unless data_file.nil?
@data = Utils.deep_merge_hashes(defaults, data_file)
end
end end
rescue SyntaxError => e rescue SyntaxError => e
puts "YAML Exception reading #{path}: #{e.message}" puts "YAML Exception reading #{path}: #{e.message}"

View File

@ -309,7 +309,8 @@ defaults:
layout: "default" layout: "default"
{% endhighlight %} {% endhighlight %}
Now, this will only set the layout for files where the type is `post`. The different types that are available to you are `page`, `post`, or `draft`. While `type` is optional, you must specify a value for `path` when creating a `scope/values` pair. Now, this will only set the layout for files where the type is `post`.
The different types that are available to you are `page`, `post`, `draft` or any collection in your site. While `type` is optional, you must specify a value for `path` when creating a `scope/values` pair.
As mentioned earlier, you can set multiple scope/values pairs for `defaults`. As mentioned earlier, you can set multiple scope/values pairs for `defaults`.
@ -333,6 +334,22 @@ defaults:
With these defaults, all posts would use the `my-site` layout. Any html files that exist in the `projects/` folder will use the `project` layout, if it exists. Those files will also have the `page.author` [liquid variable](../variables/) set to `Mr. Hyde` as well as have the category for the page set to `project`. With these defaults, all posts would use the `my-site` layout. Any html files that exist in the `projects/` folder will use the `project` layout, if it exists. Those files will also have the `page.author` [liquid variable](../variables/) set to `Mr. Hyde` as well as have the category for the page set to `project`.
{% highlight yaml %}
collections:
- my_collection:
output: true
defaults:
-
scope:
path: ""
type: "my_collection" # a collection in your site
values:
layout: "default"
{% endhighlight %}
In this example the `layout` is set to `default` inside the [collection](../collections) with the name `my_collection`.
### Precedence ### Precedence
Jekyll will apply all of the configuration settings you specify in the `defaults` section of your `_config.yml` file. However, you can choose to override settings from other scope/values pair by specifying a more specific path for the scope. Jekyll will apply all of the configuration settings you specify in the `defaults` section of your `_config.yml` file. However, you can choose to override settings from other scope/values pair by specifying a more specific path for the scope.

View File

@ -0,0 +1,4 @@
---
title: Example slide
layout: slide
---

View File

@ -0,0 +1,7 @@
---
title: Override title
layout: slide
nested:
test1: override1
test2: override2
---

View File

@ -46,6 +46,125 @@ class TestDocument < Test::Unit::TestCase
end end
context "a document as part of a collection with frontmatter defaults" do
setup do
@site = Site.new(Jekyll.configuration({
"collections" => ["slides"],
"source" => source_dir,
"destination" => dest_dir,
"defaults" => [{
"scope"=> {"path"=>"", "type"=>"slides"},
"values"=> {
"nested"=> {
"key"=>"myval",
}
}
}]
}))
@site.process
@document = @site.collections["slides"].docs.first
end
should "know the frontmatter defaults" do
assert_equal({
"title"=>"Example slide",
"layout"=>"slide",
"nested"=> {
"key"=>"myval"
}
}, @document.data)
end
end
context "a document as part of a collection with overriden default values" do
setup do
@site = Site.new(Jekyll.configuration({
"collections" => ["slides"],
"source" => source_dir,
"destination" => dest_dir,
"defaults" => [{
"scope"=> {"path"=>"", "type"=>"slides"},
"values"=> {
"nested"=> {
"test1"=>"default1",
"test2"=>"default1"
}
}
}]
}))
@site.process
@document = @site.collections["slides"].docs[1]
end
should "override default values in the document frontmatter" do
assert_equal({
"title"=>"Override title",
"layout"=>"slide",
"nested"=> {
"test1"=>"override1",
"test2"=>"override2"
}
}, @document.data)
end
end
context "a document as part of a collection with valid path" do
setup do
@site = Site.new(Jekyll.configuration({
"collections" => ["slides"],
"source" => source_dir,
"destination" => dest_dir,
"defaults" => [{
"scope"=> {"path"=>"slides", "type"=>"slides"},
"values"=> {
"nested"=> {
"key"=>"value123",
}
}
}]
}))
@site.process
@document = @site.collections["slides"].docs.first
end
should "know the frontmatter defaults" do
assert_equal({
"title"=>"Example slide",
"layout"=>"slide",
"nested"=> {
"key"=>"value123"
}
}, @document.data)
end
end
context "a document as part of a collection with invalid path" do
setup do
@site = Site.new(Jekyll.configuration({
"collections" => ["slides"],
"source" => source_dir,
"destination" => dest_dir,
"defaults" => [{
"scope"=> {"path"=>"somepath", "type"=>"slides"},
"values"=> {
"nested"=> {
"key"=>"myval",
}
}
}]
}))
@site.process
@document = @site.collections["slides"].docs.first
end
should "not know the specified frontmatter defaults" do
assert_equal({
"title"=>"Example slide",
"layout"=>"slide"
}, @document.data)
end
end
context " a document part of a rendered collection" do context " a document part of a rendered collection" do
end end