erb_lint 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/erb_lint/cache.rb +2 -2
- data/lib/erb_lint/cached_offense.rb +1 -1
- data/lib/erb_lint/cli.rb +15 -7
- data/lib/erb_lint/linter.rb +1 -1
- data/lib/erb_lint/linters/allowed_script_type.rb +8 -7
- data/lib/erb_lint/linters/closing_erb_tag_indent.rb +3 -3
- data/lib/erb_lint/linters/comment_syntax.rb +1 -1
- data/lib/erb_lint/linters/deprecated_classes.rb +2 -2
- data/lib/erb_lint/linters/erb_safety.rb +1 -1
- data/lib/erb_lint/linters/extra_newline.rb +1 -1
- data/lib/erb_lint/linters/final_newline.rb +4 -4
- data/lib/erb_lint/linters/hard_coded_string.rb +2 -2
- data/lib/erb_lint/linters/no_javascript_tag_helper.rb +6 -4
- data/lib/erb_lint/linters/no_unused_disable.rb +4 -2
- data/lib/erb_lint/linters/parser_errors.rb +1 -1
- data/lib/erb_lint/linters/partial_instance_variable.rb +2 -2
- data/lib/erb_lint/linters/require_input_autocomplete.rb +4 -4
- data/lib/erb_lint/linters/require_script_nonce.rb +2 -2
- data/lib/erb_lint/linters/right_trim.rb +1 -1
- data/lib/erb_lint/linters/rubocop.rb +3 -3
- data/lib/erb_lint/linters/rubocop_text.rb +1 -1
- data/lib/erb_lint/linters/self_closing_tag.rb +22 -5
- data/lib/erb_lint/linters/space_around_erb_tag.rb +8 -8
- data/lib/erb_lint/linters/space_in_html_tag.rb +7 -7
- data/lib/erb_lint/linters/space_indentation.rb +1 -1
- data/lib/erb_lint/linters/trailing_whitespace.rb +1 -1
- data/lib/erb_lint/offense.rb +3 -3
- data/lib/erb_lint/processed_source.rb +1 -1
- data/lib/erb_lint/reporter.rb +3 -2
- data/lib/erb_lint/reporters/compact_reporter.rb +3 -2
- data/lib/erb_lint/reporters/gitlab_reporter.rb +55 -0
- data/lib/erb_lint/reporters/multiline_reporter.rb +6 -1
- data/lib/erb_lint/runner.rb +1 -1
- data/lib/erb_lint/utils/block_map.rb +4 -4
- data/lib/erb_lint/utils/offset_corrector.rb +2 -5
- data/lib/erb_lint/utils/severity_levels.rb +8 -2
- data/lib/erb_lint/version.rb +1 -1
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba9ef5f8b8a251d649dd1cffba1094d770471a630d0fa66b402621883ea3b050
|
4
|
+
data.tar.gz: db969c9e8bacc58b20fa9ad568c98263225c8bbf41f2d32f1b5d9f44a4c58aab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1d9e86c1862a41bb8cc2d1ae520af38ced2390e3d06c3d9bc9550a434993de502167c87adf93a780fec7f87d4921e77367e8bf8c546bf59c6f88908d0208039
|
7
|
+
data.tar.gz: 468ef87d28e39aa2fb0166cdfc98bee1f1f7349d21a9a5e2c08a81f5aab47c067d1d440d6466cf28077f5d72984b9d0018bdc23af2e3b91a6127bfc46f850f5a
|
data/lib/erb_lint/cache.rb
CHANGED
@@ -16,7 +16,7 @@ module ERBLint
|
|
16
16
|
file_checksum = checksum(filename, file_content)
|
17
17
|
begin
|
18
18
|
cache_file_contents_as_offenses = JSON.parse(
|
19
|
-
File.read(File.join(@cache_dir, file_checksum))
|
19
|
+
File.read(File.join(@cache_dir, file_checksum)),
|
20
20
|
).map do |offense_hash|
|
21
21
|
ERBLint::CachedOffense.new(offense_hash)
|
22
22
|
end
|
@@ -76,7 +76,7 @@ module ERBLint
|
|
76
76
|
mode = File.stat(filename).mode
|
77
77
|
|
78
78
|
digester.update(
|
79
|
-
"#{mode}#{config.to_hash}#{ERBLint::VERSION}#{file_content}"
|
79
|
+
"#{mode}#{config.to_hash}#{ERBLint::VERSION}#{file_content}",
|
80
80
|
)
|
81
81
|
digester.hexdigest
|
82
82
|
rescue Errno::ENOENT
|
data/lib/erb_lint/cli.rb
CHANGED
@@ -74,7 +74,7 @@ module ERBLint
|
|
74
74
|
@stats.linters = enabled_linter_classes.size
|
75
75
|
@stats.autocorrectable_linters = enabled_linter_classes.count(&:support_autocorrect?)
|
76
76
|
|
77
|
-
reporter = Reporter.create_reporter(@options[:format], @stats, autocorrect
|
77
|
+
reporter = Reporter.create_reporter(@options[:format], @stats, autocorrect?, @options[:show_linter_names])
|
78
78
|
reporter.preview
|
79
79
|
|
80
80
|
runner = ERBLint::Runner.new(file_loader, @config, @options[:disable_inline_configs])
|
@@ -87,7 +87,7 @@ module ERBLint
|
|
87
87
|
rescue => e
|
88
88
|
@stats.exceptions += 1
|
89
89
|
puts "Exception occurred when processing: #{relative_filename(filename)}"
|
90
|
-
puts "If this file cannot be processed by erb-lint, "\
|
90
|
+
puts "If this file cannot be processed by erb-lint, " \
|
91
91
|
"you can exclude it in your configuration file."
|
92
92
|
puts e.message
|
93
93
|
puts Rainbow(e.backtrace.join("\n")).red
|
@@ -303,7 +303,7 @@ module ERBLint
|
|
303
303
|
ERBLint::LinterRegistry.linters.map do |klass|
|
304
304
|
linters[klass.simple_name] = { "enabled" => enabled_linter_classes.include?(klass) }
|
305
305
|
end
|
306
|
-
end
|
306
|
+
end,
|
307
307
|
)
|
308
308
|
end
|
309
309
|
|
@@ -348,8 +348,12 @@ module ERBLint
|
|
348
348
|
@options[:clear_cache] = config
|
349
349
|
end
|
350
350
|
|
351
|
-
opts.on(
|
352
|
-
"
|
351
|
+
opts.on(
|
352
|
+
"--enable-linters LINTER[,LINTER,...]",
|
353
|
+
Array,
|
354
|
+
"Only use specified linter",
|
355
|
+
"Known linters are: #{known_linter_names.join(", ")}",
|
356
|
+
) do |linters|
|
353
357
|
linters.each do |linter|
|
354
358
|
unless known_linter_names.include?(linter)
|
355
359
|
failure!("#{linter}: not a valid linter name (#{known_linter_names.join(", ")})")
|
@@ -371,6 +375,10 @@ module ERBLint
|
|
371
375
|
@options[:autocorrect] = config
|
372
376
|
end
|
373
377
|
|
378
|
+
opts.on("--show-linter-names", "Show linter names") do
|
379
|
+
@options[:show_linter_names] = true
|
380
|
+
end
|
381
|
+
|
374
382
|
opts.on("--allow-no-files", "When no matching files found, exit successfully (default: false)") do |config|
|
375
383
|
@options[:allow_no_files] = config
|
376
384
|
end
|
@@ -382,7 +390,7 @@ module ERBLint
|
|
382
390
|
opts.on(
|
383
391
|
"-sFILE",
|
384
392
|
"--stdin FILE",
|
385
|
-
"Pipe source from STDIN. Takes the path to be used to check which rules to apply."
|
393
|
+
"Pipe source from STDIN. Takes the path to be used to check which rules to apply.",
|
386
394
|
) do |file|
|
387
395
|
@options[:stdin] = [file]
|
388
396
|
end
|
@@ -398,7 +406,7 @@ module ERBLint
|
|
398
406
|
end
|
399
407
|
|
400
408
|
def format_options_help
|
401
|
-
"Report offenses in the given format: "\
|
409
|
+
"Report offenses in the given format: " \
|
402
410
|
"(#{Reporter.available_formats.join(", ")}) (default: multiline)"
|
403
411
|
end
|
404
412
|
|
data/lib/erb_lint/linter.rb
CHANGED
@@ -38,7 +38,7 @@ module ERBLint
|
|
38
38
|
def initialize(file_loader, config)
|
39
39
|
@file_loader = file_loader
|
40
40
|
@config = config
|
41
|
-
raise ArgumentError, "expect `config` to be #{self.class.config_schema} instance, "\
|
41
|
+
raise ArgumentError, "expect `config` to be #{self.class.config_schema} instance, " \
|
42
42
|
"not #{config.class}" unless config.is_a?(self.class.config_schema)
|
43
43
|
@offenses = []
|
44
44
|
end
|
@@ -12,7 +12,8 @@ module ERBLint
|
|
12
12
|
include LinterRegistry
|
13
13
|
|
14
14
|
class ConfigSchema < LinterConfig
|
15
|
-
property :allowed_types,
|
15
|
+
property :allowed_types,
|
16
|
+
accepts: array_of?(String),
|
16
17
|
default: -> { ["text/javascript"] }
|
17
18
|
property :allow_blank, accepts: [true, false], default: true, reader: :allow_blank?
|
18
19
|
property :disallow_inline_scripts, accepts: [true, false], default: false, reader: :disallow_inline_scripts?
|
@@ -30,8 +31,8 @@ module ERBLint
|
|
30
31
|
name_node = tag_node.to_a[1]
|
31
32
|
add_offense(
|
32
33
|
name_node.loc,
|
33
|
-
"Avoid using inline `<script>` tags altogether. "\
|
34
|
-
"Instead, move javascript code into a static file."
|
34
|
+
"Avoid using inline `<script>` tags altogether. " \
|
35
|
+
"Instead, move javascript code into a static file.",
|
35
36
|
)
|
36
37
|
next
|
37
38
|
end
|
@@ -44,14 +45,14 @@ module ERBLint
|
|
44
45
|
add_offense(
|
45
46
|
name_node.loc,
|
46
47
|
"Missing a `type=\"text/javascript\"` attribute to `<script>` tag.",
|
47
|
-
[type_attribute]
|
48
|
+
[type_attribute],
|
48
49
|
)
|
49
50
|
elsif type_present && !@config.allowed_types.include?(type_attribute.value)
|
50
51
|
add_offense(
|
51
52
|
type_attribute.loc,
|
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
|
+
"Avoid using #{type_attribute.value.inspect} as type for `<script>` tag. " \
|
54
|
+
"Must be one of: #{@config.allowed_types.join(", ")}" \
|
55
|
+
"#{" (or no type attribute)" if @config.allow_blank?}.",
|
55
56
|
)
|
56
57
|
end
|
57
58
|
end
|
@@ -25,13 +25,13 @@ 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(
|
32
32
|
code_node.loc.end.adjust(begin_pos: -end_spaces.size),
|
33
33
|
"Insert newline before `%>` to match start of tag.",
|
34
|
-
"\n"
|
34
|
+
"\n",
|
35
35
|
)
|
36
36
|
elsif start_with_newline && end_with_newline
|
37
37
|
current_indent = end_spaces.split("\n", -1).last
|
@@ -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
|
@@ -31,7 +31,7 @@ module ERBLint
|
|
31
31
|
|
32
32
|
add_offense(
|
33
33
|
source_range,
|
34
|
-
<<~EOF.chomp
|
34
|
+
<<~EOF.chomp,
|
35
35
|
Bad ERB comment syntax. Should be #{correct_erb_tag} without a space between.
|
36
36
|
Leaving a space between ERB tags and the Ruby comment character can cause parser errors.
|
37
37
|
EOF
|
@@ -49,7 +49,7 @@ module ERBLint
|
|
49
49
|
process_nested_offenses(
|
50
50
|
source: sub_source,
|
51
51
|
offset: offset + content_node.loc.begin_pos,
|
52
|
-
parent_source: parent_source
|
52
|
+
parent_source: parent_source,
|
53
53
|
)
|
54
54
|
end
|
55
55
|
end
|
@@ -99,7 +99,7 @@ module ERBLint
|
|
99
99
|
|
100
100
|
add_offense(
|
101
101
|
range,
|
102
|
-
format(message, class_name, violated_rule[:class_expr], suggestion)
|
102
|
+
format(message, class_name, violated_rule[:class_expr], suggestion),
|
103
103
|
)
|
104
104
|
end
|
105
105
|
end
|
@@ -29,22 +29,22 @@ module ERBLint
|
|
29
29
|
add_offense(
|
30
30
|
processed_source.to_source_range(file_content.size...file_content.size),
|
31
31
|
"Missing a trailing newline at the end of the file.",
|
32
|
-
:insert
|
32
|
+
:insert,
|
33
33
|
)
|
34
34
|
else
|
35
35
|
add_offense(
|
36
36
|
processed_source.to_source_range(
|
37
|
-
(file_content.size - final_newline.size + 1)...file_content.size
|
37
|
+
(file_content.size - final_newline.size + 1)...file_content.size,
|
38
38
|
),
|
39
39
|
"Remove multiple trailing newline at the end of the file.",
|
40
|
-
:remove
|
40
|
+
:remove,
|
41
41
|
)
|
42
42
|
end
|
43
43
|
elsif !@new_lines_should_be_present && !final_newline.empty?
|
44
44
|
add_offense(
|
45
45
|
processed_source.to_source_range(match.begin(0)...match.end(0)),
|
46
46
|
"Remove #{final_newline.size} trailing newline at the end of the file.",
|
47
|
-
:remove
|
47
|
+
:remove,
|
48
48
|
)
|
49
49
|
end
|
50
50
|
end
|
@@ -67,7 +67,7 @@ module ERBLint
|
|
67
67
|
|
68
68
|
add_offense(
|
69
69
|
source_range,
|
70
|
-
message(source_range.source)
|
70
|
+
message(source_range.source),
|
71
71
|
)
|
72
72
|
end
|
73
73
|
end
|
@@ -84,7 +84,7 @@ module ERBLint
|
|
84
84
|
def autocorrect(processed_source, offense)
|
85
85
|
string = offense.source_range.source
|
86
86
|
return unless (klass = load_corrector)
|
87
|
-
return
|
87
|
+
return if string.strip.length <= 1
|
88
88
|
|
89
89
|
node = ::RuboCop::AST::StrNode.new(:str, [string])
|
90
90
|
corrector = klass.new(node, processed_source.filename, corrector_i18n_load_path, offense.source_range)
|
@@ -38,9 +38,9 @@ module ERBLint
|
|
38
38
|
|
39
39
|
add_offense(
|
40
40
|
erb_node.loc,
|
41
|
-
"Avoid using 'javascript_tag do' as it confuses tests "\
|
41
|
+
"Avoid using 'javascript_tag do' as it confuses tests " \
|
42
42
|
"that validate html, use inline <script> instead",
|
43
|
-
[erb_node, send_node]
|
43
|
+
[erb_node, send_node],
|
44
44
|
)
|
45
45
|
end
|
46
46
|
end
|
@@ -82,8 +82,10 @@ module ERBLint
|
|
82
82
|
corrector.replace(end_node.loc, end_content)
|
83
83
|
elsif script_content
|
84
84
|
script_content = "\n//<![CDATA[\n#{script_content}\n//]]>\n" if @config.correction_style == :cdata
|
85
|
-
corrector.replace(
|
86
|
-
|
85
|
+
corrector.replace(
|
86
|
+
begin_node.loc,
|
87
|
+
"<script#{arguments}>#{script_content}</script>",
|
88
|
+
)
|
87
89
|
end
|
88
90
|
rescue Utils::RubyToERB::Error, Utils::BlockMap::ParseError
|
89
91
|
nil
|
@@ -35,8 +35,10 @@ module ERBLint
|
|
35
35
|
|
36
36
|
disabled_rules_and_line_number.each do |rule, line_numbers|
|
37
37
|
line_numbers.each do |line_number|
|
38
|
-
add_offense(
|
39
|
-
|
38
|
+
add_offense(
|
39
|
+
processed_source.source_buffer.line_range(line_number),
|
40
|
+
"Unused erblint:disable comment for #{rule}",
|
41
|
+
)
|
40
42
|
end
|
41
43
|
end
|
42
44
|
end
|
@@ -13,9 +13,9 @@ module ERBLint
|
|
13
13
|
|
14
14
|
add_offense(
|
15
15
|
processed_source.to_source_range(
|
16
|
-
processed_source.file_content =~ instance_variable_regex..processed_source.file_content.size
|
16
|
+
processed_source.file_content =~ instance_variable_regex..processed_source.file_content.size,
|
17
17
|
),
|
18
|
-
"Instance variable detected in partial."
|
18
|
+
"Instance variable detected in partial.",
|
19
19
|
)
|
20
20
|
end
|
21
21
|
end
|
@@ -62,9 +62,9 @@ module ERBLint
|
|
62
62
|
|
63
63
|
add_offense(
|
64
64
|
tag_node.to_a[1].loc,
|
65
|
-
"Input tag is missing an autocomplete attribute. If no "\
|
65
|
+
"Input tag is missing an autocomplete attribute. If no " \
|
66
66
|
"autocomplete behaviour is desired, use the value `off` or `nope`.",
|
67
|
-
[autocomplete_attribute]
|
67
|
+
[autocomplete_attribute],
|
68
68
|
)
|
69
69
|
end
|
70
70
|
end
|
@@ -96,9 +96,9 @@ module ERBLint
|
|
96
96
|
|
97
97
|
add_offense(
|
98
98
|
erb_node.loc,
|
99
|
-
"Input field helper is missing an autocomplete attribute. If no "\
|
99
|
+
"Input field helper is missing an autocomplete attribute. If no " \
|
100
100
|
"autocomplete behaviour is desired, use the value `off` or `nope`.",
|
101
|
-
[erb_node, send_node]
|
101
|
+
[erb_node, send_node],
|
102
102
|
)
|
103
103
|
end
|
104
104
|
end
|
@@ -29,7 +29,7 @@ module ERBLint
|
|
29
29
|
add_offense(
|
30
30
|
tag_node.to_a[1].loc,
|
31
31
|
"Missing a nonce attribute. Use request.content_security_policy_nonce",
|
32
|
-
[nonce_attribute]
|
32
|
+
[nonce_attribute],
|
33
33
|
)
|
34
34
|
end
|
35
35
|
end
|
@@ -67,7 +67,7 @@ module ERBLint
|
|
67
67
|
add_offense(
|
68
68
|
erb_node.loc,
|
69
69
|
"Missing a nonce attribute. Use nonce: true",
|
70
|
-
[erb_node, send_node]
|
70
|
+
[erb_node, send_node],
|
71
71
|
)
|
72
72
|
end
|
73
73
|
end
|
@@ -19,7 +19,7 @@ module ERBLint
|
|
19
19
|
|
20
20
|
add_offense(
|
21
21
|
trim_node.loc,
|
22
|
-
"Prefer #{@config.enforced_style}%> instead of #{trim_node.loc.source}%> for trimming on the right."
|
22
|
+
"Prefer #{@config.enforced_style}%> instead of #{trim_node.loc.source}%> for trimming on the right.",
|
23
23
|
)
|
24
24
|
end
|
25
25
|
end
|
@@ -134,7 +134,7 @@ module ERBLint
|
|
134
134
|
source = ::RuboCop::ProcessedSource.new(
|
135
135
|
content,
|
136
136
|
@rubocop_config.target_ruby_version,
|
137
|
-
filename
|
137
|
+
filename,
|
138
138
|
)
|
139
139
|
if ::RuboCop::Version::STRING.to_f >= 1.38
|
140
140
|
registry = RuboCop::Cop::Registry.global
|
@@ -146,10 +146,10 @@ module ERBLint
|
|
146
146
|
|
147
147
|
def cop_classes
|
148
148
|
if @only_cops.present?
|
149
|
-
selected_cops = ::RuboCop::Cop::
|
149
|
+
selected_cops = ::RuboCop::Cop::Registry.all.select { |cop| cop.match?(@only_cops) }
|
150
150
|
::RuboCop::Cop::Registry.new(selected_cops)
|
151
151
|
else
|
152
|
-
::RuboCop::Cop::Registry.new(::RuboCop::Cop::
|
152
|
+
::RuboCop::Cop::Registry.new(::RuboCop::Cop::Registry.all)
|
153
153
|
end
|
154
154
|
end
|
155
155
|
|
@@ -29,7 +29,7 @@ module ERBLint
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def cop_classes
|
32
|
-
selected_cops = ::RuboCop::Cop::
|
32
|
+
selected_cops = ::RuboCop::Cop::Registry.all.select { |cop| cop.match?(@only_cops) }
|
33
33
|
|
34
34
|
::RuboCop::Cop::Registry.new(selected_cops)
|
35
35
|
end
|
@@ -11,8 +11,25 @@ module ERBLint
|
|
11
11
|
end
|
12
12
|
self.config_schema = ConfigSchema
|
13
13
|
|
14
|
-
SELF_CLOSING_TAGS = [
|
15
|
-
|
14
|
+
SELF_CLOSING_TAGS = [
|
15
|
+
"area",
|
16
|
+
"base",
|
17
|
+
"br",
|
18
|
+
"col",
|
19
|
+
"command",
|
20
|
+
"embed",
|
21
|
+
"hr",
|
22
|
+
"input",
|
23
|
+
"keygen",
|
24
|
+
"link",
|
25
|
+
"menuitem",
|
26
|
+
"meta",
|
27
|
+
"param",
|
28
|
+
"source",
|
29
|
+
"track",
|
30
|
+
"wbr",
|
31
|
+
"img",
|
32
|
+
]
|
16
33
|
|
17
34
|
def run(processed_source)
|
18
35
|
processed_source.ast.descendants(:tag).each do |tag_node|
|
@@ -24,7 +41,7 @@ module ERBLint
|
|
24
41
|
add_offense(
|
25
42
|
start_solidus.loc,
|
26
43
|
"Tag `#{tag.name}` is a void element, it must not start with `</`.",
|
27
|
-
""
|
44
|
+
"",
|
28
45
|
)
|
29
46
|
end
|
30
47
|
|
@@ -32,7 +49,7 @@ module ERBLint
|
|
32
49
|
add_offense(
|
33
50
|
tag_node.loc.end.offset(-1),
|
34
51
|
"Tag `#{tag.name}` is self-closing, it must end with `/>`.",
|
35
|
-
"/"
|
52
|
+
"/",
|
36
53
|
)
|
37
54
|
end
|
38
55
|
|
@@ -42,7 +59,7 @@ module ERBLint
|
|
42
59
|
add_offense(
|
43
60
|
end_solidus.loc,
|
44
61
|
"Tag `#{tag.name}` is a void element, it must end with `>` and not `/>`.",
|
45
|
-
""
|
62
|
+
"",
|
46
63
|
)
|
47
64
|
end
|
48
65
|
end
|
@@ -23,17 +23,17 @@ module ERBLint
|
|
23
23
|
if start_spaces.size != 1 && !start_spaces.include?("\n")
|
24
24
|
add_offense(
|
25
25
|
code_node.loc.resize(start_spaces.size),
|
26
|
-
"Use 1 space after `<%#{indicator}#{ltrim&.loc&.source}` "\
|
26
|
+
"Use 1 space after `<%#{indicator}#{ltrim&.loc&.source}` " \
|
27
27
|
"instead of #{start_spaces.size} space#{"s" if start_spaces.size > 1}.",
|
28
|
-
" "
|
28
|
+
" ",
|
29
29
|
)
|
30
30
|
elsif start_spaces.count("\n") > 1
|
31
31
|
lines = start_spaces.split("\n", -1)
|
32
32
|
add_offense(
|
33
33
|
code_node.loc.resize(start_spaces.size),
|
34
|
-
"Use 1 newline after `<%#{indicator&.loc&.source}#{ltrim&.loc&.source}` "\
|
34
|
+
"Use 1 newline after `<%#{indicator&.loc&.source}#{ltrim&.loc&.source}` " \
|
35
35
|
"instead of #{start_spaces.count("\n")}.",
|
36
|
-
"#{lines.first}\n#{lines.last}"
|
36
|
+
"#{lines.first}\n#{lines.last}",
|
37
37
|
)
|
38
38
|
end
|
39
39
|
|
@@ -41,17 +41,17 @@ module ERBLint
|
|
41
41
|
if end_spaces.size != 1 && !end_spaces.include?("\n")
|
42
42
|
add_offense(
|
43
43
|
code_node.loc.end.adjust(begin_pos: -end_spaces.size),
|
44
|
-
"Use 1 space before `#{rtrim&.loc&.source}%>` "\
|
44
|
+
"Use 1 space before `#{rtrim&.loc&.source}%>` " \
|
45
45
|
"instead of #{end_spaces.size} space#{"s" if start_spaces.size > 1}.",
|
46
|
-
" "
|
46
|
+
" ",
|
47
47
|
)
|
48
48
|
elsif end_spaces.count("\n") > 1
|
49
49
|
lines = end_spaces.split("\n", -1)
|
50
50
|
add_offense(
|
51
51
|
code_node.loc.end.adjust(begin_pos: -end_spaces.size),
|
52
|
-
"Use 1 newline before `#{rtrim&.loc&.source}%>` "\
|
52
|
+
"Use 1 newline before `#{rtrim&.loc&.source}%>` " \
|
53
53
|
"instead of #{end_spaces.count("\n")}.",
|
54
|
-
"#{lines.first}\n#{lines.last}"
|
54
|
+
"#{lines.first}\n#{lines.last}",
|
55
55
|
)
|
56
56
|
end
|
57
57
|
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
|
|
@@ -69,24 +69,24 @@ module ERBLint
|
|
69
69
|
if non_space && !non_space.captures.empty?
|
70
70
|
add_offense(
|
71
71
|
processed_source.to_source_range(range),
|
72
|
-
"Non-whitespace character(s) detected: "\
|
72
|
+
"Non-whitespace character(s) detected: " \
|
73
73
|
"#{non_space.captures.map(&:inspect).join(", ")}.",
|
74
|
-
expected
|
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
|
-
expected
|
82
|
+
expected,
|
83
83
|
)
|
84
84
|
end
|
85
85
|
else
|
86
86
|
add_offense(
|
87
87
|
processed_source.to_source_range(range),
|
88
88
|
"#{chars.empty? ? "No" : "Extra"} space detected where there should be a single space.",
|
89
|
-
expected
|
89
|
+
expected,
|
90
90
|
)
|
91
91
|
end
|
92
92
|
end
|
@@ -103,7 +103,7 @@ module ERBLint
|
|
103
103
|
|
104
104
|
single_space_or_newline(
|
105
105
|
processed_source,
|
106
|
-
attribute.loc.end_pos...next_attribute.loc.begin_pos
|
106
|
+
attribute.loc.end_pos...next_attribute.loc.begin_pos,
|
107
107
|
)
|
108
108
|
end
|
109
109
|
end
|
@@ -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
|
|
data/lib/erb_lint/offense.rb
CHANGED
@@ -23,9 +23,9 @@ module ERBLint
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def inspect
|
26
|
-
"#<#{self.class.name} linter=#{linter.class.name} "\
|
27
|
-
"source_range=#{source_range.begin_pos}...#{source_range.end_pos} "\
|
28
|
-
"message=#{message}> "\
|
26
|
+
"#<#{self.class.name} linter=#{linter.class.name} " \
|
27
|
+
"source_range=#{source_range.begin_pos}...#{source_range.end_pos} " \
|
28
|
+
"message=#{message}> " \
|
29
29
|
"severity=#{severity}"
|
30
30
|
end
|
31
31
|
|
data/lib/erb_lint/reporter.rb
CHANGED
@@ -23,9 +23,10 @@ module ERBLint
|
|
23
23
|
.sort
|
24
24
|
end
|
25
25
|
|
26
|
-
def initialize(stats, autocorrect)
|
26
|
+
def initialize(stats, autocorrect, show_linter_names = false)
|
27
27
|
@stats = stats
|
28
28
|
@autocorrect = autocorrect
|
29
|
+
@show_linter_names = show_linter_names
|
29
30
|
end
|
30
31
|
|
31
32
|
def preview; end
|
@@ -34,7 +35,7 @@ module ERBLint
|
|
34
35
|
|
35
36
|
private
|
36
37
|
|
37
|
-
attr_reader :stats, :autocorrect
|
38
|
+
attr_reader :stats, :autocorrect, :show_linter_names
|
38
39
|
|
39
40
|
delegate :processed_files, to: :stats
|
40
41
|
end
|
@@ -33,8 +33,9 @@ module ERBLint
|
|
33
33
|
"#{filename}:",
|
34
34
|
"#{offense.line_number}:",
|
35
35
|
"#{offense.column}: ",
|
36
|
+
("[#{offense.simple_name}] " if show_linter_names),
|
36
37
|
offense.message.to_s,
|
37
|
-
].join
|
38
|
+
].compact.join
|
38
39
|
end
|
39
40
|
|
40
41
|
def footer; end
|
@@ -60,7 +61,7 @@ module ERBLint
|
|
60
61
|
|
61
62
|
if corrected_found_diff > 0
|
62
63
|
message = Rainbow(
|
63
|
-
"#{stats.corrected} error(s) corrected and #{corrected_found_diff} error(s) remaining in ERB files"
|
64
|
+
"#{stats.corrected} error(s) corrected and #{corrected_found_diff} error(s) remaining in ERB files",
|
64
65
|
).red
|
65
66
|
|
66
67
|
warn(message)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module ERBLint
|
6
|
+
module Reporters
|
7
|
+
class GitlabReporter < Reporter
|
8
|
+
def preview; end
|
9
|
+
|
10
|
+
def show
|
11
|
+
puts formatted_data
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def formatted_data
|
17
|
+
formatted_files.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
def formatted_files
|
21
|
+
processed_files.flat_map do |filename, offenses|
|
22
|
+
formatted_offenses(filename, offenses)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def formatted_offenses(filename, offenses)
|
27
|
+
offenses.map do |offense|
|
28
|
+
format_offense(filename, offense)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def format_offense(filename, offense)
|
33
|
+
{
|
34
|
+
description: offense.message,
|
35
|
+
check_name: offense.simple_name,
|
36
|
+
fingerprint: generate_fingerprint(filename, offense),
|
37
|
+
severity: offense.severity,
|
38
|
+
location: {
|
39
|
+
path: filename,
|
40
|
+
lines: {
|
41
|
+
begin: offense.line_number,
|
42
|
+
end: offense.last_line,
|
43
|
+
},
|
44
|
+
},
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def generate_fingerprint(filename, offense)
|
49
|
+
Digest::MD5.hexdigest(
|
50
|
+
"#{offense.simple_name}@#{filename}:#{offense.line_number}:#{offense.last_line}",
|
51
|
+
)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -8,9 +8,14 @@ module ERBLint
|
|
8
8
|
private
|
9
9
|
|
10
10
|
def format_offense(filename, offense)
|
11
|
+
details = "#{offense.message}#{Rainbow(" (not autocorrected)").red if autocorrect}"
|
12
|
+
if show_linter_names
|
13
|
+
details = "[#{offense.simple_name}] " + details
|
14
|
+
end
|
15
|
+
|
11
16
|
<<~EOF
|
12
17
|
|
13
|
-
#{
|
18
|
+
#{details}
|
14
19
|
In file: #{filename}:#{offense.line_number}
|
15
20
|
EOF
|
16
21
|
end
|
data/lib/erb_lint/runner.rb
CHANGED
@@ -57,7 +57,7 @@ module ERBLint
|
|
57
57
|
if no_unused_disable_enabled? && enable_inline_configs?
|
58
58
|
@no_unused_disable = ERBLint::Linters::NoUnusedDisable.new(
|
59
59
|
@file_loader,
|
60
|
-
@config.for_linter(ERBLint::Linters::NoUnusedDisable)
|
60
|
+
@config.for_linter(ERBLint::Linters::NoUnusedDisable),
|
61
61
|
)
|
62
62
|
@no_unused_disable.run(processed_source, @offenses)
|
63
63
|
@offenses.concat(@no_unused_disable.offenses)
|
@@ -60,7 +60,7 @@ module ERBLint
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def inspect
|
63
|
-
"
|
63
|
+
"#<#{self.class.name} type=#{type.inspect} nodes=#{nodes.inspect}>"
|
64
64
|
end
|
65
65
|
|
66
66
|
def &(other)
|
@@ -102,7 +102,7 @@ module ERBLint
|
|
102
102
|
node.type,
|
103
103
|
extract_map_locations(node)
|
104
104
|
.map { |loc| find_entry(loc) }
|
105
|
-
.compact.map(&:node)
|
105
|
+
.compact.map(&:node),
|
106
106
|
)
|
107
107
|
end
|
108
108
|
|
@@ -111,7 +111,7 @@ module ERBLint
|
|
111
111
|
:begin,
|
112
112
|
(extract_map_locations(node) + rescue_locations(node))
|
113
113
|
.map { |loc| find_entry(loc) }
|
114
|
-
.compact.map(&:node)
|
114
|
+
.compact.map(&:node),
|
115
115
|
)
|
116
116
|
end
|
117
117
|
|
@@ -120,7 +120,7 @@ module ERBLint
|
|
120
120
|
node.type,
|
121
121
|
(extract_map_locations(node) + when_locations(node))
|
122
122
|
.map { |loc| find_entry(loc) }
|
123
|
-
.compact.map(&:node)
|
123
|
+
.compact.map(&:node),
|
124
124
|
)
|
125
125
|
end
|
126
126
|
|
@@ -42,15 +42,12 @@ module ERBLint
|
|
42
42
|
range = to_range(node_or_range)
|
43
43
|
|
44
44
|
@processed_source.to_source_range(
|
45
|
-
bound(@offset + range.begin_pos)..bound(@offset + (range.end_pos - 1))
|
45
|
+
bound(@offset + range.begin_pos)..bound(@offset + (range.end_pos - 1)),
|
46
46
|
)
|
47
47
|
end
|
48
48
|
|
49
49
|
def bound(pos)
|
50
|
-
|
51
|
-
[pos, @bound_range.min].max,
|
52
|
-
@bound_range.max,
|
53
|
-
].min
|
50
|
+
pos.clamp(@bound_range.min, @bound_range.max)
|
54
51
|
end
|
55
52
|
|
56
53
|
private
|
@@ -5,8 +5,14 @@ module ERBLint
|
|
5
5
|
module SeverityLevels
|
6
6
|
SEVERITY_NAMES = [:info, :refactor, :convention, :warning, :error, :fatal].freeze
|
7
7
|
|
8
|
-
SEVERITY_CODE_TABLE = {
|
9
|
-
|
8
|
+
SEVERITY_CODE_TABLE = {
|
9
|
+
I: :info,
|
10
|
+
R: :refactor,
|
11
|
+
C: :convention,
|
12
|
+
W: :warning,
|
13
|
+
E: :error,
|
14
|
+
F: :fatal,
|
15
|
+
}.freeze
|
10
16
|
|
11
17
|
def severity_level_for_name(name)
|
12
18
|
SEVERITY_NAMES.index(name || :error) + 1
|
data/lib/erb_lint/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: erb_lint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Chan
|
8
8
|
- Shopify Developers
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-08-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -73,14 +73,14 @@ dependencies:
|
|
73
73
|
requirements:
|
74
74
|
- - ">="
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: '
|
76
|
+
version: '1'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: '
|
83
|
+
version: '1'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: smart_properties
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -182,6 +182,7 @@ files:
|
|
182
182
|
- lib/erb_lint/processed_source.rb
|
183
183
|
- lib/erb_lint/reporter.rb
|
184
184
|
- lib/erb_lint/reporters/compact_reporter.rb
|
185
|
+
- lib/erb_lint/reporters/gitlab_reporter.rb
|
185
186
|
- lib/erb_lint/reporters/json_reporter.rb
|
186
187
|
- lib/erb_lint/reporters/junit_reporter.rb
|
187
188
|
- lib/erb_lint/reporters/multiline_reporter.rb
|
@@ -200,7 +201,7 @@ licenses:
|
|
200
201
|
- MIT
|
201
202
|
metadata:
|
202
203
|
allowed_push_host: https://rubygems.org
|
203
|
-
post_install_message:
|
204
|
+
post_install_message:
|
204
205
|
rdoc_options: []
|
205
206
|
require_paths:
|
206
207
|
- lib
|
@@ -215,8 +216,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
215
216
|
- !ruby/object:Gem::Version
|
216
217
|
version: '0'
|
217
218
|
requirements: []
|
218
|
-
rubygems_version: 3.
|
219
|
-
signing_key:
|
219
|
+
rubygems_version: 3.5.16
|
220
|
+
signing_key:
|
220
221
|
specification_version: 4
|
221
222
|
summary: ERB lint tool
|
222
223
|
test_files: []
|