erb_lint 0.0.37 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/exe/erblint +1 -1
  3. data/lib/erb_lint/all.rb +26 -0
  4. data/lib/erb_lint/cli.rb +75 -29
  5. data/lib/erb_lint/corrector.rb +1 -1
  6. data/lib/erb_lint/linter.rb +5 -5
  7. data/lib/erb_lint/linter_config.rb +5 -3
  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 -16
  16. data/lib/erb_lint/linters/no_javascript_tag_helper.rb +11 -9
  17. data/lib/erb_lint/linters/partial_instance_variable.rb +23 -0
  18. data/lib/erb_lint/linters/require_input_autocomplete.rb +121 -0
  19. data/lib/erb_lint/linters/require_script_nonce.rb +92 -0
  20. data/lib/erb_lint/linters/right_trim.rb +1 -1
  21. data/lib/erb_lint/linters/rubocop.rb +13 -11
  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 +8 -4
  29. data/lib/erb_lint/reporter.rb +4 -2
  30. data/lib/erb_lint/reporters/compact_reporter.rb +17 -4
  31. data/lib/erb_lint/reporters/json_reporter.rb +72 -0
  32. data/lib/erb_lint/reporters/multiline_reporter.rb +2 -1
  33. data/lib/erb_lint/runner.rb +3 -2
  34. data/lib/erb_lint/runner_config.rb +9 -7
  35. data/lib/erb_lint/runner_config_resolver.rb +5 -4
  36. data/lib/erb_lint/stats.rb +13 -6
  37. data/lib/erb_lint/utils/block_map.rb +3 -2
  38. data/lib/erb_lint/utils/offset_corrector.rb +2 -2
  39. data/lib/erb_lint/utils/ruby_to_erb.rb +6 -5
  40. data/lib/erb_lint/utils/severity_levels.rb +16 -0
  41. data/lib/erb_lint/version.rb +1 -1
  42. data/lib/erb_lint.rb +1 -24
  43. metadata +23 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 20ce12719e17ebfc24ca522965e85985fe665c0cbec1d9751320b1a779ec8c9c
4
- data.tar.gz: 536222d32134c71f72083c5083f575e8422024f8f5e26e0daf9b9eadd181d3e9
3
+ metadata.gz: 97583caf4e48c7c5b8a6d2e1bf4c17add7bac9693ef6032be0fb22f9d46f4fa4
4
+ data.tar.gz: 3d1dba73d37680a0339936a12a6c2a048b473a7c9077518f54edd1aa037c4ce5
5
5
  SHA512:
6
- metadata.gz: 44f138dfdfff77b04d03f293f3b48f90744bbf3fcbcfeadc1cf3b5f0d47cae5c933b18b0e7273d64cdf549170e2a2aa33c5110cbc0aa62c84855e6e29a5f67ae
7
- data.tar.gz: 1fe70e0ddb97e0930b2645b0942d5ed08e74c5b40a41af1b6b9c7b9219b4be136495a5f3a0991363e8877aaef7bab5da2eb1f4162dc85f64b2f17d6ae2ca1184
6
+ metadata.gz: a043d8859ef059100dd809112f8768908f2ec8df59a52991c09ea995d2181aeabf06c105b3d12eef13ddbbed15d220edbdd88941fe6a55a23fd5c600aa55623d
7
+ data.tar.gz: 805102e771aac93e6a75017dde3f88deee018dceff3c8c57f2ddcdea88f97f241980efc17885999989733952e771e0538a75eaf67566499e61534c9e64476f75
data/exe/erblint CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  $LOAD_PATH.unshift("#{__dir__}/../lib")
5
5
 
6
- require 'erb_lint/cli'
6
+ require "erb_lint/cli"
7
7
 
8
8
  cli = ERBLint::CLI.new
9
9
  exit(cli.run)
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ require "erb_lint"
6
+ require "erb_lint/corrector"
7
+ require "erb_lint/file_loader"
8
+ require "erb_lint/linter_config"
9
+ require "erb_lint/linter_registry"
10
+ require "erb_lint/linter"
11
+ require "erb_lint/offense"
12
+ require "erb_lint/processed_source"
13
+ require "erb_lint/runner_config"
14
+ require "erb_lint/runner"
15
+ require "erb_lint/stats"
16
+ require "erb_lint/reporter"
17
+
18
+ # Load linters
19
+ Dir[File.expand_path("linters/**/*.rb", __dir__)].each do |file|
20
+ require file
21
+ end
22
+
23
+ # Load reporters
24
+ Dir[File.expand_path("reporters/**/*.rb", __dir__)].each do |file|
25
+ require file
26
+ end
data/lib/erb_lint/cli.rb CHANGED
@@ -1,16 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'erb_lint'
4
- require 'active_support'
5
- require 'active_support/inflector'
6
- require 'optparse'
7
- require 'psych'
8
- require 'yaml'
9
- require 'rainbow'
3
+ require "erb_lint/all"
4
+ require "active_support"
5
+ require "active_support/inflector"
6
+ require "optparse"
7
+ require "psych"
8
+ require "yaml"
9
+ require "rainbow"
10
+ require "erb_lint/utils/severity_levels"
10
11
 
11
12
  module ERBLint
12
13
  class CLI
13
- DEFAULT_CONFIG_FILENAME = '.erb-lint.yml'
14
+ include Utils::SeverityLevels
15
+
16
+ DEFAULT_CONFIG_FILENAME = ".erb-lint.yml"
14
17
  DEFAULT_LINT_ALL_GLOB = "**/*.html{+*,}.erb"
15
18
 
16
19
  class ExitWithFailure < RuntimeError; end
@@ -27,7 +30,7 @@ module ERBLint
27
30
  def run(args = ARGV)
28
31
  dupped_args = args.dup
29
32
  load_options(dupped_args)
30
- @files = dupped_args
33
+ @files = @options[:stdin] || dupped_args
31
34
 
32
35
  load_config
33
36
 
@@ -40,25 +43,28 @@ module ERBLint
40
43
  ensure_files_exist(lint_files)
41
44
 
42
45
  if enabled_linter_classes.empty?
43
- failure!('no linter available with current configuration')
46
+ failure!("no linter available with current configuration")
44
47
  end
45
48
 
46
49
  @options[:format] ||= :multiline
50
+ @options[:fail_level] ||= severity_level_for_name(:refactor)
47
51
  @stats.files = lint_files.size
48
52
  @stats.linters = enabled_linter_classes.size
53
+ @stats.autocorrectable_linters = enabled_linter_classes.count(&:support_autocorrect?)
49
54
 
50
55
  reporter = Reporter.create_reporter(@options[:format], @stats, autocorrect?)
51
56
  reporter.preview
52
57
 
53
58
  runner = ERBLint::Runner.new(file_loader, @config)
59
+ file_content = nil
54
60
 
55
61
  lint_files.each do |filename|
56
62
  runner.clear_offenses
57
63
  begin
58
- run_with_corrections(runner, filename)
64
+ file_content = run_with_corrections(runner, filename)
59
65
  rescue => e
60
66
  @stats.exceptions += 1
61
- puts "Exception occured when processing: #{relative_filename(filename)}"
67
+ puts "Exception occurred when processing: #{relative_filename(filename)}"
62
68
  puts "If this file cannot be processed by erb-lint, "\
63
69
  "you can exclude it in your configuration file."
64
70
  puts e.message
@@ -69,6 +75,12 @@ module ERBLint
69
75
 
70
76
  reporter.show
71
77
 
78
+ if stdin? && autocorrect?
79
+ # When running from stdin, we only lint a single file
80
+ puts "================ #{lint_files.first} ==================\n"
81
+ puts file_content
82
+ end
83
+
72
84
  @stats.found == 0 && @stats.exceptions == 0
73
85
  rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, ExitWithFailure => e
74
86
  warn(Rainbow(e.message).red)
@@ -88,7 +100,7 @@ module ERBLint
88
100
  end
89
101
 
90
102
  def run_with_corrections(runner, filename)
91
- file_content = File.read(filename, encoding: Encoding::UTF_8)
103
+ file_content = read_content(filename)
92
104
 
93
105
  7.times do
94
106
  processed_source = ERBLint::ProcessedSource.new(filename, file_content)
@@ -101,8 +113,11 @@ module ERBLint
101
113
 
102
114
  @stats.corrected += corrector.corrections.size
103
115
 
104
- File.open(filename, "wb") do |file|
105
- file.write(corrector.corrected_content)
116
+ # Don't overwrite the file if the input comes from stdin
117
+ unless stdin?
118
+ File.open(filename, "wb") do |file|
119
+ file.write(corrector.corrected_content)
120
+ end
106
121
  end
107
122
 
108
123
  file_content = corrector.corrected_content
@@ -111,14 +126,27 @@ module ERBLint
111
126
  offenses_filename = relative_filename(filename)
112
127
  offenses = runner.offenses || []
113
128
 
114
- @stats.found += offenses.size
129
+ @stats.ignored, @stats.found = offenses.partition do |offense|
130
+ severity_level_for_name(offense.severity) < @options[:fail_level]
131
+ end.map(&:size)
132
+ .zip([@stats.ignored, @stats.found])
133
+ .map(&:sum)
134
+
115
135
  @stats.processed_files[offenses_filename] ||= []
116
136
  @stats.processed_files[offenses_filename] |= offenses
137
+
138
+ file_content
139
+ end
140
+
141
+ def read_content(filename)
142
+ return File.read(filename, encoding: Encoding::UTF_8) unless stdin?
143
+
144
+ $stdin.binmode.read.force_encoding(Encoding::UTF_8)
117
145
  end
118
146
 
119
147
  def correct(processed_source, offenses)
120
148
  corrector = ERBLint::Corrector.new(processed_source, offenses)
121
- failure!(corrector.diagnostics.join(', ')) if corrector.diagnostics.any?
149
+ failure!(corrector.diagnostics.join(", ")) if corrector.diagnostics.any?
122
150
  corrector
123
151
  end
124
152
 
@@ -156,7 +184,7 @@ module ERBLint
156
184
  else
157
185
  @files
158
186
  .map { |f| Dir.exist?(f) ? Dir[File.join(f, glob)] : f }
159
- .map { |f| f.include?('*') ? Dir[f] : f }
187
+ .map { |f| f.include?("*") ? Dir[f] : f }
160
188
  .flatten
161
189
  .map { |f| File.expand_path(f, Dir.pwd) }
162
190
  .select { |filename| !excluded?(filename) }
@@ -169,7 +197,8 @@ module ERBLint
169
197
 
170
198
  def excluded?(filename)
171
199
  @config.global_exclude.any? do |path|
172
- File.fnmatch?(path, filename)
200
+ expanded_path = File.expand_path(path, Dir.pwd)
201
+ File.fnmatch?(expanded_path, filename)
173
202
  end
174
203
  end
175
204
 
@@ -204,22 +233,18 @@ module ERBLint
204
233
 
205
234
  def enabled_linter_classes
206
235
  @enabled_linter_classes ||= ERBLint::LinterRegistry.linters
207
- .select { |klass| linter_can_run?(klass) && enabled_linter_names.include?(klass.simple_name.underscore) }
208
- end
209
-
210
- def linter_can_run?(klass)
211
- !autocorrect? || klass.support_autocorrect?
236
+ .select { |klass| enabled_linter_names.include?(klass.simple_name.underscore) }
212
237
  end
213
238
 
214
239
  def relative_filename(filename)
215
- filename.sub("#{File.expand_path('.', Dir.pwd)}/", '')
240
+ filename.sub("#{File.expand_path(".", Dir.pwd)}/", "")
216
241
  end
217
242
 
218
243
  def runner_config_override
219
244
  RunnerConfig.new(
220
245
  linters: {}.tap do |linters|
221
246
  ERBLint::LinterRegistry.linters.map do |klass|
222
- linters[klass.simple_name] = { 'enabled' => enabled_linter_classes.include?(klass) }
247
+ linters[klass.simple_name] = { "enabled" => enabled_linter_classes.include?(klass) }
223
248
  end
224
249
  end
225
250
  )
@@ -255,19 +280,36 @@ module ERBLint
255
280
  end
256
281
 
257
282
  opts.on("--enable-linters LINTER[,LINTER,...]", Array,
258
- "Only use specified linter", "Known linters are: #{known_linter_names.join(', ')}") do |linters|
283
+ "Only use specified linter", "Known linters are: #{known_linter_names.join(", ")}") do |linters|
259
284
  linters.each do |linter|
260
285
  unless known_linter_names.include?(linter)
261
- failure!("#{linter}: not a valid linter name (#{known_linter_names.join(', ')})")
286
+ failure!("#{linter}: not a valid linter name (#{known_linter_names.join(", ")})")
262
287
  end
263
288
  end
264
289
  @options[:enabled_linters] = linters
265
290
  end
266
291
 
292
+ opts.on("--fail-level SEVERITY", "Minimum severity for exit with error code") do |level|
293
+ parsed_severity = SEVERITY_CODE_TABLE[level.upcase.to_sym] || (SEVERITY_NAMES & [level.downcase]).first
294
+
295
+ if parsed_severity.nil?
296
+ failure!("#{level}: not a valid failure level (#{SEVERITY_NAMES.join(", ")})")
297
+ end
298
+ @options[:fail_level] = severity_level_for_name(parsed_severity)
299
+ end
300
+
267
301
  opts.on("-a", "--autocorrect", "Correct offenses automatically if possible (default: false)") do |config|
268
302
  @options[:autocorrect] = config
269
303
  end
270
304
 
305
+ opts.on(
306
+ "-sFILE",
307
+ "--stdin FILE",
308
+ "Pipe source from STDIN. Takes the path to be used to check which rules to apply."
309
+ ) do |file|
310
+ @options[:stdin] = [file]
311
+ end
312
+
271
313
  opts.on_tail("-h", "--help", "Show this message") do
272
314
  success!(opts)
273
315
  end
@@ -280,12 +322,16 @@ module ERBLint
280
322
 
281
323
  def format_options_help
282
324
  "Report offenses in the given format: "\
283
- "(#{Reporter.available_formats.join(', ')}) (default: multiline)"
325
+ "(#{Reporter.available_formats.join(", ")}) (default: multiline)"
284
326
  end
285
327
 
286
328
  def invalid_format_error_message(given_format)
287
329
  formats = Reporter.available_formats.map { |format| " - #{format}\n" }
288
330
  "#{given_format}: is not a valid format. Available formats:\n#{formats.join}"
289
331
  end
332
+
333
+ def stdin?
334
+ @options[:stdin].present?
335
+ end
290
336
  end
291
337
  end
@@ -21,7 +21,7 @@ module ERBLint
21
21
  end
22
22
 
23
23
  if ::RuboCop::Version::STRING.to_f >= 0.87
24
- require 'rubocop/cop/legacy/corrector'
24
+ require "rubocop/cop/legacy/corrector"
25
25
  BASE = ::RuboCop::Cop::Legacy::Corrector
26
26
 
27
27
  def diagnostics
@@ -15,9 +15,9 @@ module ERBLint
15
15
  # `ERBLint::Linters::Compass::Bar.simple_name` #=> "Compass::Bar"
16
16
  def inherited(linter)
17
17
  super
18
- linter.simple_name = if linter.name.start_with?('ERBLint::Linters::')
19
- name_parts = linter.name.split('::')
20
- name_parts[2..-1].join('::')
18
+ linter.simple_name = if linter.name.start_with?("ERBLint::Linters::")
19
+ name_parts = linter.name.split("::")
20
+ name_parts[2..-1].join("::")
21
21
  else
22
22
  linter.name
23
23
  end
@@ -53,8 +53,8 @@ module ERBLint
53
53
  raise NotImplementedError, "must implement ##{__method__}"
54
54
  end
55
55
 
56
- def add_offense(source_range, message, context = nil)
57
- @offenses << Offense.new(self, source_range, message, context)
56
+ def add_offense(source_range, message, context = nil, severity = nil)
57
+ @offenses << Offense.new(self, source_range, message, context, severity)
58
58
  end
59
59
 
60
60
  def clear_offenses
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support'
4
- require 'smart_properties'
3
+ require "active_support"
4
+ require "smart_properties"
5
5
 
6
6
  module ERBLint
7
7
  class LinterConfig
@@ -27,8 +27,9 @@ module ERBLint
27
27
  allowed_keys = self.class.properties.keys.map(&:to_s)
28
28
  given_keys = config.keys
29
29
  if (extra_keys = given_keys - allowed_keys).any?
30
- raise Error, "Given key is not allowed: #{extra_keys.join(', ')}"
30
+ raise Error, "Given key is not allowed: #{extra_keys.join(", ")}"
31
31
  end
32
+
32
33
  super(config)
33
34
  rescue SmartProperties::InitializationError => e
34
35
  raise Error, "The following properties are required to be set: #{e.properties}"
@@ -40,6 +41,7 @@ module ERBLint
40
41
  unless self.class.properties.key?(name)
41
42
  raise Error, "No such property: #{name}"
42
43
  end
44
+
43
45
  super
44
46
  end
45
47
 
@@ -3,7 +3,7 @@
3
3
  module ERBLint
4
4
  # Stores all linters available to the application.
5
5
  module LinterRegistry
6
- CUSTOM_LINTERS_DIR = '.erb-linters'
6
+ CUSTOM_LINTERS_DIR = ".erb-linters"
7
7
  @loaded_linters = []
8
8
 
9
9
  class << self
@@ -27,7 +27,7 @@ module ERBLint
27
27
  end
28
28
 
29
29
  def load_custom_linters(directory = CUSTOM_LINTERS_DIR)
30
- ruby_files = Dir.glob(File.expand_path(File.join(directory, '**', '*.rb')))
30
+ ruby_files = Dir.glob(File.expand_path(File.join(directory, "**", "*.rb")))
31
31
  ruby_files.each { |file| require file }
32
32
  end
33
33
  end
@@ -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,7 @@ module ERBLint
13
13
 
14
14
  class ConfigSchema < LinterConfig
15
15
  property :allowed_types, accepts: array_of?(String),
16
- default: -> { ['text/javascript'] }
16
+ default: -> { ["text/javascript"] }
17
17
  property :allow_blank, accepts: [true, false], default: true, reader: :allow_blank?
18
18
  property :disallow_inline_scripts, accepts: [true, false], default: false, reader: :disallow_inline_scripts?
19
19
  end
@@ -24,19 +24,19 @@ module ERBLint
24
24
  parser.nodes_with_type(:tag).each do |tag_node|
25
25
  tag = BetterHtml::Tree::Tag.from_node(tag_node)
26
26
  next if tag.closing?
27
- next unless tag.name == 'script'
27
+ next unless tag.name == "script"
28
28
 
29
29
  if @config.disallow_inline_scripts?
30
30
  name_node = tag_node.to_a[1]
31
31
  add_offense(
32
32
  name_node.loc,
33
33
  "Avoid using inline `<script>` tags altogether. "\
34
- "Instead, move javascript code into a static file."
34
+ "Instead, move javascript code into a static file."
35
35
  )
36
36
  next
37
37
  end
38
38
 
39
- type_attribute = tag.attributes['type']
39
+ type_attribute = tag.attributes["type"]
40
40
  type_present = type_attribute.present? && type_attribute.value_node.present?
41
41
 
42
42
  if !type_present && !@config.allow_blank?
@@ -50,8 +50,8 @@ module ERBLint
50
50
  add_offense(
51
51
  type_attribute.loc,
52
52
  "Avoid using #{type_attribute.value.inspect} as type for `<script>` tag. "\
53
- "Must be one of: #{@config.allowed_types.join(', ')}"\
54
- "#{' (or no type attribute)' if @config.allow_blank?}."
53
+ "Must be one of: #{@config.allowed_types.join(", ")}"\
54
+ "#{" (or no type attribute)" if @config.allow_blank?}."
55
55
  )
56
56
  end
57
57
  end
@@ -59,6 +59,7 @@ module ERBLint
59
59
 
60
60
  def autocorrect(_processed_source, offense)
61
61
  return unless offense.context
62
+
62
63
  lambda do |corrector|
63
64
  type_attribute, = *offense.context
64
65
  if type_attribute.nil?
@@ -25,7 +25,7 @@ module ERBLint
25
25
  add_offense(
26
26
  code_node.loc.end.adjust(begin_pos: -end_spaces.size),
27
27
  "Remove newline before `%>` to match start of tag.",
28
- ' '
28
+ " "
29
29
  )
30
30
  elsif start_with_newline && !end_with_newline
31
31
  add_offense(
@@ -39,7 +39,7 @@ module ERBLint
39
39
  add_offense(
40
40
  code_node.loc.end.adjust(begin_pos: -current_indent.size),
41
41
  "Indent `%>` on column #{erb_node.loc.column} to match start of tag.",
42
- ' ' * erb_node.loc.column
42
+ " " * erb_node.loc.column
43
43
  )
44
44
  end
45
45
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'better_html'
4
- require 'better_html/parser'
3
+ require "better_html"
4
+ require "better_html/parser"
5
5
 
6
6
  module ERBLint
7
7
  module Linters
@@ -11,7 +11,7 @@ module ERBLint
11
11
 
12
12
  class RuleSet
13
13
  include SmartProperties
14
- property :suggestion, accepts: String, default: ''
14
+ property :suggestion, accepts: String, default: ""
15
15
  property :deprecated, accepts: LinterConfig.array_of?(String), default: -> { [] }
16
16
  end
17
17
 
@@ -57,9 +57,10 @@ module ERBLint
57
57
  def class_name_with_loc(processed_source)
58
58
  Enumerator.new do |yielder|
59
59
  tags(processed_source).each do |tag|
60
- class_value = tag.attributes['class']&.value
60
+ class_value = tag.attributes["class"]&.value
61
61
  next unless class_value
62
- class_value.split(' ').each do |class_name|
62
+
63
+ class_value.split(" ").each do |class_name|
63
64
  yielder.yield(class_name, tag.loc)
64
65
  end
65
66
  end
@@ -69,7 +70,7 @@ module ERBLint
69
70
  def text_tags_content(processed_source)
70
71
  Enumerator.new do |yielder|
71
72
  script_tags(processed_source)
72
- .select { |tag| tag.attributes['type']&.value == 'text/html' }
73
+ .select { |tag| tag.attributes["type"]&.value == "text/html" }
73
74
  .each do |tag|
74
75
  index = processed_source.ast.to_a.find_index(tag.node)
75
76
  next_node = processed_source.ast.to_a[index + 1]
@@ -80,7 +81,7 @@ module ERBLint
80
81
  end
81
82
 
82
83
  def script_tags(processed_source)
83
- tags(processed_source).select { |tag| tag.name == 'script' }
84
+ tags(processed_source).select { |tag| tag.name == "script" }
84
85
  end
85
86
 
86
87
  def tags(processed_source)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'better_html'
4
- require 'better_html/test_helper/safe_erb_tester'
3
+ require "better_html"
4
+ require "better_html/test_helper/safe_erb_tester"
5
5
 
6
6
  module ERBLint
7
7
  module Linters
@@ -22,7 +22,7 @@ module ERBLint
22
22
 
23
23
  def autocorrect(_processed_source, offense)
24
24
  lambda do |corrector|
25
- corrector.replace(offense.source_range, '')
25
+ corrector.replace(offense.source_range, "")
26
26
  end
27
27
  end
28
28
  end
@@ -28,7 +28,7 @@ module ERBLint
28
28
  if final_newline.empty?
29
29
  add_offense(
30
30
  processed_source.to_source_range(file_content.size...file_content.size),
31
- 'Missing a trailing newline at the end of the file.',
31
+ "Missing a trailing newline at the end of the file.",
32
32
  :insert
33
33
  )
34
34
  else
@@ -36,7 +36,7 @@ module ERBLint
36
36
  processed_source.to_source_range(
37
37
  (file_content.size - final_newline.size + 1)...file_content.size
38
38
  ),
39
- 'Remove multiple trailing newline at the end of the file.',
39
+ "Remove multiple trailing newline at the end of the file.",
40
40
  :remove
41
41
  )
42
42
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "set"
3
- require 'better_html/tree/tag'
4
- require 'active_support/core_ext/string/inflections'
4
+ require "better_html/tree/tag"
5
+ require "active_support/core_ext/string/inflections"
5
6
 
6
7
  module ERBLint
7
8
  module Linters
@@ -13,17 +14,37 @@ module ERBLint
13
14
  MissingCorrector = Class.new(StandardError)
14
15
  MissingI18nLoadPath = Class.new(StandardError)
15
16
 
16
- ALLOWED_CORRECTORS = %w(
17
- I18nCorrector
18
- RuboCop::Corrector::I18n::HardCodedString
19
- )
20
-
21
- NON_TEXT_TAGS = Set.new(%w(script style xmp iframe noembed noframes listing))
22
- BLACK_LISTED_TEXT = Set.new(%w(&nbsp; &ensp; &emsp; &thinsp;))
17
+ ALLOWED_CORRECTORS = ["I18nCorrector", "RuboCop::Corrector::I18n::HardCodedString"]
18
+
19
+ NON_TEXT_TAGS = Set.new(["script", "style", "xmp", "iframe", "noembed", "noframes", "listing"])
20
+ TEXT_NOT_ALLOWED = Set.new([
21
+ "&nbsp;",
22
+ "&amp;",
23
+ "&lt;",
24
+ "&gt;",
25
+ "&quot;",
26
+ "&copy;",
27
+ "&reg;",
28
+ "&trade;",
29
+ "&hellip;",
30
+ "&mdash;",
31
+ "&bull;",
32
+ "&ldquo;",
33
+ "&rdquo;",
34
+ "&lsquo;",
35
+ "&rsquo;",
36
+ "&larr;",
37
+ "&rarr;",
38
+ "&darr;",
39
+ "&uarr;",
40
+ "&ensp;",
41
+ "&emsp;",
42
+ "&thinsp;",
43
+ ])
23
44
 
24
45
  class ConfigSchema < LinterConfig
25
46
  property :corrector, accepts: Hash, required: false, default: -> { {} }
26
- property :i18n_load_path, accepts: String, required: false, default: ''
47
+ property :i18n_load_path, accepts: String, required: false, default: ""
27
48
  end
28
49
  self.config_schema = ConfigSchema
29
50
 
@@ -63,9 +84,10 @@ module ERBLint
63
84
  string = offense.source_range.source
64
85
  return unless (klass = load_corrector)
65
86
  return unless string.strip.length > 1
87
+
66
88
  node = ::RuboCop::AST::StrNode.new(:str, [string])
67
89
  corrector = klass.new(node, processed_source.filename, corrector_i18n_load_path, offense.source_range)
68
- corrector.autocorrect(tag_start: '<%= ', tag_end: ' %>')
90
+ corrector.autocorrect(tag_start: "<%= ", tag_end: " %>")
69
91
  rescue MissingCorrector, MissingI18nLoadPath
70
92
  nil
71
93
  end
@@ -73,20 +95,21 @@ module ERBLint
73
95
  private
74
96
 
75
97
  def check_string?(str)
76
- string = str.gsub(/\s*/, '')
77
- string.length > 1 && !BLACK_LISTED_TEXT.include?(string)
98
+ string = str.gsub(/\s*/, "")
99
+ string.length > 1 && !TEXT_NOT_ALLOWED.include?(string)
78
100
  end
79
101
 
80
102
  def load_corrector
81
- corrector_name = @config['corrector'].fetch('name') { raise MissingCorrector }
103
+ corrector_name = @config["corrector"].fetch("name") { raise MissingCorrector }
82
104
  raise ForbiddenCorrector unless ALLOWED_CORRECTORS.include?(corrector_name)
83
- require @config['corrector'].fetch('path') { raise MissingCorrector }
105
+
106
+ require @config["corrector"].fetch("path") { raise MissingCorrector }
84
107
 
85
108
  corrector_name.safe_constantize
86
109
  end
87
110
 
88
111
  def corrector_i18n_load_path
89
- @config['corrector'].fetch('i18n_load_path') { raise MissingI18nLoadPath }
112
+ @config["corrector"].fetch("i18n_load_path") { raise MissingI18nLoadPath }
90
113
  end
91
114
 
92
115
  def non_text_tag?(processed_source, text_node)