erb_lint 0.1.0 → 0.1.3
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/exe/erblint +1 -1
- data/lib/erb_lint/all.rb +15 -15
- data/lib/erb_lint/cli.rb +20 -23
- data/lib/erb_lint/corrector.rb +1 -1
- data/lib/erb_lint/linter.rb +4 -4
- data/lib/erb_lint/linter_config.rb +10 -5
- data/lib/erb_lint/linter_registry.rb +2 -2
- data/lib/erb_lint/linters/allowed_script_type.rb +9 -8
- data/lib/erb_lint/linters/closing_erb_tag_indent.rb +2 -2
- data/lib/erb_lint/linters/deprecated_classes.rb +8 -7
- data/lib/erb_lint/linters/erb_safety.rb +2 -2
- data/lib/erb_lint/linters/extra_newline.rb +1 -1
- data/lib/erb_lint/linters/final_newline.rb +2 -2
- data/lib/erb_lint/linters/hard_coded_string.rb +39 -36
- data/lib/erb_lint/linters/no_javascript_tag_helper.rb +11 -9
- data/lib/erb_lint/linters/partial_instance_variable.rb +1 -1
- data/lib/erb_lint/linters/require_input_autocomplete.rb +8 -10
- data/lib/erb_lint/linters/require_script_nonce.rb +10 -10
- data/lib/erb_lint/linters/right_trim.rb +1 -1
- data/lib/erb_lint/linters/rubocop.rb +12 -10
- data/lib/erb_lint/linters/rubocop_text.rb +1 -1
- data/lib/erb_lint/linters/self_closing_tag.rb +6 -7
- data/lib/erb_lint/linters/space_around_erb_tag.rb +8 -7
- data/lib/erb_lint/linters/space_in_html_tag.rb +7 -6
- 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 +1 -0
- data/lib/erb_lint/reporter.rb +4 -2
- data/lib/erb_lint/reporters/compact_reporter.rb +9 -2
- data/lib/erb_lint/reporters/multiline_reporter.rb +2 -1
- data/lib/erb_lint/runner.rb +1 -1
- data/lib/erb_lint/runner_config.rb +8 -7
- data/lib/erb_lint/runner_config_resolver.rb +5 -4
- data/lib/erb_lint/stats.rb +10 -6
- data/lib/erb_lint/utils/block_map.rb +3 -2
- data/lib/erb_lint/utils/offset_corrector.rb +2 -2
- data/lib/erb_lint/utils/ruby_to_erb.rb +6 -5
- data/lib/erb_lint/utils/severity_levels.rb +2 -2
- data/lib/erb_lint/version.rb +1 -1
- data/lib/erb_lint.rb +1 -1
- metadata +17 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84ee5b7d05405468648ea7ea174c2f8f57ec1e56490873e1e89e1e9f618df585
|
4
|
+
data.tar.gz: 3f7db38955673a6218517c8a031c97a9aed5a03fe8a1a9ed11c631cc8aa920f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e466a9178358d9400fa7a38cda19d1263efecaa1729391b1eea5c9dae2cf928686f97c5d84a0df85ba6774465f415ef94ec628cda8cc38834f2983fe525f41e7
|
7
|
+
data.tar.gz: 1f7cc9b5a8994d9378f70085d69e0012baa78c0da7896b366dfd32f894f05b4c3978c831eab31f6b209c9c4a42bfe36dcf0bb413a872a91a2bb22bfc79effc16
|
data/exe/erblint
CHANGED
data/lib/erb_lint/all.rb
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "rubocop"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
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
17
|
|
18
18
|
# Load linters
|
19
|
-
Dir[File.expand_path(
|
19
|
+
Dir[File.expand_path("linters/**/*.rb", __dir__)].each do |file|
|
20
20
|
require file
|
21
21
|
end
|
22
22
|
|
23
23
|
# Load reporters
|
24
|
-
Dir[File.expand_path(
|
24
|
+
Dir[File.expand_path("reporters/**/*.rb", __dir__)].each do |file|
|
25
25
|
require file
|
26
26
|
end
|
data/lib/erb_lint/cli.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
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"
|
11
11
|
|
12
12
|
module ERBLint
|
13
13
|
class CLI
|
14
14
|
include Utils::SeverityLevels
|
15
15
|
|
16
|
-
DEFAULT_CONFIG_FILENAME =
|
16
|
+
DEFAULT_CONFIG_FILENAME = ".erb-lint.yml"
|
17
17
|
DEFAULT_LINT_ALL_GLOB = "**/*.html{+*,}.erb"
|
18
18
|
|
19
19
|
class ExitWithFailure < RuntimeError; end
|
@@ -43,13 +43,14 @@ module ERBLint
|
|
43
43
|
ensure_files_exist(lint_files)
|
44
44
|
|
45
45
|
if enabled_linter_classes.empty?
|
46
|
-
failure!(
|
46
|
+
failure!("no linter available with current configuration")
|
47
47
|
end
|
48
48
|
|
49
49
|
@options[:format] ||= :multiline
|
50
50
|
@options[:fail_level] ||= severity_level_for_name(:refactor)
|
51
51
|
@stats.files = lint_files.size
|
52
52
|
@stats.linters = enabled_linter_classes.size
|
53
|
+
@stats.autocorrectable_linters = enabled_linter_classes.count(&:support_autocorrect?)
|
53
54
|
|
54
55
|
reporter = Reporter.create_reporter(@options[:format], @stats, autocorrect?)
|
55
56
|
reporter.preview
|
@@ -145,7 +146,7 @@ module ERBLint
|
|
145
146
|
|
146
147
|
def correct(processed_source, offenses)
|
147
148
|
corrector = ERBLint::Corrector.new(processed_source, offenses)
|
148
|
-
failure!(corrector.diagnostics.join(
|
149
|
+
failure!(corrector.diagnostics.join(", ")) if corrector.diagnostics.any?
|
149
150
|
corrector
|
150
151
|
end
|
151
152
|
|
@@ -183,7 +184,7 @@ module ERBLint
|
|
183
184
|
else
|
184
185
|
@files
|
185
186
|
.map { |f| Dir.exist?(f) ? Dir[File.join(f, glob)] : f }
|
186
|
-
.map { |f| f.include?(
|
187
|
+
.map { |f| f.include?("*") ? Dir[f] : f }
|
187
188
|
.flatten
|
188
189
|
.map { |f| File.expand_path(f, Dir.pwd) }
|
189
190
|
.select { |filename| !excluded?(filename) }
|
@@ -232,22 +233,18 @@ module ERBLint
|
|
232
233
|
|
233
234
|
def enabled_linter_classes
|
234
235
|
@enabled_linter_classes ||= ERBLint::LinterRegistry.linters
|
235
|
-
.select { |klass|
|
236
|
-
end
|
237
|
-
|
238
|
-
def linter_can_run?(klass)
|
239
|
-
!autocorrect? || klass.support_autocorrect?
|
236
|
+
.select { |klass| enabled_linter_names.include?(klass.simple_name.underscore) }
|
240
237
|
end
|
241
238
|
|
242
239
|
def relative_filename(filename)
|
243
|
-
filename.sub("#{File.expand_path(
|
240
|
+
filename.sub("#{File.expand_path(".", Dir.pwd)}/", "")
|
244
241
|
end
|
245
242
|
|
246
243
|
def runner_config_override
|
247
244
|
RunnerConfig.new(
|
248
245
|
linters: {}.tap do |linters|
|
249
246
|
ERBLint::LinterRegistry.linters.map do |klass|
|
250
|
-
linters[klass.simple_name] = {
|
247
|
+
linters[klass.simple_name] = { "enabled" => enabled_linter_classes.include?(klass) }
|
251
248
|
end
|
252
249
|
end
|
253
250
|
)
|
@@ -283,10 +280,10 @@ module ERBLint
|
|
283
280
|
end
|
284
281
|
|
285
282
|
opts.on("--enable-linters LINTER[,LINTER,...]", Array,
|
286
|
-
"Only use specified linter", "Known linters are: #{known_linter_names.join(
|
283
|
+
"Only use specified linter", "Known linters are: #{known_linter_names.join(", ")}") do |linters|
|
287
284
|
linters.each do |linter|
|
288
285
|
unless known_linter_names.include?(linter)
|
289
|
-
failure!("#{linter}: not a valid linter name (#{known_linter_names.join(
|
286
|
+
failure!("#{linter}: not a valid linter name (#{known_linter_names.join(", ")})")
|
290
287
|
end
|
291
288
|
end
|
292
289
|
@options[:enabled_linters] = linters
|
@@ -296,7 +293,7 @@ module ERBLint
|
|
296
293
|
parsed_severity = SEVERITY_CODE_TABLE[level.upcase.to_sym] || (SEVERITY_NAMES & [level.downcase]).first
|
297
294
|
|
298
295
|
if parsed_severity.nil?
|
299
|
-
failure!("#{level}: not a valid failure level (#{SEVERITY_NAMES.join(
|
296
|
+
failure!("#{level}: not a valid failure level (#{SEVERITY_NAMES.join(", ")})")
|
300
297
|
end
|
301
298
|
@options[:fail_level] = severity_level_for_name(parsed_severity)
|
302
299
|
end
|
@@ -325,7 +322,7 @@ module ERBLint
|
|
325
322
|
|
326
323
|
def format_options_help
|
327
324
|
"Report offenses in the given format: "\
|
328
|
-
|
325
|
+
"(#{Reporter.available_formats.join(", ")}) (default: multiline)"
|
329
326
|
end
|
330
327
|
|
331
328
|
def invalid_format_error_message(given_format)
|
data/lib/erb_lint/corrector.rb
CHANGED
data/lib/erb_lint/linter.rb
CHANGED
@@ -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?(
|
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
|
@@ -46,7 +46,7 @@ module ERBLint
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def excludes_file?(filename)
|
49
|
-
@config.excludes_file?(filename)
|
49
|
+
@config.excludes_file?(filename, @file_loader.base_path)
|
50
50
|
end
|
51
51
|
|
52
52
|
def run(_processed_source)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
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
|
|
@@ -51,9 +53,12 @@ module ERBLint
|
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
54
|
-
def excludes_file?(
|
56
|
+
def excludes_file?(absolute_filename, base_path)
|
55
57
|
exclude.any? do |path|
|
56
|
-
File.fnmatch?(path,
|
58
|
+
return true if File.fnmatch?(path, absolute_filename)
|
59
|
+
|
60
|
+
relative_path = absolute_filename.delete_prefix("#{base_path}/")
|
61
|
+
File.fnmatch?(path, relative_path)
|
57
62
|
end
|
58
63
|
end
|
59
64
|
end
|
@@ -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 =
|
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,
|
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
|
4
|
-
require
|
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: -> { [
|
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 ==
|
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
|
-
|
34
|
+
"Instead, move javascript code into a static file."
|
35
35
|
)
|
36
36
|
next
|
37
37
|
end
|
38
38
|
|
39
|
-
type_attribute = tag.attributes[
|
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
|
-
|
54
|
-
|
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
|
-
|
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
|
4
|
-
require
|
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[
|
60
|
+
class_value = tag.attributes["class"]&.value
|
61
61
|
next unless class_value
|
62
|
-
|
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[
|
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 ==
|
84
|
+
tags(processed_source).select { |tag| tag.name == "script" }
|
84
85
|
end
|
85
86
|
|
86
87
|
def tags(processed_source)
|
@@ -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
|
-
|
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
|
-
|
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
|
4
|
-
require
|
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,37 +14,37 @@ module ERBLint
|
|
13
14
|
MissingCorrector = Class.new(StandardError)
|
14
15
|
MissingI18nLoadPath = Class.new(StandardError)
|
15
16
|
|
16
|
-
ALLOWED_CORRECTORS =
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
&
|
24
|
-
&
|
25
|
-
&
|
26
|
-
&
|
27
|
-
&
|
28
|
-
&
|
29
|
-
&
|
30
|
-
&
|
31
|
-
&
|
32
|
-
&
|
33
|
-
&
|
34
|
-
&
|
35
|
-
&
|
36
|
-
&
|
37
|
-
&
|
38
|
-
&
|
39
|
-
&
|
40
|
-
&
|
41
|
-
&
|
42
|
-
)
|
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
|
+
" ",
|
22
|
+
"&",
|
23
|
+
"<",
|
24
|
+
">",
|
25
|
+
""",
|
26
|
+
"©",
|
27
|
+
"®",
|
28
|
+
"™",
|
29
|
+
"…",
|
30
|
+
"—",
|
31
|
+
"•",
|
32
|
+
"“",
|
33
|
+
"”",
|
34
|
+
"‘",
|
35
|
+
"’",
|
36
|
+
"←",
|
37
|
+
"→",
|
38
|
+
"↓",
|
39
|
+
"↑",
|
40
|
+
" ",
|
41
|
+
" ",
|
42
|
+
" ",
|
43
|
+
])
|
43
44
|
|
44
45
|
class ConfigSchema < LinterConfig
|
45
46
|
property :corrector, accepts: Hash, required: false, default: -> { {} }
|
46
|
-
property :i18n_load_path, accepts: String, required: false, default:
|
47
|
+
property :i18n_load_path, accepts: String, required: false, default: ""
|
47
48
|
end
|
48
49
|
self.config_schema = ConfigSchema
|
49
50
|
|
@@ -83,9 +84,10 @@ module ERBLint
|
|
83
84
|
string = offense.source_range.source
|
84
85
|
return unless (klass = load_corrector)
|
85
86
|
return unless string.strip.length > 1
|
87
|
+
|
86
88
|
node = ::RuboCop::AST::StrNode.new(:str, [string])
|
87
89
|
corrector = klass.new(node, processed_source.filename, corrector_i18n_load_path, offense.source_range)
|
88
|
-
corrector.autocorrect(tag_start:
|
90
|
+
corrector.autocorrect(tag_start: "<%= ", tag_end: " %>")
|
89
91
|
rescue MissingCorrector, MissingI18nLoadPath
|
90
92
|
nil
|
91
93
|
end
|
@@ -93,20 +95,21 @@ module ERBLint
|
|
93
95
|
private
|
94
96
|
|
95
97
|
def check_string?(str)
|
96
|
-
string = str.gsub(/\s*/,
|
97
|
-
string.length > 1 && !
|
98
|
+
string = str.gsub(/\s*/, "")
|
99
|
+
string.length > 1 && !TEXT_NOT_ALLOWED.include?(string)
|
98
100
|
end
|
99
101
|
|
100
102
|
def load_corrector
|
101
|
-
corrector_name = @config[
|
103
|
+
corrector_name = @config["corrector"].fetch("name") { raise MissingCorrector }
|
102
104
|
raise ForbiddenCorrector unless ALLOWED_CORRECTORS.include?(corrector_name)
|
103
|
-
|
105
|
+
|
106
|
+
require @config["corrector"].fetch("path") { raise MissingCorrector }
|
104
107
|
|
105
108
|
corrector_name.safe_constantize
|
106
109
|
end
|
107
110
|
|
108
111
|
def corrector_i18n_load_path
|
109
|
-
@config[
|
112
|
+
@config["corrector"].fetch("i18n_load_path") { raise MissingI18nLoadPath }
|
110
113
|
end
|
111
114
|
|
112
115
|
def non_text_tag?(processed_source, text_node)
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
3
|
+
require "better_html"
|
4
|
+
require "better_html/ast/node"
|
5
|
+
require "better_html/test_helper/ruby_node"
|
6
|
+
require "erb_lint/utils/block_map"
|
7
|
+
require "erb_lint/utils/ruby_to_erb"
|
8
8
|
|
9
9
|
module ERBLint
|
10
10
|
module Linters
|
@@ -21,7 +21,8 @@ module ERBLint
|
|
21
21
|
parser.ast.descendants(:erb).each do |erb_node|
|
22
22
|
indicator_node, _, code_node, _ = *erb_node
|
23
23
|
indicator = indicator_node&.loc&.source
|
24
|
-
next if indicator ==
|
24
|
+
next if indicator == "#"
|
25
|
+
|
25
26
|
source = code_node.loc.source
|
26
27
|
|
27
28
|
ruby_node =
|
@@ -31,13 +32,14 @@ module ERBLint
|
|
31
32
|
nil
|
32
33
|
end
|
33
34
|
next unless ruby_node
|
35
|
+
|
34
36
|
send_node = ruby_node.descendants(:send).first
|
35
37
|
next unless send_node&.method_name?(:javascript_tag)
|
36
38
|
|
37
39
|
add_offense(
|
38
40
|
erb_node.loc,
|
39
41
|
"Avoid using 'javascript_tag do' as it confuses tests "\
|
40
|
-
|
42
|
+
"that validate html, use inline <script> instead",
|
41
43
|
[erb_node, send_node]
|
42
44
|
)
|
43
45
|
end
|
@@ -63,10 +65,10 @@ module ERBLint
|
|
63
65
|
return unless (0..2).cover?(argument_nodes.size)
|
64
66
|
|
65
67
|
script_content = unless argument_nodes.first&.type?(:hash)
|
66
|
-
Utils::RubyToERB.ruby_to_erb(argument_nodes.first,
|
68
|
+
Utils::RubyToERB.ruby_to_erb(argument_nodes.first, "==")
|
67
69
|
end
|
68
70
|
arguments = if argument_nodes.last&.type?(:hash)
|
69
|
-
|
71
|
+
" " + Utils::RubyToERB.html_options_to_tag_attributes(argument_nodes.last)
|
70
72
|
end
|
71
73
|
|
72
74
|
return if end_node && script_content
|
@@ -8,7 +8,7 @@ module ERBLint
|
|
8
8
|
|
9
9
|
def run(processed_source)
|
10
10
|
instance_variable_regex = /\s@\w+/
|
11
|
-
return unless processed_source.filename.match?(
|
11
|
+
return unless processed_source.filename.match?(%r{(\A|.*/)_[^/\s]*\.html\.erb\z}) &&
|
12
12
|
processed_source.file_content.match?(instance_variable_regex)
|
13
13
|
|
14
14
|
add_offense(
|