class SCSSLint::Config

Loads and manages application configuration.

Constants

DEFAULT_FILE
FILE_NAME

Attributes

options[R]
warnings[R]

Public Class Methods

default() click to toggle source
# File lib/scss_lint/config.rb, line 12
def default
  load(DEFAULT_FILE, merge_with_default: false)
end
linter_name(linter) click to toggle source
# File lib/scss_lint/config.rb, line 28
def linter_name(linter)
  linter = linter.is_a?(Class) ? linter : linter.class
  linter.name.split('::')[2..-1].join('::')
end
load(file, options = {}) click to toggle source

Loads a configuration from a file, merging it with the default configuration.

# File lib/scss_lint/config.rb, line 18
def load(file, options = {})
  config_options = load_options_hash_from_file(file)

  if options.fetch(:merge_with_default, true)
    config_options = smart_merge(default_options_hash, config_options)
  end

  Config.new(config_options)
end
new(options) click to toggle source
# File lib/scss_lint/config.rb, line 166
def initialize(options)
  @options = options
  @warnings = []

  validate_linters
end

Private Class Methods

apply_options_to_matching_linters(class_name_glob, current_options, linter_options) click to toggle source
# File lib/scss_lint/config.rb, line 91
def apply_options_to_matching_linters(class_name_glob, current_options, linter_options)
  linter_names_matching_glob(class_name_glob).each do |linter_name|
    old_options = current_options['linters'].fetch(linter_name, {})
    current_options['linters'][linter_name] = smart_merge(old_options, linter_options)
  end
end
convert_single_options_to_arrays(options) click to toggle source

Convert any config options that accept a single value or an array to an array form so that merging works.

# File lib/scss_lint/config.rb, line 65
def convert_single_options_to_arrays(options)
  options = options.dup

  if options['exclude']
    # Ensure exclude is an array, since we allow user to specify a single
    # string.
    options['exclude'] = [options['exclude']].flatten
  end

  options
end
default_options_hash() click to toggle source
# File lib/scss_lint/config.rb, line 35
def default_options_hash
  @default_options_hash ||= load_options_hash_from_file(DEFAULT_FILE)
end
ensure_exclude_paths_are_absolute(options, original_file) click to toggle source

Ensure all excludes are absolute paths

# File lib/scss_lint/config.rb, line 119
def ensure_exclude_paths_are_absolute(options, original_file)
  options = options.dup

  if options['exclude']
    excludes = [options['exclude']].flatten

    options['exclude'] = excludes.map do |exclusion_glob|
      if exclusion_glob.start_with?('/')
        exclusion_glob
      else
        # Expand the path assuming it is relative to the config file itself
        File.expand_path(exclusion_glob, File.expand_path(File.dirname(original_file)))
      end
    end
  end

  options
end
ensure_linter_exclude_paths_are_absolute(options, original_file) click to toggle source
# File lib/scss_lint/config.rb, line 105
def ensure_linter_exclude_paths_are_absolute(options, original_file)
  options = options.dup

  options['linters'] ||= {}

  options['linters'].keys.each do |linter_name|
    options['linters'][linter_name] =
      ensure_exclude_paths_are_absolute(options['linters'][linter_name], original_file)
  end

  options
end
linter_names_matching_glob(class_name_glob) click to toggle source
# File lib/scss_lint/config.rb, line 98
def linter_names_matching_glob(class_name_glob)
  class_name_regex = /#{class_name_glob.gsub('*', '[^:]+')}/

  LinterRegistry.linters.map { |linter_class| linter_name(linter_class) }
                .select { |linter_name| linter_name.match(class_name_regex) }
end
load_file_contents(file) click to toggle source

For easy stubbing in tests

# File lib/scss_lint/config.rb, line 149
def load_file_contents(file)
  File.open(file, 'r').read
end
load_options_hash_from_file(file) click to toggle source

Recursively load config files, fetching files specified by ‘include` directives and merging the file’s config with the files specified.

# File lib/scss_lint/config.rb, line 41
def load_options_hash_from_file(file)
  file_contents = load_file_contents(file)

  begin
    options =
      if yaml = YAML.load(file_contents)
        yaml.to_hash
      else
        {}
      end
  rescue => ex
    raise SCSSLint::Exceptions::InvalidConfiguration,
          "Invalid configuration: #{ex.message}"
  end

  options = convert_single_options_to_arrays(options)
  options = merge_wildcard_linter_options(options)
  options = ensure_exclude_paths_are_absolute(options, file)
  options = ensure_linter_exclude_paths_are_absolute(options, file)
  options
end
merge_wildcard_linter_options(options) click to toggle source

Merge options from wildcard linters into individual linter configs

# File lib/scss_lint/config.rb, line 78
def merge_wildcard_linter_options(options)
  options = options.dup

  options.fetch('linters', {}).keys.each do |class_name|
    next unless class_name.include?('*')

    wildcard_options = options['linters'].delete(class_name)
    apply_options_to_matching_linters(class_name, options, wildcard_options)
  end

  options
end
path_relative_to_config(relative_include_path, base_config_path) click to toggle source
# File lib/scss_lint/config.rb, line 138
def path_relative_to_config(relative_include_path, base_config_path)
  if relative_include_path.start_with?('/')
    relative_include_path
  else
    path = File.join(File.dirname(base_config_path), relative_include_path)
    # Remove double backslashes appearing in Windows paths.
    path.gsub(%r{^//}, File::SEPARATOR)
  end
end
smart_merge(parent, child) click to toggle source

Merge two hashes, concatenating lists and further merging nested hashes.

# File lib/scss_lint/config.rb, line 154
def smart_merge(parent, child)
  parent.merge(child) do |_key, old, new|
    case old
    when Hash
      smart_merge(old, new)
    else
      new
    end
  end
end

Public Instance Methods

disable_all_linters() click to toggle source
# File lib/scss_lint/config.rb, line 191
def disable_all_linters
  @options['linters'].values.each do |linter_config|
    linter_config['enabled'] = false
  end
end
disable_linter(linter) click to toggle source
# File lib/scss_lint/config.rb, line 187
def disable_linter(linter)
  linter_options(linter)['enabled'] = false
end
enable_linter(linter) click to toggle source
# File lib/scss_lint/config.rb, line 183
def enable_linter(linter)
  linter_options(linter)['enabled'] = true
end
enabled_linters() click to toggle source
# File lib/scss_lint/config.rb, line 173
def enabled_linters
  LinterRegistry.extract_linters_from(@options['linters'].keys).select do |linter|
    linter_options(linter)['enabled']
  end
end
exclude_file(file_path) click to toggle source
# File lib/scss_lint/config.rb, line 221
def exclude_file(file_path)
  abs_path = File.expand_path(file_path)

  @options['exclude'] ||= []
  @options['exclude'] << abs_path
end
exclude_patterns() click to toggle source
# File lib/scss_lint/config.rb, line 209
def exclude_patterns
  @options.fetch('exclude', [])
end
excluded_file?(file_path) click to toggle source
# File lib/scss_lint/config.rb, line 201
def excluded_file?(file_path)
  abs_path = File.expand_path(file_path)

  @options.fetch('exclude', []).any? do |exclusion_glob|
    File.fnmatch(exclusion_glob, abs_path)
  end
end
excluded_file_for_linter?(file_path, linter) click to toggle source
# File lib/scss_lint/config.rb, line 213
def excluded_file_for_linter?(file_path, linter)
  abs_path = File.expand_path(file_path)

  linter_options(linter).fetch('exclude', []).any? do |exclusion_glob|
    File.fnmatch(exclusion_glob, abs_path)
  end
end
linter_enabled?(linter) click to toggle source
# File lib/scss_lint/config.rb, line 179
def linter_enabled?(linter)
  linter_options(linter)['enabled']
end
linter_options(linter) click to toggle source
# File lib/scss_lint/config.rb, line 197
def linter_options(linter)
  @options['linters'][self.class.linter_name(linter)]
end
scss_files() click to toggle source

@return Array

# File lib/scss_lint/config.rb, line 229
def scss_files
  if path = @options['scss_files']
    Dir[path]
  else
    []
  end
end

Private Instance Methods

validate_linters() click to toggle source
# File lib/scss_lint/config.rb, line 239
def validate_linters
  return unless linters = @options['linters']

  linters.keys.each do |name|
    begin
      Linter.const_get(name)
    rescue NameError
      @warnings << "Linter #{name} does not exist; ignoring"
    end
  end
end