diff --git a/features/frontmatter_defaults.feature b/features/frontmatter_defaults.feature index 3f2d3cd5..c3e7c8de 100644 --- a/features/frontmatter_defaults.feature +++ b/features/frontmatter_defaults.feature @@ -77,3 +77,54 @@ Feature: frontmatter defaults Then I should see "a blog by some guy" in "_site/frontmatter.html" And I should see "nothing" in "_site/override.html" 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" diff --git a/lib/jekyll/document.rb b/lib/jekyll/document.rb index 248e6d15..f1fcdf2a 100644 --- a/lib/jekyll/document.rb +++ b/lib/jekyll/document.rb @@ -176,6 +176,8 @@ module Jekyll end # 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. def read(opts = {}) @@ -183,10 +185,17 @@ module Jekyll @data = SafeYAML.load_file(path) else 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)) if content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m @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 rescue SyntaxError => e puts "YAML Exception reading #{path}: #{e.message}" diff --git a/site/docs/configuration.md b/site/docs/configuration.md index e9a21db7..23b16e9a 100644 --- a/site/docs/configuration.md +++ b/site/docs/configuration.md @@ -309,7 +309,8 @@ defaults: layout: "default" {% 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`. @@ -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`. +{% 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 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. diff --git a/test/source/_slides/example-slide-1.html b/test/source/_slides/example-slide-1.html new file mode 100644 index 00000000..fcd89b3c --- /dev/null +++ b/test/source/_slides/example-slide-1.html @@ -0,0 +1,4 @@ +--- + title: Example slide + layout: slide +--- diff --git a/test/source/_slides/example-slide-2.html b/test/source/_slides/example-slide-2.html new file mode 100644 index 00000000..15158990 --- /dev/null +++ b/test/source/_slides/example-slide-2.html @@ -0,0 +1,7 @@ +--- + title: Override title + layout: slide + nested: + test1: override1 + test2: override2 +--- diff --git a/test/test_document.rb b/test/test_document.rb index 672f7d2e..98fde67e 100644 --- a/test/test_document.rb +++ b/test/test_document.rb @@ -46,6 +46,125 @@ class TestDocument < Test::Unit::TestCase 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 end