From ba8607f276320244028a2a4efc5a0dc34eba8822 Mon Sep 17 00:00:00 2001 From: Jared White Date: Fri, 11 Sep 2020 09:51:52 -0700 Subject: [PATCH] Process data cascade for folder-based frontmatter defaults (#139) * Process data cascade for folder-based frontmatter defaults * Fix bogus image URL * Test the new data cascade defaults --- bridgetown-core/lib/bridgetown-core.rb | 1 + .../concerns/site/configurable.rb | 4 +++ .../bridgetown-core/frontmatter_defaults.rb | 17 ++++++++++++ bridgetown-core/lib/bridgetown-core/reader.rb | 1 + .../readers/collection_reader.rb | 1 + .../bridgetown-core/readers/data_reader.rb | 1 + .../readers/defaults_reader.rb | 27 +++++++++++++++++++ .../bridgetown-core/readers/layout_reader.rb | 1 + .../bridgetown-core/readers/page_reader.rb | 1 + .../bridgetown-core/readers/post_reader.rb | 1 + .../readers/static_file_reader.rb | 1 + .../test/source/src/_posts/_defaults.yml | 1 + .../test/source/src/_posts/es/_defaults.yml | 1 + .../es/further/2020-09-10-further-nested.md | 8 ++++++ bridgetown-core/test/test_defaults_reader.rb | 17 ++++++++++++ bridgetown-core/test/test_filters.rb | 1 + .../test/test_front_matter_defaults.rb | 15 +++++++++++ bridgetown-core/test/test_generated_site.rb | 2 +- bridgetown-core/test/test_site.rb | 2 +- bridgetown-website/bridgetown.config.yml | 19 ------------- bridgetown-website/src/_defaults.yml | 1 + bridgetown-website/src/_docs/_defaults.yml | 1 + bridgetown-website/src/_posts/_defaults.yml | 2 ++ .../src/_posts/drafts/_defaults.yml | 1 + 24 files changed, 106 insertions(+), 21 deletions(-) create mode 100644 bridgetown-core/lib/bridgetown-core/readers/defaults_reader.rb create mode 100644 bridgetown-core/test/source/src/_posts/_defaults.yml create mode 100644 bridgetown-core/test/source/src/_posts/es/_defaults.yml create mode 100644 bridgetown-core/test/source/src/_posts/es/further/2020-09-10-further-nested.md create mode 100644 bridgetown-core/test/test_defaults_reader.rb create mode 100644 bridgetown-website/src/_defaults.yml create mode 100644 bridgetown-website/src/_docs/_defaults.yml create mode 100644 bridgetown-website/src/_posts/_defaults.yml create mode 100644 bridgetown-website/src/_posts/drafts/_defaults.yml diff --git a/bridgetown-core/lib/bridgetown-core.rb b/bridgetown-core/lib/bridgetown-core.rb index 98e42e965..bd317ac4a 100644 --- a/bridgetown-core/lib/bridgetown-core.rb +++ b/bridgetown-core/lib/bridgetown-core.rb @@ -68,6 +68,7 @@ module Bridgetown autoload :Cache, "bridgetown-core/cache" autoload :CollectionReader, "bridgetown-core/readers/collection_reader" autoload :DataReader, "bridgetown-core/readers/data_reader" + autoload :DefaultsReader, "bridgetown-core/readers/defaults_reader" autoload :LayoutReader, "bridgetown-core/readers/layout_reader" autoload :PostReader, "bridgetown-core/readers/post_reader" autoload :PageReader, "bridgetown-core/readers/page_reader" diff --git a/bridgetown-core/lib/bridgetown-core/concerns/site/configurable.rb b/bridgetown-core/lib/bridgetown-core/concerns/site/configurable.rb index 2dfca39e9..2b17e1855 100644 --- a/bridgetown-core/lib/bridgetown-core/concerns/site/configurable.rb +++ b/bridgetown-core/lib/bridgetown-core/concerns/site/configurable.rb @@ -37,6 +37,10 @@ def config=(config) @config end + def defaults_reader + @defaults_reader ||= DefaultsReader.new(self) + end + # Returns the current instance of {FrontmatterDefaults} or # creates a new instance {FrontmatterDefaults} if it doesn't already exist. # diff --git a/bridgetown-core/lib/bridgetown-core/frontmatter_defaults.rb b/bridgetown-core/lib/bridgetown-core/frontmatter_defaults.rb index a479da0b6..aa976f186 100644 --- a/bridgetown-core/lib/bridgetown-core/frontmatter_defaults.rb +++ b/bridgetown-core/lib/bridgetown-core/frontmatter_defaults.rb @@ -54,6 +54,10 @@ def ensure_time!(set) # # Returns the default value or nil if none was found def find(path, type, setting) + merged_data = {} + merge_data_cascade_for_path(path, merged_data) + return merged_data[setting] if merged_data.key?(setting) + value = nil old_scope = nil @@ -74,6 +78,9 @@ def find(path, type, setting) # Returns a hash with all default values (an empty hash if there are none) def all(path, type) defaults = {} + + merge_data_cascade_for_path(path, defaults) + old_scope = nil matching_sets(path, type).each do |set| if has_precedence?(old_scope, set["scope"]) @@ -88,6 +95,16 @@ def all(path, type) private + def merge_data_cascade_for_path(path, merged_data) + absolute_path = @site.in_source_dir(path) + @site.defaults_reader.path_defaults + .select { |k, _v| absolute_path.include? k } + .sort_by { |k, _v| k.length } + .each do |defaults| + merged_data.merge!(defaults[1]) + end + end + # Checks if a given default setting scope matches the given path and type # # scope - the hash indicating the scope, as defined in bridgetown.config.yml diff --git a/bridgetown-core/lib/bridgetown-core/reader.rb b/bridgetown-core/lib/bridgetown-core/reader.rb index 0b87628f4..c3066f482 100644 --- a/bridgetown-core/lib/bridgetown-core/reader.rb +++ b/bridgetown-core/lib/bridgetown-core/reader.rb @@ -13,6 +13,7 @@ def initialize(site) # Returns nothing. # rubocop:disable Metrics/AbcSize def read + @site.defaults_reader.read @site.layouts = LayoutReader.new(site).read read_directories read_included_excludes diff --git a/bridgetown-core/lib/bridgetown-core/readers/collection_reader.rb b/bridgetown-core/lib/bridgetown-core/readers/collection_reader.rb index 60148f3f7..7a9b26af1 100644 --- a/bridgetown-core/lib/bridgetown-core/readers/collection_reader.rb +++ b/bridgetown-core/lib/bridgetown-core/readers/collection_reader.rb @@ -5,6 +5,7 @@ class CollectionReader SPECIAL_COLLECTIONS = %w(posts data).freeze attr_reader :site, :content + def initialize(site) @site = site @content = {} diff --git a/bridgetown-core/lib/bridgetown-core/readers/data_reader.rb b/bridgetown-core/lib/bridgetown-core/readers/data_reader.rb index c3208a85c..3cc919d77 100644 --- a/bridgetown-core/lib/bridgetown-core/readers/data_reader.rb +++ b/bridgetown-core/lib/bridgetown-core/readers/data_reader.rb @@ -3,6 +3,7 @@ module Bridgetown class DataReader attr_reader :site, :content + def initialize(site) @site = site @content = ActiveSupport::HashWithIndifferentAccess.new diff --git a/bridgetown-core/lib/bridgetown-core/readers/defaults_reader.rb b/bridgetown-core/lib/bridgetown-core/readers/defaults_reader.rb new file mode 100644 index 000000000..a9f5d0af6 --- /dev/null +++ b/bridgetown-core/lib/bridgetown-core/readers/defaults_reader.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Bridgetown + class DefaultsReader + attr_reader :site, :path_defaults + + def initialize(site) + @site = site + @path_defaults = ActiveSupport::HashWithIndifferentAccess.new + end + + def read + return unless File.directory?(site.source) + + entries = Dir.chdir(site.source) do + Dir["**/_defaults.{yaml,yml,json}"] + end + + entries.each do |entry| + path = @site.in_source_dir(entry) + @path_defaults[File.dirname(path) + File::SEPARATOR] = SafeYAML.load_file(path) + end + + @path_defaults + end + end +end diff --git a/bridgetown-core/lib/bridgetown-core/readers/layout_reader.rb b/bridgetown-core/lib/bridgetown-core/readers/layout_reader.rb index c3259293b..ae6991300 100644 --- a/bridgetown-core/lib/bridgetown-core/readers/layout_reader.rb +++ b/bridgetown-core/lib/bridgetown-core/readers/layout_reader.rb @@ -3,6 +3,7 @@ module Bridgetown class LayoutReader attr_reader :site + def initialize(site) @site = site @layouts = {} diff --git a/bridgetown-core/lib/bridgetown-core/readers/page_reader.rb b/bridgetown-core/lib/bridgetown-core/readers/page_reader.rb index 467014a64..db6a69aee 100644 --- a/bridgetown-core/lib/bridgetown-core/readers/page_reader.rb +++ b/bridgetown-core/lib/bridgetown-core/readers/page_reader.rb @@ -3,6 +3,7 @@ module Bridgetown class PageReader attr_reader :site, :dir, :unfiltered_content + def initialize(site, dir) @site = site @dir = dir diff --git a/bridgetown-core/lib/bridgetown-core/readers/post_reader.rb b/bridgetown-core/lib/bridgetown-core/readers/post_reader.rb index e7d4ff32e..063a2e05b 100644 --- a/bridgetown-core/lib/bridgetown-core/readers/post_reader.rb +++ b/bridgetown-core/lib/bridgetown-core/readers/post_reader.rb @@ -3,6 +3,7 @@ module Bridgetown class PostReader attr_reader :site, :unfiltered_content + def initialize(site) @site = site end diff --git a/bridgetown-core/lib/bridgetown-core/readers/static_file_reader.rb b/bridgetown-core/lib/bridgetown-core/readers/static_file_reader.rb index 78347d6bd..b715c2a22 100644 --- a/bridgetown-core/lib/bridgetown-core/readers/static_file_reader.rb +++ b/bridgetown-core/lib/bridgetown-core/readers/static_file_reader.rb @@ -3,6 +3,7 @@ module Bridgetown class StaticFileReader attr_reader :site, :dir, :unfiltered_content + def initialize(site, dir) @site = site @dir = dir diff --git a/bridgetown-core/test/source/src/_posts/_defaults.yml b/bridgetown-core/test/source/src/_posts/_defaults.yml new file mode 100644 index 000000000..10deab66e --- /dev/null +++ b/bridgetown-core/test/source/src/_posts/_defaults.yml @@ -0,0 +1 @@ +ruby3: groovy diff --git a/bridgetown-core/test/source/src/_posts/es/_defaults.yml b/bridgetown-core/test/source/src/_posts/es/_defaults.yml new file mode 100644 index 000000000..904be5877 --- /dev/null +++ b/bridgetown-core/test/source/src/_posts/es/_defaults.yml @@ -0,0 +1 @@ +ruby3: trippin diff --git a/bridgetown-core/test/source/src/_posts/es/further/2020-09-10-further-nested.md b/bridgetown-core/test/source/src/_posts/es/further/2020-09-10-further-nested.md new file mode 100644 index 000000000..895fb6a89 --- /dev/null +++ b/bridgetown-core/test/source/src/_posts/es/further/2020-09-10-further-nested.md @@ -0,0 +1,8 @@ +--- +layout: default +title: Further Nested +--- + +url: {{ page.url }} +date: {{ page.date }} +id: {{ page.id }} diff --git a/bridgetown-core/test/test_defaults_reader.rb b/bridgetown-core/test/test_defaults_reader.rb new file mode 100644 index 000000000..920ae178e --- /dev/null +++ b/bridgetown-core/test/test_defaults_reader.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require "helper" + +class TestDefaultsReader < BridgetownUnitTest + def setup + @reader = DefaultsReader.new(fixture_site) + @reader.read + end + + context "default files" do + should "be loaded" do + assert_equal "groovy", @reader.path_defaults[fixture_site.source + "/_posts/"][:ruby3] + assert_equal "trippin", @reader.path_defaults[fixture_site.source + "/_posts/es/"][:ruby3] + end + end +end diff --git a/bridgetown-core/test/test_filters.rb b/bridgetown-core/test/test_filters.rb index 89ab984c7..e25c686fd 100644 --- a/bridgetown-core/test/test_filters.rb +++ b/bridgetown-core/test/test_filters.rb @@ -657,6 +657,7 @@ def select; end "categories" => [ "publish_test", ], + "ruby3" => "groovy", "layout" => "default", "title" => "Publish", "category" => "publish_test", diff --git a/bridgetown-core/test/test_front_matter_defaults.rb b/bridgetown-core/test/test_front_matter_defaults.rb index e9cea856b..e9133504b 100644 --- a/bridgetown-core/test/test_front_matter_defaults.rb +++ b/bridgetown-core/test/test_front_matter_defaults.rb @@ -222,4 +222,19 @@ class TestFrontMatterDefaults < BridgetownUnitTest assert(@site.posts.find { |page| page.data["date"] == date }) end end + + context "A site with front matter data cascade" do + setup do + @site = fixture_site + @site.process + end + + should "have a post with a value from the defaults file" do + assert(@site.posts.find { |page| page.data[:title] == "Post with Permalink" }.data[:ruby3] == "groovy") + end + + should "have an overridden value in a subtree" do + assert(@site.posts.find { |page| page.data[:title] == "Further Nested" }.data[:ruby3] == "trippin") + end + end end diff --git a/bridgetown-core/test/test_generated_site.rb b/bridgetown-core/test/test_generated_site.rb index 714297e24..d14393060 100644 --- a/bridgetown-core/test/test_generated_site.rb +++ b/bridgetown-core/test/test_generated_site.rb @@ -16,7 +16,7 @@ class TestGeneratedSite < BridgetownUnitTest end should "ensure post count is as expected" do - assert_equal 60, @site.posts.size + assert_equal 61, @site.posts.size end should "insert site.posts into the index" do diff --git a/bridgetown-core/test/test_site.rb b/bridgetown-core/test/test_site.rb index 03d3fa58e..0efcb9c58 100644 --- a/bridgetown-core/test/test_site.rb +++ b/bridgetown-core/test/test_site.rb @@ -53,7 +53,7 @@ def read_posts context "creating sites" do setup do @site = Site.new(site_configuration) - @num_invalid_posts = 5 + @num_invalid_posts = 7 end teardown do diff --git a/bridgetown-website/bridgetown.config.yml b/bridgetown-website/bridgetown.config.yml index 2d8103d7a..ed5d370c9 100644 --- a/bridgetown-website/bridgetown.config.yml +++ b/bridgetown-website/bridgetown.config.yml @@ -14,25 +14,6 @@ collections: name: Documentation foo: bar -defaults: - - scope: - path: "" - values: - image: /images/bridgetown-logo-twitter-card.jpg - - scope: - path: _docs - values: - layout: docs - - scope: - path: _posts - values: - layout: post - category: news - - scope: - path: _posts/drafts - values: - published: false - pagination: enabled: true diff --git a/bridgetown-website/src/_defaults.yml b/bridgetown-website/src/_defaults.yml new file mode 100644 index 000000000..d18fdd5e8 --- /dev/null +++ b/bridgetown-website/src/_defaults.yml @@ -0,0 +1 @@ +image: /images/bridgetown-logo-twitter-card.jpg diff --git a/bridgetown-website/src/_docs/_defaults.yml b/bridgetown-website/src/_docs/_defaults.yml new file mode 100644 index 000000000..df5d36a64 --- /dev/null +++ b/bridgetown-website/src/_docs/_defaults.yml @@ -0,0 +1 @@ +layout: docs diff --git a/bridgetown-website/src/_posts/_defaults.yml b/bridgetown-website/src/_posts/_defaults.yml new file mode 100644 index 000000000..bf162af9f --- /dev/null +++ b/bridgetown-website/src/_posts/_defaults.yml @@ -0,0 +1,2 @@ +layout: post +category: news diff --git a/bridgetown-website/src/_posts/drafts/_defaults.yml b/bridgetown-website/src/_posts/drafts/_defaults.yml new file mode 100644 index 000000000..eee85139f --- /dev/null +++ b/bridgetown-website/src/_posts/drafts/_defaults.yml @@ -0,0 +1 @@ +published: false