diff --git a/features/data.feature b/features/data.feature index 45f5554e..4f0e32ed 100644 --- a/features/data.feature +++ b/features/data.feature @@ -60,6 +60,35 @@ Feature: Data And I should see "Jack" in "_site/index.html" And I should see "Leon" in "_site/index.html" + Scenario: autoload *.yaml files in subdirectories in _data directory + Given I have a _data directory + And I have a _data/categories directory + And I have a "_data/categories/dairy.yaml" file with content: + """ + name: Dairy Products + """ + And I have an "index.html" page that contains "{{ site.data.categories.dairy.name }}" + When I run jekyll build + Then the "_site/index.html" file should exist + And I should see "Dairy Products" in "_site/index.html" + + Scenario: folders should have precedence over files with the same name + Given I have a _data directory + And I have a _data/categories directory + And I have a "_data/categories/dairy.yaml" file with content: + """ + name: Dairy Products + """ + And I have a "_data/categories.yaml" file with content: + """ + dairy: + name: Should not display this + """ + And I have an "index.html" page that contains "{{ site.data.categories.dairy.name }}" + When I run jekyll build + Then the "_site/index.html" file should exist + And I should see "Dairy Products" in "_site/index.html" + Scenario: should be backward compatible with site.data in _config.yml Given I have a "_config.yml" file with content: """ diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 9efe2500..9b05f0f7 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -196,17 +196,33 @@ module Jekyll # Returns nothing def read_data(dir) base = File.join(source, dir) - return unless File.directory?(base) && (!safe || !File.symlink?(base)) + read_data_to(base, self.data) + end - entries = Dir.chdir(base) { Dir['*.{yaml,yml,json}'] } - entries.delete_if { |e| File.directory?(File.join(base, e)) } + # Read and parse all yaml files under and add them to the + # variable. + # + # dir - The string absolute path of the directory to read. + # data - The variable to which data will be added. + # + # Returns nothing + def read_data_to(dir, data) + return unless File.directory?(dir) && (!safe || !File.symlink?(dir)) + + entries = Dir.chdir(dir) do + Dir['*.{yaml,yml,json}'] + Dir['*'].select { |fn| File.directory?(fn) } + end entries.each do |entry| - path = File.join(source, dir, entry) + path = File.join(dir, entry) next if File.symlink?(path) && safe key = sanitize_filename(File.basename(entry, '.*')) - self.data[key] = SafeYAML.load_file(path) + if File.directory?(path) + read_data_to(path, data[key] = {}) + else + data[key] = SafeYAML.load_file(path) + end end end diff --git a/site/docs/datafiles.md b/site/docs/datafiles.md index 05e59345..dbac1dec 100644 --- a/site/docs/datafiles.md +++ b/site/docs/datafiles.md @@ -61,3 +61,47 @@ You can now render the list of members in a template: {% endraw %} {% endhighlight %} + +## Example: Organizations + +Data files can also be placed in sub-folders of the `_data` folder. Each folder level will be added to a variable's namespace. The example bellow shows how GitHub organizations could be defined separately in a file under the `orgs` folder: + +In `_data/orgs/jekyll.yml`: + +{% highlight yaml %} +username: jekyll +name: Jekyll +members: + - name: Tom Preston-Werner + github: mojombo + + - name: Parker Moore + github: parkr +{% endhighlight %} + +In `_data/orgs/doeorg.yml`: + +{% highlight yaml %} +username: doeorg +name: Doe Org +members: + - name: John Doe + github: jdoe +{% endhighlight %} + +The organizations can then be accessed via `site.data.orgs`, followed by the file name: + +{% highlight html %} +{% raw %} + +{% endraw %} +{% endhighlight %} diff --git a/test/source/_data/categories/dairy.yaml b/test/source/_data/categories/dairy.yaml new file mode 100644 index 00000000..c091a68c --- /dev/null +++ b/test/source/_data/categories/dairy.yaml @@ -0,0 +1,6 @@ +name: Dairy +products: +- name: cheese + price: 5.3 +- name: milk + price: 2.5 \ No newline at end of file diff --git a/test/test_site.rb b/test/test_site.rb index de02b8dd..48290d45 100644 --- a/test/test_site.rb +++ b/test/test_site.rb @@ -389,6 +389,16 @@ class TestSite < Test::Unit::TestCase assert_equal site.site_payload['site']['data']['members'], file_content end + should 'auto load yaml files in subdirectory' do + site = Site.new(Jekyll.configuration) + site.process + + file_content = SafeYAML.load_file(File.join(source_dir, '_data', 'categories', 'dairy.yaml')) + + assert_equal site.data['categories']['dairy'], file_content + assert_equal site.site_payload['site']['data']['categories']['dairy'], file_content + end + should "load symlink files in unsafe mode" do site = Site.new(Jekyll.configuration.merge({'safe' => false})) site.process