erb_lint 0.0.21 → 0.0.22
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/erb_lint/cli.rb +13 -11
- data/lib/erb_lint/linter.rb +12 -1
- data/lib/erb_lint/linters/allowed_script_type.rb +32 -38
- data/lib/erb_lint/linters/closing_erb_tag_indent.rb +8 -11
- data/lib/erb_lint/linters/deprecated_classes.rb +8 -14
- data/lib/erb_lint/linters/erb_safety.rb +4 -9
- data/lib/erb_lint/linters/extra_newline.rb +5 -11
- data/lib/erb_lint/linters/final_newline.rb +10 -13
- data/lib/erb_lint/linters/hard_coded_string.rb +14 -10
- data/lib/erb_lint/linters/no_javascript_tag_helper.rb +6 -15
- data/lib/erb_lint/linters/parser_errors.rb +4 -5
- data/lib/erb_lint/linters/right_trim.rb +8 -11
- data/lib/erb_lint/linters/rubocop.rb +17 -37
- data/lib/erb_lint/linters/self_closing_tag.rb +6 -8
- data/lib/erb_lint/linters/space_around_erb_tag.rb +37 -43
- data/lib/erb_lint/linters/space_in_html_tag.rb +31 -39
- data/lib/erb_lint/linters/space_indentation.rb +4 -5
- data/lib/erb_lint/linters/trailing_whitespace.rb +4 -5
- data/lib/erb_lint/offense.rb +1 -1
- data/lib/erb_lint/processed_source.rb +8 -3
- data/lib/erb_lint/runner.rb +10 -3
- data/lib/erb_lint/utils/block_map.rb +3 -3
- data/lib/erb_lint/utils/offset_corrector.rb +3 -4
- data/lib/erb_lint/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ec3e8e2ac9c73109d17f77b2e93a43e12f8c89e
|
4
|
+
data.tar.gz: 116d80b17dcf0ff05f356dd21fbc34f3f3af4da6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 300e58e388b3d6904b750bfeb2ea2576490204191a5160cd3e8929421ca47804b114f706c8cd3be96b2e22a27d8cef0a3d1970de18c4b54ed9611b16f2052874
|
7
|
+
data.tar.gz: 9a02fefe7fecd0af7cba69ba7c3777a20c51af7c0621c6b3471538fad81a510806935e8a142b4233cafe96772add6960f8d7935668a7800c88db40da5c1b518a
|
data/lib/erb_lint/cli.rb
CHANGED
@@ -51,10 +51,9 @@ module ERBLint
|
|
51
51
|
"#{enabled_linter_classes.size} #{'autocorrectable ' if autocorrect?}linters..."
|
52
52
|
puts
|
53
53
|
|
54
|
-
runner = ERBLint::Runner.new(file_loader, @config)
|
55
54
|
lint_files.each do |filename|
|
56
55
|
begin
|
57
|
-
run_with_corrections(
|
56
|
+
run_with_corrections(filename)
|
58
57
|
rescue => e
|
59
58
|
puts "Exception occured when processing: #{relative_filename(filename)}"
|
60
59
|
puts e.message
|
@@ -64,8 +63,9 @@ module ERBLint
|
|
64
63
|
end
|
65
64
|
|
66
65
|
if @stats.corrected > 0
|
67
|
-
|
68
|
-
|
66
|
+
corrected_found_diff = @stats.found - @stats.corrected
|
67
|
+
if corrected_found_diff > 0
|
68
|
+
warn "#{@stats.corrected} error(s) corrected and #{corrected_found_diff} error(s) remaining in ERB files".red
|
69
69
|
else
|
70
70
|
puts "#{@stats.corrected} error(s) corrected in ERB files".green
|
71
71
|
end
|
@@ -93,16 +93,17 @@ module ERBLint
|
|
93
93
|
@options[:autocorrect]
|
94
94
|
end
|
95
95
|
|
96
|
-
def run_with_corrections(
|
96
|
+
def run_with_corrections(filename)
|
97
97
|
file_content = File.read(filename)
|
98
|
-
|
98
|
+
|
99
|
+
runner = ERBLint::Runner.new(file_loader, @config)
|
99
100
|
|
100
101
|
7.times do
|
101
102
|
processed_source = ERBLint::ProcessedSource.new(filename, file_content)
|
102
|
-
|
103
|
-
break unless autocorrect? && offenses.any?
|
103
|
+
runner.run(processed_source)
|
104
|
+
break unless autocorrect? && runner.offenses.any?
|
104
105
|
|
105
|
-
corrector = correct(processed_source, offenses)
|
106
|
+
corrector = correct(processed_source, runner.offenses)
|
106
107
|
break if corrector.corrections.empty?
|
107
108
|
break if processed_source.file_content == corrector.corrected_content
|
108
109
|
|
@@ -113,10 +114,11 @@ module ERBLint
|
|
113
114
|
end
|
114
115
|
|
115
116
|
file_content = corrector.corrected_content
|
117
|
+
runner.clear_offenses
|
116
118
|
end
|
117
119
|
|
118
|
-
@stats.found += offenses.size
|
119
|
-
offenses.each do |offense|
|
120
|
+
@stats.found += runner.offenses.size
|
121
|
+
runner.offenses.each do |offense|
|
120
122
|
puts <<~EOF
|
121
123
|
#{offense.message}#{' (not autocorrected)'.red if autocorrect?}
|
122
124
|
In file: #{relative_filename(filename)}:#{offense.line_range.begin}
|
data/lib/erb_lint/linter.rb
CHANGED
@@ -29,12 +29,15 @@ module ERBLint
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
attr_reader :offenses
|
33
|
+
|
32
34
|
# Must be implemented by the concrete inheriting class.
|
33
35
|
def initialize(file_loader, config)
|
34
36
|
@file_loader = file_loader
|
35
37
|
@config = config
|
36
38
|
raise ArgumentError, "expect `config` to be #{self.class.config_schema} instance, "\
|
37
39
|
"not #{config.class}" unless config.is_a?(self.class.config_schema)
|
40
|
+
@offenses = []
|
38
41
|
end
|
39
42
|
|
40
43
|
def enabled?
|
@@ -45,8 +48,16 @@ module ERBLint
|
|
45
48
|
@config.excludes_file?(filename)
|
46
49
|
end
|
47
50
|
|
48
|
-
def
|
51
|
+
def run(_processed_source)
|
49
52
|
raise NotImplementedError, "must implement ##{__method__}"
|
50
53
|
end
|
54
|
+
|
55
|
+
def add_offense(source_range, message, context = nil)
|
56
|
+
@offenses << Offense.new(self, source_range, message, context)
|
57
|
+
end
|
58
|
+
|
59
|
+
def clear_offenses
|
60
|
+
@offenses = []
|
61
|
+
end
|
51
62
|
end
|
52
63
|
end
|
@@ -19,58 +19,52 @@ module ERBLint
|
|
19
19
|
end
|
20
20
|
self.config_schema = ConfigSchema
|
21
21
|
|
22
|
-
def
|
22
|
+
def run(processed_source)
|
23
23
|
parser = processed_source.parser
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
next unless tag.name == 'script'
|
24
|
+
parser.nodes_with_type(:tag).each do |tag_node|
|
25
|
+
tag = BetterHtml::Tree::Tag.from_node(tag_node)
|
26
|
+
next if tag.closing?
|
27
|
+
next unless tag.name == 'script'
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
29
|
+
if @config.disallow_inline_scripts?
|
30
|
+
name_node = tag_node.to_a[1]
|
31
|
+
add_offense(
|
32
|
+
name_node.loc,
|
33
|
+
"Avoid using inline `<script>` tags altogether. "\
|
34
|
+
"Instead, move javascript code into a static file."
|
35
|
+
)
|
36
|
+
next
|
37
|
+
end
|
40
38
|
|
41
|
-
|
42
|
-
|
39
|
+
type_attribute = tag.attributes['type']
|
40
|
+
type_present = type_attribute.present? && type_attribute.value_node.present?
|
43
41
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
"#{' (or no type attribute)' if @config.allow_blank?}."
|
59
|
-
)
|
60
|
-
end
|
42
|
+
if !type_present && !@config.allow_blank?
|
43
|
+
name_node = tag_node.to_a[1]
|
44
|
+
add_offense(
|
45
|
+
name_node.loc,
|
46
|
+
"Missing a `type=\"text/javascript\"` attribute to `<script>` tag.",
|
47
|
+
[type_attribute]
|
48
|
+
)
|
49
|
+
elsif type_present && !@config.allowed_types.include?(type_attribute.value)
|
50
|
+
add_offense(
|
51
|
+
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?}."
|
55
|
+
)
|
61
56
|
end
|
62
57
|
end
|
63
58
|
end
|
64
59
|
|
65
|
-
def autocorrect(
|
60
|
+
def autocorrect(_processed_source, offense)
|
66
61
|
return unless offense.context
|
67
62
|
lambda do |corrector|
|
68
63
|
type_attribute, = *offense.context
|
69
64
|
if type_attribute.nil?
|
70
65
|
corrector.insert_after(offense.source_range, ' type="text/javascript"')
|
71
66
|
elsif !type_attribute.value.present?
|
72
|
-
|
73
|
-
corrector.replace(range, 'type="text/javascript"')
|
67
|
+
corrector.replace(type_attribute.node.loc, 'type="text/javascript"')
|
74
68
|
end
|
75
69
|
end
|
76
70
|
end
|
@@ -10,8 +10,8 @@ module ERBLint
|
|
10
10
|
START_SPACES = /\A([[:space:]]*)/m
|
11
11
|
END_SPACES = /([[:space:]]*)\z/m
|
12
12
|
|
13
|
-
def
|
14
|
-
processed_source.ast.descendants(:erb).
|
13
|
+
def run(processed_source)
|
14
|
+
processed_source.ast.descendants(:erb).each do |erb_node|
|
15
15
|
_, _, code_node, = *erb_node
|
16
16
|
code = code_node.children.first
|
17
17
|
|
@@ -22,25 +22,22 @@ module ERBLint
|
|
22
22
|
end_with_newline = end_spaces.include?("\n")
|
23
23
|
|
24
24
|
if !start_with_newline && end_with_newline
|
25
|
-
|
26
|
-
|
27
|
-
processed_source.to_source_range(code_node.loc.stop - end_spaces.size + 1, code_node.loc.stop),
|
25
|
+
add_offense(
|
26
|
+
code_node.loc.end.adjust(begin_pos: -end_spaces.size),
|
28
27
|
"Remove newline before `%>` to match start of tag.",
|
29
28
|
' '
|
30
29
|
)
|
31
30
|
elsif start_with_newline && !end_with_newline
|
32
|
-
|
33
|
-
|
34
|
-
processed_source.to_source_range(code_node.loc.stop, code_node.loc.stop),
|
31
|
+
add_offense(
|
32
|
+
code_node.loc.end.adjust(begin_pos: -end_spaces.size),
|
35
33
|
"Insert newline before `%>` to match start of tag.",
|
36
34
|
"\n"
|
37
35
|
)
|
38
36
|
elsif start_with_newline && end_with_newline
|
39
37
|
current_indent = end_spaces.split("\n", -1).last
|
40
38
|
if erb_node.loc.column != current_indent.size
|
41
|
-
|
42
|
-
|
43
|
-
processed_source.to_source_range(code_node.loc.stop - current_indent.size + 1, code_node.loc.stop),
|
39
|
+
add_offense(
|
40
|
+
code_node.loc.end.adjust(begin_pos: -current_indent.size),
|
44
41
|
"Indent `%>` on column #{erb_node.loc.column} to match start of tag.",
|
45
42
|
' ' * erb_node.loc.column
|
46
43
|
)
|
@@ -29,7 +29,7 @@ module ERBLint
|
|
29
29
|
@addendum = @config.addendum
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
32
|
+
def run(processed_source)
|
33
33
|
process_nested_offenses(
|
34
34
|
source: processed_source,
|
35
35
|
offset: 0,
|
@@ -40,23 +40,18 @@ module ERBLint
|
|
40
40
|
private
|
41
41
|
|
42
42
|
def process_nested_offenses(source:, offset:, parent_source:)
|
43
|
-
offenses = []
|
44
43
|
class_name_with_loc(source).each do |class_name, loc|
|
45
|
-
range = parent_source.to_source_range(
|
46
|
-
|
47
|
-
offset + loc.stop
|
48
|
-
)
|
49
|
-
offenses += generate_errors(class_name, range)
|
44
|
+
range = parent_source.to_source_range(loc).offset(offset)
|
45
|
+
generate_offenses(class_name, range)
|
50
46
|
end
|
51
47
|
text_tags_content(source).each do |content_node|
|
52
48
|
sub_source = ProcessedSource.new(source.filename, content_node.loc.source)
|
53
|
-
|
49
|
+
process_nested_offenses(
|
54
50
|
source: sub_source,
|
55
|
-
offset: offset + content_node.loc.
|
51
|
+
offset: offset + content_node.loc.begin_pos,
|
56
52
|
parent_source: parent_source
|
57
53
|
)
|
58
54
|
end
|
59
|
-
offenses
|
60
55
|
end
|
61
56
|
|
62
57
|
def class_name_with_loc(processed_source)
|
@@ -96,13 +91,12 @@ module ERBLint
|
|
96
91
|
processed_source.parser.nodes_with_type(:tag)
|
97
92
|
end
|
98
93
|
|
99
|
-
def
|
100
|
-
violated_rules(class_name).
|
94
|
+
def generate_offenses(class_name, range)
|
95
|
+
violated_rules(class_name).each do |violated_rule|
|
101
96
|
suggestion = " #{violated_rule[:suggestion]}".rstrip
|
102
97
|
message = "Deprecated class `%s` detected matching the pattern `%s`.%s #{@addendum}".strip
|
103
98
|
|
104
|
-
|
105
|
-
self,
|
99
|
+
add_offense(
|
106
100
|
range,
|
107
101
|
format(message, class_name, violated_rule[:class_expr], suggestion)
|
108
102
|
)
|
@@ -20,21 +20,16 @@ module ERBLint
|
|
20
20
|
@config_filename = @config.better_html_config
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
parser = BetterHtml::Parser.new(processed_source.file_content, template_language: :html)
|
27
|
-
testers_for(parser).each do |tester|
|
23
|
+
def run(processed_source)
|
24
|
+
testers_for(processed_source.parser).each do |tester|
|
28
25
|
tester.validate
|
29
26
|
tester.errors.each do |error|
|
30
|
-
|
31
|
-
|
32
|
-
processed_source.to_source_range(error.location.start, error.location.stop),
|
27
|
+
add_offense(
|
28
|
+
error.location,
|
33
29
|
error.message
|
34
30
|
)
|
35
31
|
end
|
36
32
|
end
|
37
|
-
offenses
|
38
33
|
end
|
39
34
|
|
40
35
|
private
|
@@ -8,22 +8,16 @@ module ERBLint
|
|
8
8
|
|
9
9
|
EXTRA_NEWLINES = /(\n{3,})/m
|
10
10
|
|
11
|
-
def
|
12
|
-
matches = processed_source.file_content.match(EXTRA_NEWLINES)
|
13
|
-
return [] unless matches
|
11
|
+
def run(processed_source)
|
12
|
+
return unless (matches = processed_source.file_content.match(EXTRA_NEWLINES))
|
14
13
|
|
15
|
-
offenses = []
|
16
14
|
matches.captures.each_index do |index|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
matches.begin(index) + 2,
|
21
|
-
matches.end(index) - 1
|
22
|
-
),
|
15
|
+
add_offense(
|
16
|
+
processed_source
|
17
|
+
.to_source_range((matches.begin(index) + 2)...matches.end(index)),
|
23
18
|
"Extra blank line detected."
|
24
19
|
)
|
25
20
|
end
|
26
|
-
offenses
|
27
21
|
end
|
28
22
|
|
29
23
|
def autocorrect(_processed_source, offense)
|
@@ -16,40 +16,37 @@ module ERBLint
|
|
16
16
|
@new_lines_should_be_present = @config.present?
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
19
|
+
def run(processed_source)
|
20
20
|
file_content = processed_source.file_content
|
21
21
|
|
22
|
-
|
23
|
-
return offenses if file_content.empty?
|
22
|
+
return if file_content.empty?
|
24
23
|
|
25
24
|
match = file_content.match(/(\n+)\z/)
|
26
25
|
final_newline = match&.captures&.first || ""
|
27
26
|
|
28
27
|
if @new_lines_should_be_present && final_newline.size != 1
|
29
28
|
if final_newline.empty?
|
30
|
-
|
31
|
-
|
32
|
-
processed_source.to_source_range(file_content.size, file_content.size - 1),
|
29
|
+
add_offense(
|
30
|
+
processed_source.to_source_range(file_content.size...file_content.size),
|
33
31
|
'Missing a trailing newline at the end of the file.',
|
34
32
|
:insert
|
35
33
|
)
|
36
34
|
else
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
add_offense(
|
36
|
+
processed_source.to_source_range(
|
37
|
+
(file_content.size - final_newline.size + 1)...file_content.size
|
38
|
+
),
|
40
39
|
'Remove multiple trailing newline at the end of the file.',
|
41
40
|
:remove
|
42
41
|
)
|
43
42
|
end
|
44
43
|
elsif !@new_lines_should_be_present && !final_newline.empty?
|
45
|
-
|
46
|
-
|
47
|
-
processed_source.to_source_range(match.begin(0), match.end(0) - 1),
|
44
|
+
add_offense(
|
45
|
+
processed_source.to_source_range(match.begin(0)...match.end(0)),
|
48
46
|
"Remove #{final_newline.size} trailing newline at the end of the file.",
|
49
47
|
:remove
|
50
48
|
)
|
51
49
|
end
|
52
|
-
offenses
|
53
50
|
end
|
54
51
|
|
55
52
|
def autocorrect(_processed_source, offense)
|
@@ -22,24 +22,23 @@ module ERBLint
|
|
22
22
|
end
|
23
23
|
self.config_schema = ConfigSchema
|
24
24
|
|
25
|
-
def
|
25
|
+
def run(processed_source)
|
26
26
|
hardcoded_strings = processed_source.ast.descendants(:text).each_with_object([]) do |text_node, to_check|
|
27
27
|
next if javascript?(processed_source, text_node)
|
28
28
|
|
29
29
|
offended_strings = text_node.to_a.select { |node| relevant_node(node) }
|
30
30
|
offended_strings.each do |offended_string|
|
31
31
|
offended_string.split("\n").each do |str|
|
32
|
-
to_check << [text_node, str] if str
|
32
|
+
to_check << [text_node, str] if check_string?(str)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
hardcoded_strings.compact.
|
38
|
-
|
39
|
-
source_range = processed_source.to_source_range(
|
37
|
+
hardcoded_strings.compact.each do |text_node, offended_str|
|
38
|
+
range = find_range(text_node, offended_str)
|
39
|
+
source_range = processed_source.to_source_range(range)
|
40
40
|
|
41
|
-
|
42
|
-
self,
|
41
|
+
add_offense(
|
43
42
|
source_range,
|
44
43
|
message(source_range.source)
|
45
44
|
)
|
@@ -50,9 +49,9 @@ module ERBLint
|
|
50
49
|
match = node.loc.source.match(Regexp.new(Regexp.quote(str.strip)))
|
51
50
|
return unless match
|
52
51
|
|
53
|
-
range_begin = match.begin(0) + node.loc.
|
54
|
-
range_end = match.end(0) + node.loc.
|
55
|
-
|
52
|
+
range_begin = match.begin(0) + node.loc.begin_pos
|
53
|
+
range_end = match.end(0) + node.loc.begin_pos
|
54
|
+
(range_begin...range_end)
|
56
55
|
end
|
57
56
|
|
58
57
|
def autocorrect(processed_source, offense)
|
@@ -69,6 +68,11 @@ module ERBLint
|
|
69
68
|
|
70
69
|
private
|
71
70
|
|
71
|
+
def check_string?(str)
|
72
|
+
string = str.gsub(/\s*/, '')
|
73
|
+
string.length > 1 && !%w( ).include?(string)
|
74
|
+
end
|
75
|
+
|
72
76
|
def load_corrector
|
73
77
|
corrector_name = @config['corrector'].fetch('name') { raise MissingCorrector }
|
74
78
|
raise ForbiddenCorrector unless ALLOWED_CORRECTORS.include?(corrector_name)
|
@@ -15,9 +15,7 @@ module ERBLint
|
|
15
15
|
end
|
16
16
|
self.config_schema = ConfigSchema
|
17
17
|
|
18
|
-
def
|
19
|
-
offenses = []
|
20
|
-
|
18
|
+
def run(processed_source)
|
21
19
|
parser = processed_source.parser
|
22
20
|
parser.ast.descendants(:erb).each do |erb_node|
|
23
21
|
indicator_node, _, code_node, _ = *erb_node
|
@@ -29,16 +27,13 @@ module ERBLint
|
|
29
27
|
send_node = ruby_node.descendants(:send).first
|
30
28
|
next unless send_node&.method_name?(:javascript_tag)
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
processed_source.to_source_range(erb_node.loc.start, erb_node.loc.stop),
|
30
|
+
add_offense(
|
31
|
+
erb_node.loc,
|
35
32
|
"Avoid using 'javascript_tag do' as it confuses tests "\
|
36
33
|
"that validate html, use inline <script> instead",
|
37
34
|
[erb_node, send_node]
|
38
35
|
)
|
39
36
|
end
|
40
|
-
|
41
|
-
offenses
|
42
37
|
end
|
43
38
|
|
44
39
|
def autocorrect(processed_source, offense)
|
@@ -56,10 +51,6 @@ module ERBLint
|
|
56
51
|
return unless (1..2).cover?(nodes.size)
|
57
52
|
|
58
53
|
begin_node, end_node = nodes
|
59
|
-
begin_range = processed_source
|
60
|
-
.to_source_range(begin_node.loc.start, begin_node.loc.stop)
|
61
|
-
end_range = processed_source
|
62
|
-
.to_source_range(end_node.loc.start, end_node.loc.stop) if end_node
|
63
54
|
|
64
55
|
argument_nodes = send_node.arguments
|
65
56
|
return unless (0..2).cover?(argument_nodes.size)
|
@@ -76,13 +67,13 @@ module ERBLint
|
|
76
67
|
if end_node
|
77
68
|
begin_content = "<script#{arguments}>"
|
78
69
|
begin_content += "\n//<![CDATA[\n" if @config.correction_style == :cdata
|
79
|
-
corrector.replace(
|
70
|
+
corrector.replace(begin_node.loc, begin_content)
|
80
71
|
end_content = "</script>"
|
81
72
|
end_content = "\n//]]>\n" + end_content if @config.correction_style == :cdata
|
82
|
-
corrector.replace(
|
73
|
+
corrector.replace(end_node.loc, end_content)
|
83
74
|
elsif script_content
|
84
75
|
script_content = "\n//<![CDATA[\n#{script_content}\n//]]>\n" if @config.correction_style == :cdata
|
85
|
-
corrector.replace(
|
76
|
+
corrector.replace(begin_node.loc,
|
86
77
|
"<script#{arguments}>#{script_content}</script>")
|
87
78
|
end
|
88
79
|
rescue Utils::RubyToERB::Error, Utils::BlockMap::ParseError
|
@@ -5,11 +5,10 @@ module ERBLint
|
|
5
5
|
class ParserErrors < Linter
|
6
6
|
include LinterRegistry
|
7
7
|
|
8
|
-
def
|
9
|
-
processed_source.parser.parser_errors.
|
10
|
-
|
11
|
-
|
12
|
-
processed_source.to_source_range(error.loc.start, error.loc.stop - 1),
|
8
|
+
def run(processed_source)
|
9
|
+
processed_source.parser.parser_errors.each do |error|
|
10
|
+
add_offense(
|
11
|
+
error.loc,
|
13
12
|
"#{error.message} (at #{error.loc.source})"
|
14
13
|
)
|
15
14
|
end
|
@@ -12,18 +12,15 @@ module ERBLint
|
|
12
12
|
end
|
13
13
|
self.config_schema = ConfigSchema
|
14
14
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
next if trim_node.nil? || trim_node.loc.source == @config.enforced_style
|
15
|
+
def run(processed_source)
|
16
|
+
processed_source.ast.descendants(:erb).each do |erb_node|
|
17
|
+
_, _, _, trim_node = *erb_node
|
18
|
+
next if trim_node.nil? || trim_node.loc.source == @config.enforced_style
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
)
|
26
|
-
end
|
20
|
+
add_offense(
|
21
|
+
trim_node.loc,
|
22
|
+
"Prefer #{@config.enforced_style}%> instead of #{trim_node.loc.source}%> for trimming on the right."
|
23
|
+
)
|
27
24
|
end
|
28
25
|
end
|
29
26
|
|
@@ -29,23 +29,23 @@ module ERBLint
|
|
29
29
|
@rubocop_config = RuboCop::ConfigLoader.merge_with_default(custom_config, '')
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
descendant_nodes(processed_source).
|
34
|
-
|
32
|
+
def run(processed_source)
|
33
|
+
descendant_nodes(processed_source).each do |erb_node|
|
34
|
+
inspect_content(processed_source, erb_node)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
def autocorrect(processed_source, offense)
|
39
|
-
return unless offense.
|
39
|
+
return unless offense.context
|
40
40
|
|
41
41
|
lambda do |corrector|
|
42
42
|
passthrough = Utils::OffsetCorrector.new(
|
43
43
|
processed_source,
|
44
44
|
corrector,
|
45
|
-
offense.offset,
|
46
|
-
offense.bound_range,
|
45
|
+
offense.context[:offset],
|
46
|
+
offense.context[:bound_range],
|
47
47
|
)
|
48
|
-
offense.
|
48
|
+
offense.context[:rubocop_correction].call(passthrough)
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -55,16 +55,6 @@ module ERBLint
|
|
55
55
|
processed_source.ast.descendants(:erb)
|
56
56
|
end
|
57
57
|
|
58
|
-
class OffenseWithCorrection < Offense
|
59
|
-
attr_reader :correction, :offset, :bound_range
|
60
|
-
def initialize(linter, source_range, message, correction:, offset:, bound_range:)
|
61
|
-
super(linter, source_range, message)
|
62
|
-
@correction = correction
|
63
|
-
@offset = offset
|
64
|
-
@bound_range = bound_range
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
58
|
def inspect_content(processed_source, erb_node)
|
69
59
|
indicator, _, code_node, = *erb_node
|
70
60
|
return if indicator&.children&.first == '#'
|
@@ -79,7 +69,7 @@ module ERBLint
|
|
79
69
|
|
80
70
|
team = build_team
|
81
71
|
team.inspect_file(source)
|
82
|
-
team.cops.
|
72
|
+
team.cops.each do |cop|
|
83
73
|
correction_offset = 0
|
84
74
|
cop.offenses.reject(&:disabled?).each do |rubocop_offense|
|
85
75
|
if rubocop_offense.corrected?
|
@@ -87,18 +77,12 @@ module ERBLint
|
|
87
77
|
correction_offset += 1
|
88
78
|
end
|
89
79
|
|
90
|
-
offset = code_node.loc.
|
91
|
-
offense_range = processed_source
|
92
|
-
|
93
|
-
offset
|
94
|
-
)
|
80
|
+
offset = code_node.loc.begin_pos - alignment_column
|
81
|
+
offense_range = processed_source
|
82
|
+
.to_source_range(rubocop_offense.location)
|
83
|
+
.offset(offset)
|
95
84
|
|
96
|
-
|
97
|
-
code_node.loc.start,
|
98
|
-
code_node.loc.stop
|
99
|
-
)
|
100
|
-
|
101
|
-
offenses << add_offense(rubocop_offense, offense_range, correction, offset, bound_range)
|
85
|
+
add_offense(rubocop_offense, offense_range, correction, offset, code_node.loc.range)
|
102
86
|
end
|
103
87
|
end
|
104
88
|
end
|
@@ -173,16 +157,12 @@ module ERBLint
|
|
173
157
|
configs.compact
|
174
158
|
end
|
175
159
|
|
176
|
-
def add_offense(
|
177
|
-
if
|
178
|
-
|
179
|
-
options = { correction: correction, offset: offset, bound_range: bound_range }
|
180
|
-
else
|
181
|
-
klass = Offense
|
182
|
-
options = {}
|
160
|
+
def add_offense(rubocop_offense, offense_range, correction, offset, bound_range)
|
161
|
+
context = if rubocop_offense.corrected?
|
162
|
+
{ rubocop_correction: correction, offset: offset, bound_range: bound_range }
|
183
163
|
end
|
184
164
|
|
185
|
-
|
165
|
+
super(offense_range, rubocop_offense.message.strip, context)
|
186
166
|
end
|
187
167
|
end
|
188
168
|
end
|
@@ -11,25 +11,23 @@ module ERBLint
|
|
11
11
|
link menuitem meta param source track wbr img
|
12
12
|
)
|
13
13
|
|
14
|
-
def
|
15
|
-
processed_source.ast.descendants(:tag).
|
14
|
+
def run(processed_source)
|
15
|
+
processed_source.ast.descendants(:tag).each do |tag_node|
|
16
16
|
tag = BetterHtml::Tree::Tag.from_node(tag_node)
|
17
17
|
next unless SELF_CLOSING_TAGS.include?(tag.name)
|
18
18
|
|
19
19
|
if tag.closing?
|
20
20
|
start_solidus = tag_node.children.first
|
21
|
-
|
22
|
-
|
23
|
-
processed_source.to_source_range(start_solidus.loc.start, start_solidus.loc.stop),
|
21
|
+
add_offense(
|
22
|
+
start_solidus.loc,
|
24
23
|
"Tag `#{tag.name}` is self-closing, it must not start with `</`.",
|
25
24
|
''
|
26
25
|
)
|
27
26
|
end
|
28
27
|
|
29
28
|
next if tag.self_closing?
|
30
|
-
|
31
|
-
|
32
|
-
processed_source.to_source_range(tag_node.loc.stop, tag_node.loc.stop - 1),
|
29
|
+
add_offense(
|
30
|
+
tag_node.loc.end.offset(-1),
|
33
31
|
"Tag `#{tag.name}` is self-closing, it must end with `/>`.",
|
34
32
|
'/'
|
35
33
|
)
|
@@ -11,51 +11,45 @@ module ERBLint
|
|
11
11
|
START_SPACES = /\A([[:space:]]*)/m
|
12
12
|
END_SPACES = /([[:space:]]*)\z/m
|
13
13
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
code = code_node.children.first
|
14
|
+
def run(processed_source)
|
15
|
+
processed_source.ast.descendants(:erb).each do |erb_node|
|
16
|
+
indicator, ltrim, code_node, rtrim = *erb_node
|
17
|
+
code = code_node.children.first
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
)
|
38
|
-
end
|
19
|
+
start_spaces = code.match(START_SPACES)&.captures&.first || ""
|
20
|
+
if start_spaces.size != 1 && !start_spaces.include?("\n")
|
21
|
+
add_offense(
|
22
|
+
code_node.loc.resize(start_spaces.size),
|
23
|
+
"Use 1 space after `<%#{indicator&.loc&.source}#{ltrim&.loc&.source}` "\
|
24
|
+
"instead of #{start_spaces.size} space#{'s' if start_spaces.size > 1}.",
|
25
|
+
' '
|
26
|
+
)
|
27
|
+
elsif start_spaces.count("\n") > 1
|
28
|
+
lines = start_spaces.split("\n", -1)
|
29
|
+
add_offense(
|
30
|
+
code_node.loc.resize(start_spaces.size),
|
31
|
+
"Use 1 newline after `<%#{indicator&.loc&.source}#{ltrim&.loc&.source}` "\
|
32
|
+
"instead of #{start_spaces.count("\n")}.",
|
33
|
+
"#{lines.first}\n#{lines.last}"
|
34
|
+
)
|
35
|
+
end
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
"#{lines.first}\n#{lines.last}"
|
57
|
-
)
|
58
|
-
end
|
37
|
+
end_spaces = code.match(END_SPACES)&.captures&.first || ""
|
38
|
+
if end_spaces.size != 1 && !end_spaces.include?("\n")
|
39
|
+
add_offense(
|
40
|
+
code_node.loc.end.adjust(begin_pos: -end_spaces.size),
|
41
|
+
"Use 1 space before `#{rtrim&.loc&.source}%>` "\
|
42
|
+
"instead of #{end_spaces.size} space#{'s' if start_spaces.size > 1}.",
|
43
|
+
' '
|
44
|
+
)
|
45
|
+
elsif end_spaces.count("\n") > 1
|
46
|
+
lines = end_spaces.split("\n", -1)
|
47
|
+
add_offense(
|
48
|
+
code_node.loc.end.adjust(begin_pos: -end_spaces.size),
|
49
|
+
"Use 1 newline before `#{rtrim&.loc&.source}%>` "\
|
50
|
+
"instead of #{end_spaces.count("\n")}.",
|
51
|
+
"#{lines.first}\n#{lines.last}"
|
52
|
+
)
|
59
53
|
end
|
60
54
|
end
|
61
55
|
end
|
@@ -6,35 +6,33 @@ module ERBLint
|
|
6
6
|
class SpaceInHtmlTag < Linter
|
7
7
|
include LinterRegistry
|
8
8
|
|
9
|
-
def
|
10
|
-
offenses = []
|
9
|
+
def run(processed_source)
|
11
10
|
processed_source.ast.descendants(:tag).each do |tag_node|
|
12
11
|
start_solidus, name, attributes, end_solidus = *tag_node
|
13
12
|
|
14
|
-
next_loc = name&.loc&.
|
15
|
-
end_solidus&.loc&.
|
13
|
+
next_loc = name&.loc&.begin_pos || attributes&.loc&.begin_pos ||
|
14
|
+
end_solidus&.loc&.begin_pos || (tag_node.loc.end_pos - 1)
|
16
15
|
if start_solidus
|
17
|
-
|
18
|
-
|
16
|
+
no_space(processed_source, (tag_node.loc.begin_pos + 1)...start_solidus.loc.begin_pos)
|
17
|
+
no_space(processed_source, start_solidus.loc.end_pos...next_loc)
|
19
18
|
else
|
20
|
-
|
19
|
+
no_space(processed_source, (tag_node.loc.begin_pos + 1)...next_loc)
|
21
20
|
end
|
22
21
|
|
23
22
|
if attributes
|
24
|
-
|
25
|
-
|
23
|
+
single_space_or_newline(processed_source, name.loc.end_pos...attributes.loc.begin_pos) if name
|
24
|
+
process_attributes(processed_source, attributes)
|
26
25
|
end
|
27
26
|
|
28
|
-
previous_loc = attributes&.loc&.
|
29
|
-
start_solidus&.loc&.
|
27
|
+
previous_loc = attributes&.loc&.end_pos || name&.loc&.end_pos ||
|
28
|
+
start_solidus&.loc&.end_pos || (tag_node.loc.begin_pos + 1)
|
30
29
|
if end_solidus
|
31
|
-
|
32
|
-
|
30
|
+
single_space(processed_source, previous_loc...end_solidus.loc.begin_pos)
|
31
|
+
no_space(processed_source, end_solidus.loc.end_pos...(tag_node.loc.end_pos - 1))
|
33
32
|
else
|
34
|
-
|
33
|
+
no_space(processed_source, previous_loc...(tag_node.loc.end_pos - 1))
|
35
34
|
end
|
36
35
|
end
|
37
|
-
offenses.compact
|
38
36
|
end
|
39
37
|
|
40
38
|
def autocorrect(_processed_source, offense)
|
@@ -45,25 +43,22 @@ module ERBLint
|
|
45
43
|
|
46
44
|
private
|
47
45
|
|
48
|
-
def no_space(processed_source,
|
49
|
-
range = Range.new(begin_pos, end_pos - 1)
|
46
|
+
def no_space(processed_source, range)
|
50
47
|
chars = processed_source.file_content[range]
|
51
48
|
return if chars.empty?
|
52
49
|
|
53
|
-
|
54
|
-
|
55
|
-
processed_source.to_source_range(begin_pos, end_pos - 1),
|
50
|
+
add_offense(
|
51
|
+
processed_source.to_source_range(range),
|
56
52
|
"Extra space detected where there should be no space.",
|
57
53
|
''
|
58
54
|
)
|
59
55
|
end
|
60
56
|
|
61
|
-
def single_space_or_newline(processed_source,
|
62
|
-
single_space(processed_source,
|
57
|
+
def single_space_or_newline(processed_source, range)
|
58
|
+
single_space(processed_source, range, accept_newline: true)
|
63
59
|
end
|
64
60
|
|
65
|
-
def single_space(processed_source,
|
66
|
-
range = Range.new(begin_pos, end_pos - 1)
|
61
|
+
def single_space(processed_source, range, accept_newline: false)
|
67
62
|
chars = processed_source.file_content[range]
|
68
63
|
return if chars == ' '
|
69
64
|
|
@@ -72,27 +67,24 @@ module ERBLint
|
|
72
67
|
non_space = chars.match(/([^[[:space:]]])/m)
|
73
68
|
|
74
69
|
if non_space && !non_space.captures.empty?
|
75
|
-
|
76
|
-
|
77
|
-
processed_source.to_source_range(begin_pos, end_pos - 1),
|
70
|
+
add_offense(
|
71
|
+
processed_source.to_source_range(range),
|
78
72
|
"Non-whitespace character(s) detected: "\
|
79
73
|
"#{non_space.captures.map(&:inspect).join(', ')}.",
|
80
74
|
expected
|
81
75
|
)
|
82
76
|
elsif newlines && accept_newline
|
83
77
|
if expected != chars
|
84
|
-
|
85
|
-
|
86
|
-
processed_source.to_source_range(begin_pos, end_pos - 1),
|
78
|
+
add_offense(
|
79
|
+
processed_source.to_source_range(range),
|
87
80
|
"#{chars.empty? ? 'No' : 'Extra'} space detected where there should be "\
|
88
81
|
"a single space or a single line break.",
|
89
82
|
expected
|
90
83
|
)
|
91
84
|
end
|
92
85
|
else
|
93
|
-
|
94
|
-
|
95
|
-
processed_source.to_source_range(begin_pos, end_pos - 1),
|
86
|
+
add_offense(
|
87
|
+
processed_source.to_source_range(range),
|
96
88
|
"#{chars.empty? ? 'No' : 'Extra'} space detected where there should be a single space.",
|
97
89
|
expected
|
98
90
|
)
|
@@ -100,19 +92,19 @@ module ERBLint
|
|
100
92
|
end
|
101
93
|
|
102
94
|
def process_attributes(processed_source, attributes)
|
103
|
-
offenses = []
|
104
95
|
attributes.children.each_with_index do |attribute, index|
|
105
96
|
name, equal, value = *attribute
|
106
|
-
|
107
|
-
|
97
|
+
no_space(processed_source, name.loc.end_pos...equal.loc.begin_pos) if equal
|
98
|
+
no_space(processed_source, equal.loc.end_pos...value.loc.begin_pos) if equal && value
|
108
99
|
|
109
100
|
next if index >= attributes.children.size - 1
|
110
101
|
next_attribute = attributes.children[index + 1]
|
111
102
|
|
112
|
-
|
113
|
-
|
103
|
+
single_space_or_newline(
|
104
|
+
processed_source,
|
105
|
+
attribute.loc.end_pos...next_attribute.loc.begin_pos
|
106
|
+
)
|
114
107
|
end
|
115
|
-
offenses
|
116
108
|
end
|
117
109
|
end
|
118
110
|
end
|
@@ -13,16 +13,15 @@ module ERBLint
|
|
13
13
|
|
14
14
|
START_SPACES = /\A([[:blank:]]*)/
|
15
15
|
|
16
|
-
def
|
16
|
+
def run(processed_source)
|
17
17
|
lines = processed_source.file_content.split("\n", -1)
|
18
18
|
document_pos = 0
|
19
|
-
lines.
|
19
|
+
lines.each do |line|
|
20
20
|
spaces = line.match(START_SPACES)&.captures&.first
|
21
21
|
|
22
22
|
if spaces.include?("\t")
|
23
|
-
|
24
|
-
|
25
|
-
processed_source.to_source_range(document_pos, document_pos + spaces.length - 1),
|
23
|
+
add_offense(
|
24
|
+
processed_source.to_source_range(document_pos...(document_pos + spaces.length)),
|
26
25
|
"Indent with spaces instead of tabs.",
|
27
26
|
spaces.gsub("\t", ' ' * @config.tab_width)
|
28
27
|
)
|
@@ -8,17 +8,16 @@ module ERBLint
|
|
8
8
|
|
9
9
|
TRAILING_WHITESPACE = /([[:space:]]*)\Z/
|
10
10
|
|
11
|
-
def
|
11
|
+
def run(processed_source)
|
12
12
|
lines = processed_source.file_content.split("\n", -1)
|
13
13
|
document_pos = 0
|
14
|
-
lines.
|
14
|
+
lines.each do |line|
|
15
15
|
document_pos += line.length + 1
|
16
16
|
whitespace = line.match(TRAILING_WHITESPACE)&.captures&.first
|
17
17
|
next unless whitespace && !whitespace.empty?
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
processed_source.to_source_range(document_pos - whitespace.length - 1, document_pos - 2),
|
19
|
+
add_offense(
|
20
|
+
processed_source.to_source_range((document_pos - whitespace.length - 1)...(document_pos - 1)),
|
22
21
|
"Extra whitespace detected at end of line."
|
23
22
|
)
|
24
23
|
end
|
data/lib/erb_lint/offense.rb
CHANGED
@@ -17,7 +17,7 @@ module ERBLint
|
|
17
17
|
|
18
18
|
def inspect
|
19
19
|
"#<#{self.class.name} linter=#{linter.class.name} "\
|
20
|
-
"source_range=#{source_range.begin_pos}
|
20
|
+
"source_range=#{source_range.begin_pos}...#{source_range.end_pos} "\
|
21
21
|
"message=#{message}>"
|
22
22
|
end
|
23
23
|
|
@@ -7,7 +7,7 @@ module ERBLint
|
|
7
7
|
def initialize(filename, file_content)
|
8
8
|
@filename = filename
|
9
9
|
@file_content = file_content
|
10
|
-
@parser = BetterHtml::Parser.new(
|
10
|
+
@parser = BetterHtml::Parser.new(source_buffer, template_language: :html)
|
11
11
|
end
|
12
12
|
|
13
13
|
def ast
|
@@ -22,8 +22,13 @@ module ERBLint
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def to_source_range(
|
26
|
-
Parser::Source::Range
|
25
|
+
def to_source_range(range)
|
26
|
+
range = (range.begin_pos...range.end_pos) if range.is_a?(::Parser::Source::Range)
|
27
|
+
BetterHtml::Tokenizer::Location.new(
|
28
|
+
source_buffer,
|
29
|
+
range.begin,
|
30
|
+
range.exclude_end? ? range.end : range.end + 1
|
31
|
+
)
|
27
32
|
end
|
28
33
|
end
|
29
34
|
end
|
data/lib/erb_lint/runner.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
module ERBLint
|
4
4
|
# Runs all enabled linters against an html.erb file.
|
5
5
|
class Runner
|
6
|
+
attr_reader :offenses
|
7
|
+
|
6
8
|
def initialize(file_loader, config)
|
7
9
|
@file_loader = file_loader
|
8
10
|
@config = config || RunnerConfig.default
|
@@ -13,16 +15,21 @@ module ERBLint
|
|
13
15
|
@linters = linter_classes.map do |linter_class|
|
14
16
|
linter_class.new(@file_loader, @config.for_linter(linter_class))
|
15
17
|
end
|
18
|
+
@offenses = []
|
16
19
|
end
|
17
20
|
|
18
21
|
def run(processed_source)
|
19
|
-
offenses = []
|
20
22
|
@linters
|
21
23
|
.reject { |linter| linter.excludes_file?(processed_source.filename) }
|
22
24
|
.each do |linter|
|
23
|
-
|
25
|
+
linter.run(processed_source)
|
26
|
+
@offenses.concat(linter.offenses)
|
24
27
|
end
|
25
|
-
|
28
|
+
end
|
29
|
+
|
30
|
+
def clear_offenses
|
31
|
+
@offenses = []
|
32
|
+
@linters.each(&:clear_offenses)
|
26
33
|
end
|
27
34
|
end
|
28
35
|
end
|
@@ -26,7 +26,7 @@ module ERBLint
|
|
26
26
|
private
|
27
27
|
|
28
28
|
def erb_nodes
|
29
|
-
erb_ast.descendants(:erb).sort { |a, b| a.loc.
|
29
|
+
erb_ast.descendants(:erb).sort { |a, b| a.loc.begin_pos <=> b.loc.begin_pos }
|
30
30
|
end
|
31
31
|
|
32
32
|
class Entry
|
@@ -72,14 +72,14 @@ module ERBLint
|
|
72
72
|
def ordered(nodes)
|
73
73
|
nodes
|
74
74
|
.uniq(&:loc)
|
75
|
-
.sort { |a, b| a.loc.
|
75
|
+
.sort { |a, b| a.loc.begin_pos <=> b.loc.begin_pos }
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
79
|
def build_map
|
80
80
|
erb_nodes.each do |erb_node|
|
81
81
|
indicator_node, _, code_node, _ = *erb_node
|
82
|
-
length = code_node.loc.
|
82
|
+
length = code_node.loc.size
|
83
83
|
start = current_pos
|
84
84
|
if indicator_node.nil?
|
85
85
|
append("#{code_node.loc.source}\n")
|
@@ -40,15 +40,14 @@ module ERBLint
|
|
40
40
|
|
41
41
|
def range_with_offset(range)
|
42
42
|
@processed_source.to_source_range(
|
43
|
-
bound(@offset + range.begin_pos)
|
44
|
-
bound(@offset + range.end_pos - 1),
|
43
|
+
bound(@offset + range.begin_pos)..bound(@offset + (range.end_pos - 1))
|
45
44
|
)
|
46
45
|
end
|
47
46
|
|
48
47
|
def bound(pos)
|
49
48
|
[
|
50
|
-
[pos, @bound_range.
|
51
|
-
@bound_range.
|
49
|
+
[pos, @bound_range.min].max,
|
50
|
+
@bound_range.max
|
52
51
|
].min
|
53
52
|
end
|
54
53
|
end
|
data/lib/erb_lint/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: erb_lint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.22
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Chan
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-02-
|
11
|
+
date: 2018-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: better_html
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.0.
|
19
|
+
version: 1.0.6
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.0.
|
26
|
+
version: 1.0.6
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: html_tokenizer
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|