module Bunto::Utils

Constants

SLUGIFY_ASCII_REGEXP
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/bunto/utils.rb, line 32
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/bunto/utils.rb, line 45
def deep_merge_hashes!(target, overwrite)
  merge_values(target, overwrite)
  merge_default_proc(target, overwrite)
  duplicate_frozen_values(target)

  target
end
duplicable?(obj) click to toggle source
# File lib/bunto/utils.rb, line 57
def duplicable?(obj)
  case obj
  when nil, false, true, Symbol, Numeric
    false
  else
    true
  end
end
has_yaml_header?(file) click to toggle source

Determines whether a given file has

Returns true if the YAML front matter is present. rubocop: disable PredicateName

# File lib/bunto/utils.rb, line 141
def has_yaml_header?(file)
  !!(File.open(file, "rb", &:readline) =~ %r!\A---\s*\r?\n!)
rescue EOFError
  false
end
mergable?(value) click to toggle source
# File lib/bunto/utils.rb, line 53
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/bunto/utils.rb, line 296
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/bunto/utils.rb, line 131
def parse_date(input, msg = "Input could not be parsed.")
  Time.parse(input).localtime
rescue ArgumentError
  raise Errors::InvalidDateError, "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/bunto/utils.rb, line 74
def pluralized_array_from_hash(hash, singular_key, plural_key)
  [].tap do |array|
    value = value_from_singular_key(hash, singular_key)
    value ||= value_from_plural_key(hash, plural_key)
    array << value
  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/bunto/utils.rb, line 285
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.

When mode is “ascii”, some everything else except ASCII characters a-z (lowercase), A-Z (uppercase) and 0-9 (numbers) 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"

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

Returns the slugified string.

# File lib/bunto/utils.rb, line 186
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
    when "ascii"
      # For web servers not being able to handle Unicode, the safe
      # method is to ditch anything else but latin letters and numeric
      # digits.
      SLUGIFY_ASCII_REGEXP
    end

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

  # Remove leading/trailing hyphen
  slug.gsub!(%r!^\-|\-$!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/bunto/utils.rb, line 120
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/bunto/utils.rb, line 19
def strip_heredoc(str)
  str.gsub(%r!^[ \t]{#{(str.scan(%r!^[ \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/bunto/utils.rb, line 111
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/bunto/utils.rb, line 25
def titleize_slug(slug)
  slug.split("-").map!(&:capitalize).join(" ")
end
transform_keys(hash) { |key| ... } click to toggle source
# File lib/bunto/utils.rb, line 98
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/bunto/utils.rb, line 86
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/bunto/utils.rb, line 82
def value_from_singular_key(hash, key)
  hash[key] if hash.key?(key) || (hash.default_proc && hash[key])
end

Private Instance Methods

duplicate_frozen_values(target) click to toggle source
# File lib/bunto/utils.rb, line 325
def duplicate_frozen_values(target)
  target.each do |key, val|
    target[key] = val.dup if val.frozen? && duplicable?(val)
  end
end
merge_default_proc(target, overwrite) click to toggle source
# File lib/bunto/utils.rb, line 318
def merge_default_proc(target, overwrite)
  if target.is_a?(Hash) && overwrite.is_a?(Hash) && target.default_proc.nil?
    target.default_proc = overwrite.default_proc
  end
end
merge_values(target, overwrite) click to toggle source
# File lib/bunto/utils.rb, line 305
def merge_values(target, overwrite)
  target.merge!(overwrite) do |_key, old_val, new_val|
    if new_val.nil?
      old_val
    elsif mergable?(old_val) && mergable?(new_val)
      deep_merge_hashes(old_val, new_val)
    else
      new_val
    end
  end
end