This class handles custom defaults for YAML frontmatter settings. These are set in _config.yml and apply both to internal use (e.g. layout) and the data available to liquid.
It is exposed via the frontmatter_defaults method on the site class.
Initializes a new instance.
# File lib/jekyll/frontmatter_defaults.rb, line 9 def initialize(site) @site = site end
Collects a hash with all default values for a page or post
path - the relative path of the page or post type - a symbol indicating the type (:post, :page or :draft)
Returns a hash with all default values (an empty hash if there are none)
# File lib/jekyll/frontmatter_defaults.rb, line 71 def all(path, type) defaults = {} old_scope = nil matching_sets(path, type).each do |set| if has_precedence?(old_scope, set["scope"]) defaults = Utils.deep_merge_hashes(defaults, set["values"]) old_scope = set["scope"] else defaults = Utils.deep_merge_hashes(set["values"], defaults) end end defaults end
# File lib/jekyll/frontmatter_defaults.rb, line 34 def ensure_time!(set) return set unless set.key?("values") && set["values"].key?("date") return set if set["values"]["date"].is_a?(Time) set["values"]["date"] = Utils.parse_date( set["values"]["date"], "An invalid date format was found in a front-matter default set: #{set}" ) set end
Finds a default value for a given setting, filtered by path and type
path - the path (relative to the source) of the page, post or :draft the default is used in type - a symbol indicating whether a :page, a :post or a :draft calls this method
Returns the default value or nil if none was found
# File lib/jekyll/frontmatter_defaults.rb, line 52 def find(path, type, setting) value = nil old_scope = nil matching_sets(path, type).each do |set| if set["values"].key?(setting) && has_precedence?(old_scope, set["scope"]) value = set["values"][setting] old_scope = set["scope"] end end value end
# File lib/jekyll/frontmatter_defaults.rb, line 13 def update_deprecated_types(set) return set unless set.key?("scope") && set["scope"].key?("type") set["scope"]["type"] = case set["scope"]["type"] when "page" Deprecator.defaults_deprecate_type("page", "pages") "pages" when "post" Deprecator.defaults_deprecate_type("post", "posts") "posts" when "draft" Deprecator.defaults_deprecate_type("draft", "drafts") "drafts" else set["scope"]["type"] end set end
Checks if a given default setting scope matches the given path and type
scope - the hash indicating the scope, as defined in _config.yml path - the path to check for type - the type (:post, :page or :draft) to check for
Returns true if the scope applies to the given path and type
# File lib/jekyll/frontmatter_defaults.rb, line 94 def applies?(scope, path, type) applies_path?(scope, path) && applies_type?(scope, type) end
# File lib/jekyll/frontmatter_defaults.rb, line 98 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 return true end end end
Determines whether the scope applies to type. The scope applies to the type if:
1. no 'type' is specified 2. the 'type' in the scope is the same as the type asked about
scope - the Hash defaults set being asked about application type - the type of the document being processed / asked about
its defaults.
Returns true if either of the above conditions are satisfied,
otherwise returns false
# File lib/jekyll/frontmatter_defaults.rb, line 120 def applies_type?(scope, type) !scope.key?("type") || scope["type"].eql?(type.to_s) end
Determines if a new scope has precedence over an old one
old_scope - the old scope hash, or nil if there's none new_scope - the new scope hash
Returns true if the new scope has precedence over the older rubocop: disable PredicateName
# File lib/jekyll/frontmatter_defaults.rb, line 140 def has_precedence?(old_scope, new_scope) return true if old_scope.nil? new_path = sanitize_path(new_scope["path"]) old_path = sanitize_path(old_scope["path"]) if new_path.length != old_path.length new_path.length >= old_path.length elsif new_scope.key?("type") true else !old_scope.key? "type" end end
Collects a list of sets that match the given path and type
Returns an array of hashes
# File lib/jekyll/frontmatter_defaults.rb, line 159 def matching_sets(path, type) valid_sets.select do |set| !set.key?("scope") || applies?(set["scope"], path, type) end end
Sanitizes the given path by removing a leading and adding a trailing slash
# File lib/jekyll/frontmatter_defaults.rb, line 187 def sanitize_path(path) if path.nil? || path.empty? "" else path.gsub(%r\A/!, "").gsub(%r([^/])\z!, '\1') end end
Checks if a given set of default values is valid
set - the default value hash, as defined in _config.yml
Returns true if the set is valid and can be used in this class
# File lib/jekyll/frontmatter_defaults.rb, line 129 def valid?(set) set.is_a?(Hash) && set["values"].is_a?(Hash) end
Returns a list of valid sets
This is not cached to allow plugins to modify the configuration and have their changes take effect
Returns an array of hashes
# File lib/jekyll/frontmatter_defaults.rb, line 171 def valid_sets sets = @site.config["defaults"] return [] unless sets.is_a?(Array) sets.map do |set| if valid?(set) ensure_time!(update_deprecated_types(set)) else Jekyll.logger.warn "Defaults:", "An invalid front-matter default set was found:" Jekyll.logger.warn set.to_s nil end end.compact end