erb_lint 0.1.0 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/exe/erblint +1 -1
  3. data/lib/erb_lint/all.rb +15 -15
  4. data/lib/erb_lint/cli.rb +20 -23
  5. data/lib/erb_lint/corrector.rb +1 -1
  6. data/lib/erb_lint/linter.rb +4 -4
  7. data/lib/erb_lint/linter_config.rb +10 -5
  8. data/lib/erb_lint/linter_registry.rb +2 -2
  9. data/lib/erb_lint/linters/allowed_script_type.rb +9 -8
  10. data/lib/erb_lint/linters/closing_erb_tag_indent.rb +2 -2
  11. data/lib/erb_lint/linters/deprecated_classes.rb +8 -7
  12. data/lib/erb_lint/linters/erb_safety.rb +2 -2
  13. data/lib/erb_lint/linters/extra_newline.rb +1 -1
  14. data/lib/erb_lint/linters/final_newline.rb +2 -2
  15. data/lib/erb_lint/linters/hard_coded_string.rb +39 -36
  16. data/lib/erb_lint/linters/no_javascript_tag_helper.rb +11 -9
  17. data/lib/erb_lint/linters/partial_instance_variable.rb +1 -1
  18. data/lib/erb_lint/linters/require_input_autocomplete.rb +8 -10
  19. data/lib/erb_lint/linters/require_script_nonce.rb +10 -10
  20. data/lib/erb_lint/linters/right_trim.rb +1 -1
  21. data/lib/erb_lint/linters/rubocop.rb +12 -10
  22. data/lib/erb_lint/linters/rubocop_text.rb +1 -1
  23. data/lib/erb_lint/linters/self_closing_tag.rb +6 -7
  24. data/lib/erb_lint/linters/space_around_erb_tag.rb +8 -7
  25. data/lib/erb_lint/linters/space_in_html_tag.rb +7 -6
  26. data/lib/erb_lint/linters/space_indentation.rb +1 -1
  27. data/lib/erb_lint/linters/trailing_whitespace.rb +1 -1
  28. data/lib/erb_lint/offense.rb +1 -0
  29. data/lib/erb_lint/reporter.rb +4 -2
  30. data/lib/erb_lint/reporters/compact_reporter.rb +9 -2
  31. data/lib/erb_lint/reporters/multiline_reporter.rb +2 -1
  32. data/lib/erb_lint/runner.rb +1 -1
  33. data/lib/erb_lint/runner_config.rb +8 -7
  34. data/lib/erb_lint/runner_config_resolver.rb +5 -4
  35. data/lib/erb_lint/stats.rb +10 -6
  36. data/lib/erb_lint/utils/block_map.rb +3 -2
  37. data/lib/erb_lint/utils/offset_corrector.rb +2 -2
  38. data/lib/erb_lint/utils/ruby_to_erb.rb +6 -5
  39. data/lib/erb_lint/utils/severity_levels.rb +2 -2
  40. data/lib/erb_lint/version.rb +1 -1
  41. data/lib/erb_lint.rb +1 -1
  42. metadata +17 -17
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'better_html'
4
- require 'better_html/tree/tag'
3
+ require "better_html"
4
+ require "better_html/tree/tag"
5
5
 
6
6
  module ERBLint
7
7
  module Linters
@@ -13,7 +13,6 @@ module ERBLint
13
13
  "date",
14
14
  "datetime-local",
15
15
  "email",
16
- "hidden",
17
16
  "month",
18
17
  "number",
19
18
  "password",
@@ -33,7 +32,6 @@ module ERBLint
33
32
  :text_field_tag,
34
33
  :utf8_enforcer_tag,
35
34
  :month_field_tag,
36
- :hidden_field_tag,
37
35
  :number_field_tag,
38
36
  :password_field_tag,
39
37
  :search_field_tag,
@@ -56,8 +54,8 @@ module ERBLint
56
54
  parser.nodes_with_type(:tag).each do |tag_node|
57
55
  tag = BetterHtml::Tree::Tag.from_node(tag_node)
58
56
 
59
- autocomplete_attribute = tag.attributes['autocomplete']
60
- type_attribute = tag.attributes['type']
57
+ autocomplete_attribute = tag.attributes["autocomplete"]
58
+ type_attribute = tag.attributes["type"]
61
59
 
62
60
  next if !html_input_tag?(tag) || autocomplete_present?(autocomplete_attribute)
63
61
  next unless html_type_requires_autocomplete_attribute?(type_attribute)
@@ -65,7 +63,7 @@ module ERBLint
65
63
  add_offense(
66
64
  tag_node.to_a[1].loc,
67
65
  "Input tag is missing an autocomplete attribute. If no "\
68
- "autocomplete behaviour is desired, use the value `off` or `nope`.",
66
+ "autocomplete behaviour is desired, use the value `off` or `nope`.",
69
67
  [autocomplete_attribute]
70
68
  )
71
69
  end
@@ -76,7 +74,7 @@ module ERBLint
76
74
  end
77
75
 
78
76
  def html_input_tag?(tag)
79
- !tag.closing? && tag.name == 'input'
77
+ !tag.closing? && tag.name == "input"
80
78
  end
81
79
 
82
80
  def html_type_requires_autocomplete_attribute?(type_attribute)
@@ -99,7 +97,7 @@ module ERBLint
99
97
  add_offense(
100
98
  erb_node.loc,
101
99
  "Input field helper is missing an autocomplete attribute. If no "\
102
- "autocomplete behaviour is desired, use the value `off` or `nope`.",
100
+ "autocomplete behaviour is desired, use the value `off` or `nope`.",
103
101
  [erb_node, send_node]
104
102
  )
105
103
  end
@@ -110,7 +108,7 @@ module ERBLint
110
108
  end
111
109
 
112
110
  def code_comment?(indicator_node)
113
- indicator_node&.loc&.source == '#'
111
+ indicator_node&.loc&.source == "#"
114
112
  end
115
113
 
116
114
  def extract_ruby_node(source)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'better_html'
4
- require 'better_html/tree/tag'
3
+ require "better_html"
4
+ require "better_html/tree/tag"
5
5
 
6
6
  module ERBLint
7
7
  module Linters
@@ -22,7 +22,7 @@ module ERBLint
22
22
  def find_html_script_tags(parser)
23
23
  parser.nodes_with_type(:tag).each do |tag_node|
24
24
  tag = BetterHtml::Tree::Tag.from_node(tag_node)
25
- nonce_attribute = tag.attributes['nonce']
25
+ nonce_attribute = tag.attributes["nonce"]
26
26
 
27
27
  next if !html_javascript_tag?(tag) || nonce_present?(nonce_attribute)
28
28
 
@@ -40,16 +40,16 @@ module ERBLint
40
40
 
41
41
  def html_javascript_tag?(tag)
42
42
  !tag.closing? &&
43
- (tag.name == 'script' && !html_javascript_type_attribute?(tag))
43
+ (tag.name == "script" && !html_javascript_type_attribute?(tag))
44
44
  end
45
45
 
46
46
  def html_javascript_type_attribute?(tag)
47
- type_attribute = tag.attributes['type']
47
+ type_attribute = tag.attributes["type"]
48
48
 
49
49
  type_attribute &&
50
50
  type_attribute.value_node.present? &&
51
- type_attribute.value_node.to_a[1] != 'text/javascript' &&
52
- type_attribute.value_node.to_a[1] != 'application/javascript'
51
+ type_attribute.value_node.to_a[1] != "text/javascript" &&
52
+ type_attribute.value_node.to_a[1] != "application/javascript"
53
53
  end
54
54
 
55
55
  def find_rails_helper_script_tags(parser)
@@ -74,12 +74,12 @@ module ERBLint
74
74
 
75
75
  def tag_helper?(send_node)
76
76
  send_node&.method_name?(:javascript_tag) ||
77
- send_node&.method_name?(:javascript_include_tag) ||
78
- send_node&.method_name?(:javascript_pack_tag)
77
+ send_node&.method_name?(:javascript_include_tag) ||
78
+ send_node&.method_name?(:javascript_pack_tag)
79
79
  end
80
80
 
81
81
  def code_comment?(indicator_node)
82
- indicator_node&.loc&.source == '#'
82
+ indicator_node&.loc&.source == "#"
83
83
  end
84
84
 
85
85
  def extract_ruby_node(source)
@@ -8,7 +8,7 @@ module ERBLint
8
8
  include LinterRegistry
9
9
 
10
10
  class ConfigSchema < LinterConfig
11
- property :enforced_style, accepts: ['-', '='], default: '-'
11
+ property :enforced_style, accepts: ["-", "="], default: "-"
12
12
  end
13
13
  self.config_schema = ConfigSchema
14
14
 
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'better_html'
4
- require 'tempfile'
5
- require 'erb_lint/utils/offset_corrector'
3
+ require "better_html"
4
+ require "tempfile"
5
+ require "erb_lint/utils/offset_corrector"
6
6
 
7
7
  module ERBLint
8
8
  module Linters
@@ -25,7 +25,7 @@ module ERBLint
25
25
  super
26
26
  @only_cops = @config.only
27
27
  custom_config = config_from_hash(@config.rubocop_config)
28
- @rubocop_config = ::RuboCop::ConfigLoader.merge_with_default(custom_config, '')
28
+ @rubocop_config = ::RuboCop::ConfigLoader.merge_with_default(custom_config, "")
29
29
  end
30
30
 
31
31
  def run(processed_source)
@@ -37,6 +37,7 @@ module ERBLint
37
37
  if ::RuboCop::Version::STRING.to_f >= 0.87
38
38
  def autocorrect(_processed_source, offense)
39
39
  return unless offense.context
40
+
40
41
  rubocop_correction = offense.context[:rubocop_correction]
41
42
  return unless rubocop_correction
42
43
 
@@ -68,13 +69,13 @@ module ERBLint
68
69
 
69
70
  def inspect_content(processed_source, erb_node)
70
71
  indicator, _, code_node, = *erb_node
71
- return if indicator&.children&.first == '#'
72
+ return if indicator&.children&.first == "#"
72
73
 
73
74
  original_source = code_node.loc.source
74
- trimmed_source = original_source.sub(BLOCK_EXPR, '').sub(SUFFIX_EXPR, '')
75
+ trimmed_source = original_source.sub(BLOCK_EXPR, "").sub(SUFFIX_EXPR, "")
75
76
  alignment_column = code_node.loc.column
76
77
  offset = code_node.loc.begin_pos - alignment_column
77
- aligned_source = "#{' ' * alignment_column}#{trimmed_source}"
78
+ aligned_source = "#{" " * alignment_column}#{trimmed_source}"
78
79
 
79
80
  source = rubocop_processed_source(aligned_source, processed_source.filename)
80
81
  return unless source.valid_syntax?
@@ -150,16 +151,17 @@ module ERBLint
150
151
  @rubocop_config,
151
152
  extra_details: true,
152
153
  display_cop_names: true,
154
+ autocorrect: true,
153
155
  auto_correct: true,
154
156
  stdin: "",
155
157
  )
156
158
  end
157
159
 
158
160
  def config_from_hash(hash)
159
- inherit_from = hash&.delete('inherit_from')
161
+ inherit_from = hash&.delete("inherit_from")
160
162
  resolve_inheritance(hash, inherit_from)
161
163
 
162
- tempfile_from('.erblint-rubocop', hash.to_yaml) do |tempfile|
164
+ tempfile_from(".erblint-rubocop", hash.to_yaml) do |tempfile|
163
165
  ::RuboCop::ConfigLoader.load_file(tempfile.path)
164
166
  end
165
167
  end
@@ -174,7 +176,7 @@ module ERBLint
174
176
  end
175
177
 
176
178
  def base_configs(inherit_from)
177
- regex = URI::DEFAULT_PARSER.make_regexp(%w(http https))
179
+ regex = URI::DEFAULT_PARSER.make_regexp(["http", "https"])
178
180
  configs = Array(inherit_from).compact.map do |base_name|
179
181
  if base_name =~ /\A#{regex}\z/
180
182
  ::RuboCop::ConfigLoader.load_file(::RuboCop::RemoteConfig.new(base_name, Dir.pwd))
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'rubocop'
3
+ require_relative "rubocop"
4
4
 
5
5
  module ERBLint
6
6
  module Linters
@@ -11,10 +11,8 @@ module ERBLint
11
11
  end
12
12
  self.config_schema = ConfigSchema
13
13
 
14
- SELF_CLOSING_TAGS = %w(
15
- area base br col command embed hr input keygen
16
- link menuitem meta param source track wbr img
17
- )
14
+ SELF_CLOSING_TAGS = ["area", "base", "br", "col", "command", "embed", "hr", "input", "keygen", "link",
15
+ "menuitem", "meta", "param", "source", "track", "wbr", "img",]
18
16
 
19
17
  def run(processed_source)
20
18
  processed_source.ast.descendants(:tag).each do |tag_node|
@@ -26,7 +24,7 @@ module ERBLint
26
24
  add_offense(
27
25
  start_solidus.loc,
28
26
  "Tag `#{tag.name}` is a void element, it must not start with `</`.",
29
- ''
27
+ ""
30
28
  )
31
29
  end
32
30
 
@@ -34,16 +32,17 @@ module ERBLint
34
32
  add_offense(
35
33
  tag_node.loc.end.offset(-1),
36
34
  "Tag `#{tag.name}` is self-closing, it must end with `/>`.",
37
- '/'
35
+ "/"
38
36
  )
39
37
  end
40
38
 
41
39
  next unless @config.enforced_style == :never && tag.self_closing?
40
+
42
41
  end_solidus = tag_node.children.last
43
42
  add_offense(
44
43
  end_solidus.loc,
45
44
  "Tag `#{tag.name}` is a void element, it must end with `>` and not `/>`.",
46
- ''
45
+ ""
47
46
  )
48
47
  end
49
48
  end
@@ -15,7 +15,8 @@ module ERBLint
15
15
  processed_source.ast.descendants(:erb).each do |erb_node|
16
16
  indicator_node, ltrim, code_node, rtrim = *erb_node
17
17
  indicator = indicator_node&.loc&.source
18
- next if indicator == '#' || indicator == '%'
18
+ next if indicator == "#" || indicator == "%"
19
+
19
20
  code = code_node.children.first
20
21
 
21
22
  start_spaces = code.match(START_SPACES)&.captures&.first || ""
@@ -23,15 +24,15 @@ module ERBLint
23
24
  add_offense(
24
25
  code_node.loc.resize(start_spaces.size),
25
26
  "Use 1 space after `<%#{indicator}#{ltrim&.loc&.source}` "\
26
- "instead of #{start_spaces.size} space#{'s' if start_spaces.size > 1}.",
27
- ' '
27
+ "instead of #{start_spaces.size} space#{"s" if start_spaces.size > 1}.",
28
+ " "
28
29
  )
29
30
  elsif start_spaces.count("\n") > 1
30
31
  lines = start_spaces.split("\n", -1)
31
32
  add_offense(
32
33
  code_node.loc.resize(start_spaces.size),
33
34
  "Use 1 newline after `<%#{indicator&.loc&.source}#{ltrim&.loc&.source}` "\
34
- "instead of #{start_spaces.count("\n")}.",
35
+ "instead of #{start_spaces.count("\n")}.",
35
36
  "#{lines.first}\n#{lines.last}"
36
37
  )
37
38
  end
@@ -41,15 +42,15 @@ module ERBLint
41
42
  add_offense(
42
43
  code_node.loc.end.adjust(begin_pos: -end_spaces.size),
43
44
  "Use 1 space before `#{rtrim&.loc&.source}%>` "\
44
- "instead of #{end_spaces.size} space#{'s' if start_spaces.size > 1}.",
45
- ' '
45
+ "instead of #{end_spaces.size} space#{"s" if start_spaces.size > 1}.",
46
+ " "
46
47
  )
47
48
  elsif end_spaces.count("\n") > 1
48
49
  lines = end_spaces.split("\n", -1)
49
50
  add_offense(
50
51
  code_node.loc.end.adjust(begin_pos: -end_spaces.size),
51
52
  "Use 1 newline before `#{rtrim&.loc&.source}%>` "\
52
- "instead of #{end_spaces.count("\n")}.",
53
+ "instead of #{end_spaces.count("\n")}.",
53
54
  "#{lines.first}\n#{lines.last}"
54
55
  )
55
56
  end
@@ -50,7 +50,7 @@ module ERBLint
50
50
  add_offense(
51
51
  processed_source.to_source_range(range),
52
52
  "Extra space detected where there should be no space.",
53
- ''
53
+ ""
54
54
  )
55
55
  end
56
56
 
@@ -60,24 +60,24 @@ module ERBLint
60
60
 
61
61
  def single_space(processed_source, range, accept_newline: false)
62
62
  chars = processed_source.file_content[range]
63
- return if chars == ' '
63
+ return if chars == " "
64
64
 
65
65
  newlines = chars.include?("\n")
66
- expected = newlines && accept_newline ? "\n#{chars.split("\n", -1).last}" : ' '
66
+ expected = newlines && accept_newline ? "\n#{chars.split("\n", -1).last}" : " "
67
67
  non_space = chars.match(/([^[[:space:]]])/m)
68
68
 
69
69
  if non_space && !non_space.captures.empty?
70
70
  add_offense(
71
71
  processed_source.to_source_range(range),
72
72
  "Non-whitespace character(s) detected: "\
73
- "#{non_space.captures.map(&:inspect).join(', ')}.",
73
+ "#{non_space.captures.map(&:inspect).join(", ")}.",
74
74
  expected
75
75
  )
76
76
  elsif newlines && accept_newline
77
77
  if expected != chars
78
78
  add_offense(
79
79
  processed_source.to_source_range(range),
80
- "#{chars.empty? ? 'No' : 'Extra'} space detected where there should be "\
80
+ "#{chars.empty? ? "No" : "Extra"} space detected where there should be "\
81
81
  "a single space or a single line break.",
82
82
  expected
83
83
  )
@@ -85,7 +85,7 @@ module ERBLint
85
85
  else
86
86
  add_offense(
87
87
  processed_source.to_source_range(range),
88
- "#{chars.empty? ? 'No' : 'Extra'} space detected where there should be a single space.",
88
+ "#{chars.empty? ? "No" : "Extra"} space detected where there should be a single space.",
89
89
  expected
90
90
  )
91
91
  end
@@ -98,6 +98,7 @@ module ERBLint
98
98
  no_space(processed_source, equal.loc.end_pos...value.loc.begin_pos) if equal && value
99
99
 
100
100
  next if index >= attributes.children.size - 1
101
+
101
102
  next_attribute = attributes.children[index + 1]
102
103
 
103
104
  single_space_or_newline(
@@ -23,7 +23,7 @@ module ERBLint
23
23
  add_offense(
24
24
  processed_source.to_source_range(document_pos...(document_pos + spaces.length)),
25
25
  "Indent with spaces instead of tabs.",
26
- spaces.gsub("\t", ' ' * @config.tab_width)
26
+ spaces.gsub("\t", " " * @config.tab_width)
27
27
  )
28
28
  end
29
29
 
@@ -25,7 +25,7 @@ module ERBLint
25
25
 
26
26
  def autocorrect(_processed_source, offense)
27
27
  lambda do |corrector|
28
- corrector.replace(offense.source_range, '')
28
+ corrector.replace(offense.source_range, "")
29
29
  end
30
30
  end
31
31
  end
@@ -9,6 +9,7 @@ module ERBLint
9
9
  unless source_range.is_a?(Parser::Source::Range)
10
10
  raise ArgumentError, "expected Parser::Source::Range for arg 2"
11
11
  end
12
+
12
13
  @linter = linter
13
14
  @source_range = source_range
14
15
  @message = message
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require 'active_support/core_ext/class'
3
- require 'active_support/core_ext/module/delegation'
2
+
3
+ require "active_support/core_ext/class"
4
+ require "active_support/core_ext/module/delegation"
4
5
 
5
6
  module ERBLint
6
7
  class Reporter
@@ -34,6 +35,7 @@ module ERBLint
34
35
  private
35
36
 
36
37
  attr_reader :stats, :autocorrect
38
+
37
39
  delegate :processed_files, to: :stats
38
40
  end
39
41
  end
@@ -4,8 +4,7 @@ module ERBLint
4
4
  module Reporters
5
5
  class CompactReporter < Reporter
6
6
  def preview
7
- puts "Linting #{stats.files} files with "\
8
- "#{stats.linters} #{'autocorrectable ' if autocorrect}linters..."
7
+ puts "#{linting} #{stats.files} files with #{linters}..."
9
8
  end
10
9
 
11
10
  def show
@@ -21,6 +20,14 @@ module ERBLint
21
20
 
22
21
  private
23
22
 
23
+ def linting
24
+ "Linting" + (autocorrect ? " and autocorrecting" : "")
25
+ end
26
+
27
+ def linters
28
+ "#{stats.linters} linters" + (autocorrect ? " (#{stats.autocorrectable_linters} autocorrectable)" : "")
29
+ end
30
+
24
31
  def format_offense(filename, offense)
25
32
  [
26
33
  "#{filename}:",
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative "compact_reporter"
3
4
 
4
5
  module ERBLint
@@ -9,7 +10,7 @@ module ERBLint
9
10
  def format_offense(filename, offense)
10
11
  <<~EOF
11
12
 
12
- #{offense.message}#{Rainbow(' (not autocorrected)').red if autocorrect}
13
+ #{offense.message}#{Rainbow(" (not autocorrected)").red if autocorrect}
13
14
  In file: #{filename}:#{offense.line_number}
14
15
  EOF
15
16
  end
@@ -8,7 +8,7 @@ module ERBLint
8
8
  def initialize(file_loader, config)
9
9
  @file_loader = file_loader
10
10
  @config = config || RunnerConfig.default
11
- raise ArgumentError, 'expect `config` to be a RunnerConfig instance' unless @config.is_a?(RunnerConfig)
11
+ raise ArgumentError, "expect `config` to be a RunnerConfig instance" unless @config.is_a?(RunnerConfig)
12
12
 
13
13
  linter_classes = LinterRegistry.linters.select { |klass| @config.for_linter(klass).enabled? }
14
14
  @linters = linter_classes.map do |linter_class|
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'erb_lint/runner_config_resolver'
3
+ require "erb_lint/runner_config_resolver"
4
4
 
5
5
  module ERBLint
6
6
  class RunnerConfig
@@ -9,7 +9,7 @@ module ERBLint
9
9
  def initialize(config = nil, file_loader = nil)
10
10
  @config = (config || {}).dup.deep_stringify_keys
11
11
 
12
- resolver.resolve_inheritance_from_gems(@config, @config.delete('inherit_gem'))
12
+ resolver.resolve_inheritance_from_gems(@config, @config.delete("inherit_gem"))
13
13
  resolver.resolve_inheritance(@config, file_loader) if file_loader
14
14
  @config.delete("inherit_from")
15
15
  end
@@ -24,15 +24,16 @@ module ERBLint
24
24
  elsif klass.is_a?(Class) && klass <= ERBLint::Linter
25
25
  klass.simple_name
26
26
  else
27
- raise ArgumentError, 'expected String or linter class'
27
+ raise ArgumentError, "expected String or linter class"
28
28
  end
29
29
  linter_klass = LinterRegistry.find_by_name(klass_name)
30
30
  raise Error, "#{klass_name}: linter not found (is it loaded?)" unless linter_klass
31
+
31
32
  linter_klass.config_schema.new(config_hash_for_linter(klass_name))
32
33
  end
33
34
 
34
35
  def global_exclude
35
- @config['exclude'] || []
36
+ @config["exclude"] || []
36
37
  end
37
38
 
38
39
  def merge(other_config)
@@ -75,13 +76,13 @@ module ERBLint
75
76
  private
76
77
 
77
78
  def linters_config
78
- @config['linters'] || {}
79
+ @config["linters"] || {}
79
80
  end
80
81
 
81
82
  def config_hash_for_linter(klass_name)
82
83
  config_hash = linters_config[klass_name] || {}
83
- config_hash['exclude'] ||= []
84
- config_hash['exclude'].concat(global_exclude) if config_hash['exclude'].is_a?(Array)
84
+ config_hash["exclude"] ||= []
85
+ config_hash["exclude"].concat(global_exclude) if config_hash["exclude"].is_a?(Array)
85
86
  config_hash
86
87
  end
87
88
 
@@ -24,10 +24,11 @@
24
24
  module ERBLint
25
25
  class RunnerConfigResolver
26
26
  def resolve_inheritance(hash, file_loader)
27
- inherited_files = Array(hash['inherit_from'])
27
+ inherited_files = Array(hash["inherit_from"])
28
28
  base_configs(file_loader, inherited_files).reverse_each do |base_config|
29
29
  base_config.each do |k, v|
30
30
  next unless v.is_a?(Hash)
31
+
31
32
  v = v.deep_merge(hash[k]) if hash.key?(k)
32
33
  hash[k] = v
33
34
  end
@@ -36,12 +37,12 @@ module ERBLint
36
37
 
37
38
  def resolve_inheritance_from_gems(hash, gems)
38
39
  (gems || {}).each_pair do |gem_name, config_path|
39
- raise(ArgumentError, "can't inherit configuration from the erb-lint gem") if gem_name == 'erb-lint'
40
+ raise(ArgumentError, "can't inherit configuration from the erb-lint gem") if gem_name == "erb-lint"
40
41
 
41
- hash['inherit_from'] = Array(hash['inherit_from'])
42
+ hash["inherit_from"] = Array(hash["inherit_from"])
42
43
  Array(config_path).reverse_each do |path|
43
44
  # Put gem configuration first so local configuration overrides it.
44
- hash['inherit_from'].unshift(gem_config_path(gem_name, path))
45
+ hash["inherit_from"].unshift(gem_config_path(gem_name, path))
45
46
  end
46
47
  end
47
48
  end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module ERBLint
3
4
  class Stats
4
5
  attr_accessor :ignored,
5
- :found,
6
- :corrected,
7
- :exceptions,
8
- :linters,
9
- :files,
10
- :processed_files
6
+ :found,
7
+ :corrected,
8
+ :exceptions,
9
+ :linters,
10
+ :autocorrectable_linters,
11
+ :files,
12
+ :processed_files
11
13
 
12
14
  def initialize(
13
15
  ignored: 0,
@@ -15,6 +17,7 @@ module ERBLint
15
17
  corrected: 0,
16
18
  exceptions: 0,
17
19
  linters: 0,
20
+ autocorrectable_linters: 0,
18
21
  files: 0,
19
22
  processed_files: {}
20
23
  )
@@ -23,6 +26,7 @@ module ERBLint
23
26
  @corrected = corrected
24
27
  @exceptions = exceptions
25
28
  @linters = linters
29
+ @autocorrectable_linters = autocorrectable_linters
26
30
  @files = files
27
31
  @processed_files = processed_files
28
32
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'better_html/ast/node'
4
- require 'better_html/test_helper/ruby_node'
3
+ require "better_html/ast/node"
4
+ require "better_html/test_helper/ruby_node"
5
5
 
6
6
  module ERBLint
7
7
  module Utils
@@ -194,6 +194,7 @@ module ERBLint
194
194
 
195
195
  def find_entry(range)
196
196
  return unless range
197
+
197
198
  @entries.find do |entry|
198
199
  entry.contains_ruby_range?(Range.new(range.begin_pos, range.end_pos))
199
200
  end
@@ -63,8 +63,8 @@ module ERBLint
63
63
  node_or_range
64
64
  else
65
65
  raise TypeError,
66
- 'Expected a Parser::Source::Range, Comment or ' \
67
- "Rubocop::AST::Node, got #{node_or_range.class}"
66
+ "Expected a Parser::Source::Range, Comment or " \
67
+ "Rubocop::AST::Node, got #{node_or_range.class}"
68
68
  end
69
69
  end
70
70
  end
@@ -9,14 +9,15 @@ module ERBLint
9
9
  def html_options_to_tag_attributes(hash_node)
10
10
  hash_node.children.map do |pair_node|
11
11
  key_node, value_node = *pair_node
12
- key = ruby_to_erb(key_node, '=') { |s| s.tr('_', '-') }
13
- value = ruby_to_erb(value_node, '=') { |s| escape_quote(s) }
14
- [key, "\"#{value}\""].join('=')
15
- end.join(' ')
12
+ key = ruby_to_erb(key_node, "=") { |s| s.tr("_", "-") }
13
+ value = ruby_to_erb(value_node, "=") { |s| escape_quote(s) }
14
+ [key, "\"#{value}\""].join("=")
15
+ end.join(" ")
16
16
  end
17
17
 
18
18
  def ruby_to_erb(node, indicator = nil, &block)
19
19
  return node if node.nil? || node.is_a?(String)
20
+
20
21
  case node.type
21
22
  when :str, :sym
22
23
  s = node.children.first.to_s
@@ -43,7 +44,7 @@ module ERBLint
43
44
  end
44
45
 
45
46
  def escape_quote(str)
46
- str.gsub('"', '&quot;')
47
+ str.gsub('"', "&quot;")
47
48
  end
48
49
  end
49
50
  end
@@ -3,10 +3,10 @@
3
3
  module ERBLint
4
4
  module Utils
5
5
  module SeverityLevels
6
- SEVERITY_NAMES = %i[info refactor convention warning error fatal].freeze
6
+ SEVERITY_NAMES = [:info, :refactor, :convention, :warning, :error, :fatal].freeze
7
7
 
8
8
  SEVERITY_CODE_TABLE = { I: :info, R: :refactor, C: :convention,
9
- W: :warning, E: :error, F: :fatal }.freeze
9
+ W: :warning, E: :error, F: :fatal, }.freeze
10
10
 
11
11
  def severity_level_for_name(name)
12
12
  SEVERITY_NAMES.index(name || :error) + 1