From a78b518f830a45769fc762ad59ba82c1d4c98f9b Mon Sep 17 00:00:00 2001 From: Alexey Pelykh Date: Mon, 9 Oct 2017 13:52:19 +0300 Subject: [PATCH] Scope path glob (#6268) Merge pull request 6268 --- docs/_docs/configuration.md | 15 +++++++++++++++ lib/jekyll/frontmatter_defaults.rb | 21 ++++++++++++++++++--- test/test_front_matter_defaults.rb | 24 ++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/docs/_docs/configuration.md b/docs/_docs/configuration.md index 0d9c8f72..cd0f2058 100644 --- a/docs/_docs/configuration.md +++ b/docs/_docs/configuration.md @@ -549,6 +549,21 @@ defaults: In this example, the `layout` is set to `default` inside the [collection](../collections/) with the name `my_collection`. +It is also possible to use glob patterns when matching defaults. For example, it is possible to set specific layout for each `special-page.html` in any subfolder of `section` folder. + +```yaml +collections: + my_collection: + output: true + +defaults: + - + scope: + path: "section/*/special-page.html" + values: + layout: "specific-layout" +``` + ### 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/lib/jekyll/frontmatter_defaults.rb b/lib/jekyll/frontmatter_defaults.rb index fc1bcc2d..f6b89f6b 100644 --- a/lib/jekyll/frontmatter_defaults.rb +++ b/lib/jekyll/frontmatter_defaults.rb @@ -100,12 +100,27 @@ module Jekyll def applies_path?(scope, path) return true if !scope.key?("path") || scope["path"].empty? - scope_path = Pathname.new(scope["path"]) - Pathname.new(sanitize_path(path)).ascend do |ascended_path| - if ascended_path.to_s == scope_path.to_s + sanitized_path = Pathname.new(sanitize_path(path)) + + site_path = Pathname.new(@site.source) + rel_scope_path = Pathname.new(scope["path"]) + abs_scope_path = File.join(@site.source, rel_scope_path) + Dir.glob(abs_scope_path).each do |scope_path| + scope_path = Pathname.new(scope_path).relative_path_from site_path + return true if path_is_subpath?(sanitized_path, scope_path) + end + + path_is_subpath?(sanitized_path, rel_scope_path) + end + + def path_is_subpath?(path, parent_path) + path.ascend do |ascended_path| + if ascended_path.to_s == parent_path.to_s return true end end + + false end # Determines whether the scope applies to type. diff --git a/test/test_front_matter_defaults.rb b/test/test_front_matter_defaults.rb index 9bf9629a..b1773ba0 100644 --- a/test/test_front_matter_defaults.rb +++ b/test/test_front_matter_defaults.rb @@ -27,6 +27,30 @@ class TestFrontMatterDefaults < JekyllUnitTest end end + context "A site with full front matter defaults (glob)" do + setup do + @site = fixture_site({ + "defaults" => [{ + "scope" => { + "path" => "contacts/*.html", + "type" => "page", + }, + "values" => { + "key" => "val", + }, + },], + }) + @site.process + @affected = @site.pages.find { |page| page.relative_path == "contacts/bar.html" } + @not_affected = @site.pages.find { |page| page.relative_path == "about.html" } + end + + should "affect only the specified path and type" do + assert_equal @affected.data["key"], "val" + assert_nil @not_affected.data["key"] + end + end + context "A site with front matter type pages and an extension" do setup do @site = fixture_site({