module Jekyll::Utils

Constants

SLUGIFY_DEFAULT_REGEXP
SLUGIFY_MODES

Constants for use in slugify

SLUGIFY_PRETTY_REGEXP
SLUGIFY_RAW_REGEXP

Public Instance Methods

deep_merge_hashes(master_hash, other_hash) click to toggle source

Non-destructive version of #deep_merge_hashes! See that method.

Returns the merged hashes.

# File lib/jekyll/utils.rb, line 30
def deep_merge_hashes(master_hash, other_hash)
  deep_merge_hashes!(master_hash.dup, other_hash)
end
deep_merge_hashes!(target, overwrite) click to toggle source

Merges a master hash with another hash, recursively.

master_hash - the “parent” hash whose values will be overridden other_hash - the other hash whose values will be persisted after the merge

This code was lovingly stolen from some random gem: gemjack.com/gems/tartan-0.1.1/classes/Hash.html

Thanks to whoever made it.

# File lib/jekyll/utils.rb, line 43
def deep_merge_hashes!(target, overwrite)
  target.merge!(overwrite) do |key, old_val, new_val|
    if new_val.nil?
      old_val
    else
      mergable?(old_val) && mergable?(new_val) ? deep_merge_hashes(old_val, new_val) : new_val
    end
  end

  if target.respond_to?(:default_proc) && overwrite.respond_to?(:default_proc) && target.default_proc.nil?
    target.default_proc = overwrite.default_proc
  end

  target
end
has_yaml_header?(file) click to toggle source

Determines whether a given file has

Returns true if the YAML front matter is present.

# File lib/jekyll/utils.rb, line 135
def has_yaml_header?(file)
  !!(File.open(file, 'rb') { |f| f.readline } =~ /\A---\s*\r?\n/)
rescue EOFError
  false
end
mergable?(value) click to toggle source
# File lib/jekyll/utils.rb, line 59
def mergable?(value)
  value.is_a?(Hash) || value.is_a?(Drops::Drop)
end
merged_file_read_opts(site, opts) click to toggle source

Returns merged option hash for File.read of self.site (if exists) and a given param

# File lib/jekyll/utils.rb, line 278
def merged_file_read_opts(site, opts)
  merged = (site ? site.file_read_opts : {}).merge(opts)
  if merged["encoding"] && !merged["encoding"].start_with?("bom|")
    merged["encoding"].insert(0, "bom|")
  end
  merged
end
parse_date(input, msg = "Input could not be parsed.") click to toggle source

Parse a date/time and throw an error if invalid

input - the date/time to parse msg - (optional) the error message to show the user

Returns the parsed date if successful, throws a FatalException if not

# File lib/jekyll/utils.rb, line 126
def parse_date(input, msg = "Input could not be parsed.")
  Time.parse(input).localtime
rescue ArgumentError
  raise Errors::FatalException.new("Invalid date '#{input}': " + msg)
end
pluralized_array_from_hash(hash, singular_key, plural_key) click to toggle source

Read array from the supplied hash favouring the singular key and then the plural key, and handling any nil entries.

hash - the hash to read from singular_key - the singular key plural_key - the plural key

Returns an array

# File lib/jekyll/utils.rb, line 71
def pluralized_array_from_hash(hash, singular_key, plural_key)
  [].tap do |array|
    array << (value_from_singular_key(hash, singular_key) || value_from_plural_key(hash, plural_key))
  end.flatten.compact
end
safe_glob(dir, patterns, flags = 0) click to toggle source

Work the same way as Dir.glob but seperating the input into two parts ('dir' + '/' + 'pattern') to make sure the first part('dir') does not act as a pattern.

For example, Dir.glob(“path[/*”) always returns an empty array, because the method fails to find the closing pattern to '[' which is ']'

Examples:

safe_glob("path[", "*")
# => ["path[/file1", "path[/file2"]

safe_glob("path", "*", File::FNM_DOTMATCH)
# => ["path/.", "path/..", "path/file1"]

safe_glob("path", ["**", "*"])
# => ["path[/file1", "path[/folder/file2"]

dir - the dir where glob will be executed under

(the dir will be included to each result)

patterns - the patterns (or the pattern) which will be applied under the dir flags - the flags which will be applied to the pattern

Returns matched pathes

# File lib/jekyll/utils.rb, line 267
def safe_glob(dir, patterns, flags = 0)
  return [] unless Dir.exist?(dir)
  pattern = File.join(Array patterns)
  return [dir] if pattern.empty?
  Dir.chdir(dir) do
    Dir.glob(pattern, flags).map { |f| File.join(dir, f) }
  end
end
slugify(string, mode: nil, cased: false) click to toggle source

Slugify a filename or title.

string - the filename or title to slugify mode - how string is slugified cased - whether to replace all uppercase letters with their lowercase counterparts

When mode is “none”, return the given string.

When mode is “raw”, return the given string, with every sequence of spaces characters replaced with a hyphen.

When mode is “default” or nil, non-alphabetic characters are replaced with a hyphen too.

When mode is “pretty”, some non-alphabetic characters (._~!$&'()+,;=@) are not replaced with hyphen.

If cased is true, all uppercase letters in the result string are replaced with their lowercase counterparts.

Examples:

slugify("The _config.yml file")
# => "the-config-yml-file"

slugify("The _config.yml file", "pretty")
# => "the-_config.yml-file"

slugify("The _config.yml file", "pretty", true)
# => "The-_config.yml file"

Returns the slugified string.

# File lib/jekyll/utils.rb, line 173
def slugify(string, mode: nil, cased: false)
  mode ||= 'default'
  return nil if string.nil?

  unless SLUGIFY_MODES.include?(mode)
    return cased ? string : string.downcase
  end

  # Replace each character sequence with a hyphen
  re =
    case mode
    when 'raw'
      SLUGIFY_RAW_REGEXP
    when 'default'
      SLUGIFY_DEFAULT_REGEXP
    when 'pretty'
      # "._~!$&'()+,;=@" is human readable (not URI-escaped) in URL
      # and is allowed in both extN and NTFS.
      SLUGIFY_PRETTY_REGEXP
    end

  # Strip according to the mode
  slug = string.gsub(re, '-')

  # Remove leading/trailing hyphen
  slug.gsub!(/^\-|\-$/i, '')

  slug.downcase! unless cased
  slug
end
stringify_hash_keys(hash) click to toggle source

Apply to_s to all keys in the Hash

hash - the hash to which to apply this transformation

Returns a new hash with stringified keys

# File lib/jekyll/utils.rb, line 115
def stringify_hash_keys(hash)
  transform_keys(hash) { |key| key.to_s rescue key }
end
strip_heredoc(str) click to toggle source

Takes an indented string and removes the preceding spaces on each line

# File lib/jekyll/utils.rb, line 15
def strip_heredoc(str)
  str.gsub(/^[ \t]{#{(str.scan(/^[ \t]*(?=\S)/).min || "").size}}/, "")
end
symbolize_hash_keys(hash) click to toggle source

Apply to_sym to all keys in the hash

hash - the hash to which to apply this transformation

Returns a new hash with symbolized keys

# File lib/jekyll/utils.rb, line 106
def symbolize_hash_keys(hash)
  transform_keys(hash) { |key| key.to_sym rescue key }
end
titleize_slug(slug) click to toggle source

Takes a slug and turns it into a simple title.

# File lib/jekyll/utils.rb, line 21
def titleize_slug(slug)
  slug.split("-").map! do |val|
    val.capitalize
  end.join(" ")
end
transform_keys(hash) { |key| ... } click to toggle source
# File lib/jekyll/utils.rb, line 93
def transform_keys(hash)
  result = {}
  hash.each_key do |key|
    result[yield(key)] = hash[key]
  end
  result
end
value_from_plural_key(hash, key) click to toggle source
# File lib/jekyll/utils.rb, line 81
def value_from_plural_key(hash, key)
  if hash.key?(key) || (hash.default_proc && hash[key])
    val = hash[key]
    case val
    when String
      val.split
    when Array
      val.compact
    end
  end
end
value_from_singular_key(hash, key) click to toggle source
# File lib/jekyll/utils.rb, line 77
def value_from_singular_key(hash, key)
  hash[key] if hash.key?(key) || (hash.default_proc && hash[key])
end