Module: Fatty::Themes::Loader

Defined in:
lib/fatty/themes/loader.rb

Constant Summary collapse

RESERVED_KEYS =
%i[name inherit markdown].freeze
ROLE_ALIASES =
{
  status_good: :good,
  status_info: :info,
  status_warn: :warn,
  status_error: :error,

  search: :search_input,
  search_highlight: :match_current,
  search_highlight_secondary: :match_other,
}.freeze

Class Method Summary collapse

Class Method Details

.load_dir(path, registry:) ⇒ Object



21
22
23
24
25
26
# File 'lib/fatty/themes/loader.rb', line 21

def self.load_dir(path, registry:)
  Dir.glob(File.join(path.to_s, "*.{yml,yaml}")).sort.each do |file|
    load_file(file, registry: registry)
  end
  registry
end

.load_file(path, registry:) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/fatty/themes/loader.rb', line 28

def self.load_file(path, registry:)
  data = YAML.safe_load_file(
    path,
    permitted_classes: [Symbol],
    aliases: false,
    symbolize_names: true,
  )

  unless data.is_a?(Hash)
    registry.warnings << "Theme file did not contain a mapping: #{path}"
    return
  end

  registry.add(normalize(data), source: path)
rescue Psych::Exception => e
  message = "Theme YAML error in #{path}: #{e.class}: #{e.message}"
  registry.warnings << message
  Fatty.warn(message, tag: :theme) if Fatty.respond_to?(:warn)
  nil
rescue StandardError => e
  message = "Theme load error in #{path}: #{e.class}: #{e.message}"
  registry.warnings << message
  Fatty.warn(message, tag: :theme) if Fatty.respond_to?(:warn)
  nil
end

.normalize(data) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/fatty/themes/loader.rb', line 54

def self.normalize(data)
  out = {
    name: normalize_optional_symbol(data[:name]),
    inherit: normalize_optional_symbol(data[:inherit]),
    roles: {},
  }

  data.each do |key, value|
    k = key.to_sym
    next if RESERVED_KEYS.include?(k)

    out[:roles][normalize_role_name(k)] = normalize_spec(value)
  end

  normalize_markdown_roles(data[:markdown]).each do |role, spec|
    out[:roles][role] ||= spec
  end

  out
end

.normalize_attrs(value) ⇒ Object



117
118
119
# File 'lib/fatty/themes/loader.rb', line 117

def self.normalize_attrs(value)
  Array(value).map(&:to_sym)
end

.normalize_markdown_roles(value) ⇒ Object



80
81
82
83
84
85
86
87
# File 'lib/fatty/themes/loader.rb', line 80

def self.normalize_markdown_roles(value)
  return {} unless value.is_a?(Hash)

  value.each_with_object({}) do |(key, spec), roles|
    role = :"markdown_#{normalize_role_name(key)}"
    roles[role] = normalize_spec(spec)
  end
end

.normalize_optional_symbol(value) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/fatty/themes/loader.rb', line 121

def self.normalize_optional_symbol(value)
  return if value.nil?

  text = value.to_s.strip
  return if text.empty?

  case text.downcase
  when "null", "nil", "none"
    nil
  else
    text.to_sym
  end
end

.normalize_role_name(name) ⇒ Object



75
76
77
78
# File 'lib/fatty/themes/loader.rb', line 75

def self.normalize_role_name(name)
  sym = name.to_sym
  ROLE_ALIASES.fetch(sym, sym)
end

.normalize_spec(spec_hash) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/fatty/themes/loader.rb', line 89

def self.normalize_spec(spec_hash)
  return {} unless spec_hash.is_a?(Hash)

  normalized =
    spec_hash.each_with_object({}) do |(k, v), h|
      key = k.to_sym
      h[key] =
        case key
        when :attr
          v
        when :attrs
          normalize_attrs(v)
        when :border, :corners
          normalize_optional_symbol(v)
        else
          v
        end
    end

  if normalized.key?(:attr)
    attr = normalized.delete(:attr)
    attrs = normalized.key?(:attrs) ? normalized[:attrs] : []
    normalized[:attrs] = normalize_attrs(attrs + Array(attr))
  end

  normalized
end