erb_lint 0.0.21 → 0.0.22
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/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
|