Class: Herb::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/herb/configuration.rb

Constant Summary collapse

OPTIONS_PATH =

: String

File.expand_path("../../config/options.yml", __dir__ || __FILE__).freeze
OPTIONS =

: Hash[String, untyped]

YAML.safe_load_file(OPTIONS_PATH).freeze
VALID_FRAMEWORKS =

: Array

OPTIONS["framework"]["values"].freeze
VALID_TEMPLATE_ENGINES =

: Array

OPTIONS["template_engine"]["values"].freeze
CONFIG_FILENAMES =
[".herb.yml"].freeze
PROJECT_INDICATORS =
[
  ".git",
  ".herb",
  ".herb.yml",
  "Gemfile",
  "package.json",
  "Rakefile",
  "README.md",
  "*.gemspec",
  "config/application.rb"
].freeze
DEFAULTS_PATH =
File.expand_path("defaults.yml", __dir__ || __FILE__).freeze
DEFAULTS =
YAML.safe_load_file(DEFAULTS_PATH).freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_path = nil) ⇒ Configuration

Returns a new instance of Configuration.



33
34
35
36
37
38
# File 'lib/herb/configuration.rb', line 33

def initialize(project_path = nil)
  @start_path = project_path ? Pathname.new(project_path) : Pathname.pwd
  @config_path, @project_root = find_config_file
  @user_config = load_user_config
  @config = deep_merge(DEFAULTS, @user_config)
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



31
32
33
# File 'lib/herb/configuration.rb', line 31

def config
  @config
end

#config_pathObject (readonly)

Returns the value of attribute config_path.



31
32
33
# File 'lib/herb/configuration.rb', line 31

def config_path
  @config_path
end

#project_rootObject (readonly)

Returns the value of attribute project_root.



31
32
33
# File 'lib/herb/configuration.rb', line 31

def project_root
  @project_root
end

#user_configObject (readonly)

Returns the value of attribute user_config.



31
32
33
# File 'lib/herb/configuration.rb', line 31

def user_config
  @user_config
end

Class Method Details

.defaultObject



217
218
219
# File 'lib/herb/configuration.rb', line 217

def default
  @default ||= new
end

.default_exclude_patternsObject



225
226
227
# File 'lib/herb/configuration.rb', line 225

def default_exclude_patterns
  DEFAULTS.dig("files", "exclude") || []
end

.default_file_patternsObject



221
222
223
# File 'lib/herb/configuration.rb', line 221

def default_file_patterns
  DEFAULTS.dig("files", "include") || []
end

.load(project_path = nil) ⇒ Object



213
214
215
# File 'lib/herb/configuration.rb', line 213

def load(project_path = nil)
  new(project_path)
end

Instance Method Details

#[](key) ⇒ Object



40
41
42
# File 'lib/herb/configuration.rb', line 40

def [](key)
  @config[key.to_s]
end

#dig(*keys) ⇒ Object



44
45
46
# File 'lib/herb/configuration.rb', line 44

def dig(*keys)
  @config.dig(*keys.map(&:to_s))
end

#enabled_for_path?(path, tool) ⇒ Boolean

Returns:

  • (Boolean)


143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/herb/configuration.rb', line 143

def enabled_for_path?(path, tool)
  tool_config = send(tool.to_s)
  tool_include = tool_config["include"] || []
  tool_exclude = tool_config["exclude"] || []

  if tool_include.any? && path_included?(path, tool_include)
    return !path_excluded?(path, tool_exclude)
  end

  exclude_patterns = exclude_patterns_for(tool)

  !path_excluded?(path, exclude_patterns)
end

#enabled_validators(overrides = {}) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/herb/configuration.rb', line 101

def enabled_validators(overrides = {})
  config = dig("engine", "validators") || {}

  {
    security: config.fetch("security", true),
    nesting: config.fetch("nesting", true),
    accessibility: config.fetch("accessibility", true),
  }.merge(
    overrides.to_h { |key, value| [key.to_sym, !!value] }
  )
end

#engineObject



92
93
94
# File 'lib/herb/configuration.rb', line 92

def engine
  @config["engine"] || {}
end

#engine_option(key, default = nil) ⇒ Object

: (String, untyped) -> untyped



97
98
99
# File 'lib/herb/configuration.rb', line 97

def engine_option(key, default = nil)
  engine.fetch(key.to_s, default)
end

#exclude_patterns_for(tool) ⇒ Object



122
123
124
125
# File 'lib/herb/configuration.rb', line 122

def exclude_patterns_for(tool)
  tool_config = send(tool.to_s)
  file_exclude_patterns + (tool_config["exclude"] || [])
end

#file_exclude_patternsObject



84
85
86
# File 'lib/herb/configuration.rb', line 84

def file_exclude_patterns
  files["exclude"] || DEFAULTS.dig("files", "exclude") || []
end

#file_include_patternsObject



80
81
82
# File 'lib/herb/configuration.rb', line 80

def file_include_patterns
  files["include"] || DEFAULTS.dig("files", "include") || []
end

#filesObject



76
77
78
# File 'lib/herb/configuration.rb', line 76

def files
  @config["files"] || {}
end

#find_files(search_path = nil) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/herb/configuration.rb', line 173

def find_files(search_path = nil)
  search_path ||= @project_root || @start_path
  expanded_path = File.expand_path(search_path.to_s)

  all_files = file_include_patterns.flat_map do |pattern|
    Dir[File.join(expanded_path, pattern)]
  end.uniq

  all_files.reject do |file|
    relative = file.sub("#{expanded_path}/", "")
    path_excluded?(relative, file_exclude_patterns)
  end.sort
end

#find_files_for_formatter(search_path = nil) ⇒ Object



208
209
210
# File 'lib/herb/configuration.rb', line 208

def find_files_for_formatter(search_path = nil)
  find_files_for_tool(:formatter, search_path)
end

#find_files_for_linter(search_path = nil) ⇒ Object



204
205
206
# File 'lib/herb/configuration.rb', line 204

def find_files_for_linter(search_path = nil)
  find_files_for_tool(:linter, search_path)
end

#find_files_for_tool(tool, search_path = nil) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/herb/configuration.rb', line 187

def find_files_for_tool(tool, search_path = nil)
  search_path ||= @project_root || @start_path
  expanded_path = File.expand_path(search_path.to_s)

  include_patterns = include_patterns_for(tool)
  exclude_patterns = exclude_patterns_for(tool)

  all_files = include_patterns.flat_map do |pattern|
    Dir[File.join(expanded_path, pattern)]
  end.uniq

  all_files.reject do |file|
    relative = file.sub("#{expanded_path}/", "")
    path_excluded?(relative, exclude_patterns)
  end.sort
end

#formatterObject



113
114
115
# File 'lib/herb/configuration.rb', line 113

def formatter
  @config["formatter"] || {}
end

#formatter_enabled_for_path?(path) ⇒ Boolean

Returns:

  • (Boolean)


161
162
163
# File 'lib/herb/configuration.rb', line 161

def formatter_enabled_for_path?(path)
  enabled_for_path?(path, :formatter)
end

#formatter_exclude_patternsObject



139
140
141
# File 'lib/herb/configuration.rb', line 139

def formatter_exclude_patterns
  exclude_patterns_for(:formatter)
end

#formatter_include_patternsObject



135
136
137
# File 'lib/herb/configuration.rb', line 135

def formatter_include_patterns
  include_patterns_for(:formatter)
end

#frameworkObject

: () -> String



53
54
55
56
57
58
59
60
61
62
# File 'lib/herb/configuration.rb', line 53

def framework
  value = @config["framework"] || "ruby"

  unless VALID_FRAMEWORKS.include?(value)
    warn "[Herb] Unknown framework: #{value.inspect}. Valid values: #{VALID_FRAMEWORKS.join(", ")}. Defaulting to 'ruby'."
    return "ruby"
  end

  value
end

#include_patterns_for(tool) ⇒ Object



117
118
119
120
# File 'lib/herb/configuration.rb', line 117

def include_patterns_for(tool)
  tool_config = send(tool.to_s)
  file_include_patterns + (tool_config["include"] || [])
end

#linterObject



88
89
90
# File 'lib/herb/configuration.rb', line 88

def linter
  @config["linter"] || {}
end

#linter_enabled_for_path?(path) ⇒ Boolean

Returns:

  • (Boolean)


157
158
159
# File 'lib/herb/configuration.rb', line 157

def linter_enabled_for_path?(path)
  enabled_for_path?(path, :linter)
end

#linter_exclude_patternsObject



131
132
133
# File 'lib/herb/configuration.rb', line 131

def linter_exclude_patterns
  exclude_patterns_for(:linter)
end

#linter_include_patternsObject



127
128
129
# File 'lib/herb/configuration.rb', line 127

def linter_include_patterns
  include_patterns_for(:linter)
end

#path_excluded?(path, patterns) ⇒ Boolean

Returns:

  • (Boolean)


165
166
167
# File 'lib/herb/configuration.rb', line 165

def path_excluded?(path, patterns)
  patterns.any? { |pattern| File.fnmatch?(pattern, path, File::FNM_PATHNAME) }
end

#path_included?(path, patterns) ⇒ Boolean

Returns:

  • (Boolean)


169
170
171
# File 'lib/herb/configuration.rb', line 169

def path_included?(path, patterns)
  patterns.any? { |pattern| File.fnmatch?(pattern, path, File::FNM_PATHNAME) }
end

#template_engineObject

: () -> String



65
66
67
68
69
70
71
72
73
74
# File 'lib/herb/configuration.rb', line 65

def template_engine
  value = @config["template_engine"] || "erubi"

  unless VALID_TEMPLATE_ENGINES.include?(value)
    warn "[Herb] Unknown template_engine: #{value.inspect}. Valid values: #{VALID_TEMPLATE_ENGINES.join(", ")}. Defaulting to 'erubi'."
    return "erubi"
  end

  value
end

#versionObject



48
49
50
# File 'lib/herb/configuration.rb', line 48

def version
  @config["version"]
end