From 250b6ebb7e4108de387027f2ab71aba0062c9ad7 Mon Sep 17 00:00:00 2001 From: Mike Bland Date: Thu, 25 Jun 2015 12:49:24 -0400 Subject: [PATCH] Adapt StaticFile for collections, config defaults This enables files such as images and PDFs to show up in the same relative output directory as other HTML and Markdown documents in the same collection. It also enables static files to be hidden using defaults from _config.yml in the same way that other documents in the same collection and directories may be hidden using `published: false`. --- lib/jekyll/static_file.rb | 43 +++++++++++++++++++++++++++++++--- test/test_static_file.rb | 49 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/lib/jekyll/static_file.rb b/lib/jekyll/static_file.rb index 454f12476d1..48fa34c5990 100644 --- a/lib/jekyll/static_file.rb +++ b/lib/jekyll/static_file.rb @@ -37,7 +37,7 @@ def destination(dest) def destination_rel_dir if @collection - @dir.gsub(/\A_/, '') + File.dirname(url) else @dir end @@ -61,9 +61,10 @@ def modified? # Whether to write the file to the filesystem # - # Returns true. + # Returns true unless the defaults for the destination path from + # _config.yml contain `published: false`. def write? - true + defaults.fetch('published', true) end # Write the static file to the destination directory (if modified). @@ -100,5 +101,41 @@ def to_liquid "path" => File.join("", relative_path) } end + + def placeholders + { + collection: @collection.label, + path: relative_path[ + @collection.relative_directory.size..relative_path.size], + output_ext: '', + name: '', + title: '', + } + end + + # Applies a similar URL-building technique as Jekyll::Document that takes + # the collection's URL template into account. The default URL template can + # be overriden in the collection's configuration in _config.yml. + def url + @url ||= if @collection.nil? + relative_path + else + ::Jekyll::URL.new({ + template: @collection.url_template, + placeholders: placeholders, + }) + end.to_s.gsub /\/$/, '' + end + + # Returns the type of the collection if present, nil otherwise. + def type + @type ||= @collection.nil? ? nil : @collection.label.to_sym + end + + # Returns the front matter defaults defined for the file's URL and/or type + # as defined in _config.yml. + def defaults + @defaults ||= @site.frontmatter_defaults.all url, type + end end end diff --git a/test/test_static_file.rb b/test/test_static_file.rb index 3285f95217e..3af7a1f0e45 100644 --- a/test/test_static_file.rb +++ b/test/test_static_file.rb @@ -18,6 +18,16 @@ def setup_static_file(base, dir, name) StaticFile.new(@site, base, dir, name) end + def setup_static_file_with_collection(base, dir, name, label, metadata) + site = fixture_site 'collections' => {label => metadata} + StaticFile.new(site, base, dir, name, site.collections[label]) + end + + def setup_static_file_with_defaults(base, dir, name, defaults) + site = fixture_site 'defaults' => defaults + StaticFile.new(site, base, dir, name) + end + context "A StaticFile" do setup do clear_dest @@ -46,7 +56,44 @@ def setup_static_file(base, dir, name) should "have a destination relative directory without a collection" do static_file = setup_static_file("root", "dir/subdir", "file.html") - assert "dir/subdir", static_file.destination_rel_dir + assert_equal nil, static_file.type + assert_equal "dir/subdir/file.html", static_file.url + assert_equal "dir/subdir", static_file.destination_rel_dir + end + + should "have a destination relative directory with a collection" do + static_file = setup_static_file_with_collection( + "root", "_foo/dir/subdir", "file.html", "foo", {"output" => true}) + assert_equal :foo, static_file.type + assert_equal "/foo/dir/subdir/file.html", static_file.url + assert_equal "/foo/dir/subdir", static_file.destination_rel_dir + end + + should "use its collection's permalink template for the destination relative directory" do + static_file = setup_static_file_with_collection( + "root", "_foo/dir/subdir", "file.html", "foo", + {"output" => true, "permalink" => "/:path/"}) + assert_equal :foo, static_file.type + assert_equal "/dir/subdir/file.html", static_file.url + assert_equal "/dir/subdir", static_file.destination_rel_dir + end + + should "be writable by default" do + static_file = setup_static_file("root", "dir/subdir", "file.html") + assert(static_file.write?, + "static_file.write? should return true by default") + end + + should "use the _config.yml defaults to determine writability" do + defaults = [{ + "scope" => {"path" => "private"}, + "values" => {"published" => false} + }] + static_file = setup_static_file_with_defaults( + "root", "private/dir/subdir", "file.html", defaults) + assert(!static_file.write?, + "static_file.write? should return false when _config.yml sets " + + "`published: false`") end should "know its last modification time" do