erb_lint 0.0.4 → 0.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8866aae317226178c623de53d4c5e0791643c894
4
- data.tar.gz: fac55efcf4a15f251f537af97039b8669960c00b
3
+ metadata.gz: 3a211bea7ec247bcf1d79ede8f37db1b6b7d1b8c
4
+ data.tar.gz: 362ca7b4ffb1f184818889166cb572198c1def7e
5
5
  SHA512:
6
- metadata.gz: b92425a8c4fbe2c65fde42a8dab091c841e2bc0f70b29833e49c06fc99acc85b42639dc9129f200b99195930e9f7fbb96d58fdcaaefb947cd40ad76008ffe765
7
- data.tar.gz: aefbb18d6756d5e08045c4d5c8c0afb6ef8fb897f0b73c72fe905158b40d1cbc1114bfada2ec59029165b1a9d72930a172c17b6cfe059a11283bf8ec80e41bc9
6
+ metadata.gz: 45c2ff7d03c2ec43e37562887ad9cdc9f396b0084bf290036a848aa820fed661a0f99a49d120be62100aa15c640fa4374f5937c9accb0066a06028632ac56e8f
7
+ data.tar.gz: 16279ef10a1f004fe97309dde027de0bf244ac0a9e047b9a0ff04be73d5d9d71494e1e2ab08d584b9123ee96f35a05525ff7b8ff09d005d3f75f000c009eacbf
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'better_html'
4
+
3
5
  module ERBLint
4
6
  module Linters
5
7
  # Checks for deprecated classes in the start tags of HTML elements.
@@ -22,144 +24,65 @@ module ERBLint
22
24
  @addendum = config.fetch('addendum', '')
23
25
  end
24
26
 
25
- protected
26
-
27
- def lint_lines(lines)
27
+ def lint_file(file_content)
28
28
  errors = []
29
-
30
- lines.each_with_index do |line, index|
31
- start_tags = StartTagHelper.start_tags(line)
32
- start_tags.each do |start_tag|
33
- start_tag.attributes.select(&:class?).each do |class_attr|
34
- class_attr.value.split(' ').each do |class_name|
35
- errors.push(*generate_errors(class_name, index + 1))
36
- end
37
- end
38
- end
29
+ iterator = build_iterator(file_content)
30
+ each_class_name_with_line(iterator) do |class_name, line|
31
+ errors.push(*generate_errors(class_name, line))
32
+ end
33
+ each_texthtml_script(iterator) do |text_node|
34
+ errors.push(*lint_file(text_node.content))
39
35
  end
40
36
  errors
41
37
  end
42
38
 
43
39
  private
44
40
 
45
- def generate_errors(class_name, line_number)
46
- violated_rules(class_name).map do |violated_rule|
47
- suggestion = " #{violated_rule[:suggestion]}".rstrip
48
- message = "Deprecated class `%s` detected matching the pattern `%s`.%s #{@addendum}".strip
49
- {
50
- line: line_number,
51
- message: format(message, class_name, violated_rule[:class_expr], suggestion)
52
- }
53
- end
41
+ def build_iterator(file_content)
42
+ BetterHtml::NodeIterator.new(file_content, template_language: :html)
54
43
  end
55
44
 
56
- def violated_rules(class_name)
57
- @deprecated_ruleset.select do |deprecated_rule|
58
- /\A#{deprecated_rule[:class_expr]}\z/.match(class_name)
45
+ def each_class_name_with_line(iterator)
46
+ each_element_with_index(iterator) do |element, _index|
47
+ klass = element.find_attr('class')
48
+ next unless klass
49
+ klass.value_without_quotes.split(' ').each do |class_name|
50
+ yield class_name, klass.name_parts.first.location.line
51
+ end
59
52
  end
60
53
  end
61
- end
62
-
63
- # Provides methods and classes for finding HTML start tags and their attributes.
64
- module StartTagHelper
65
- # These patterns cover a superset of the W3 HTML5 specification.
66
- # Additional cases not included in the spec include those that are still rendered by some browsers.
67
-
68
- # Attribute Patterns
69
- # https://www.w3.org/TR/html5/syntax.html#syntax-attributes
70
-
71
- # attribute names must be non empty and can't contain a certain set of special characters
72
- ATTRIBUTE_NAME_PATTERN = %r{[^\s"'>\/=]+}
73
-
74
- ATTRIBUTE_VALUE_PATTERN = %r{
75
- "([^"]*)" | # double-quoted value
76
- '([^']*)' | # single-quoted value
77
- ([^\s"'=<>`]+) # unquoted non-empty value without special characters
78
- }x
79
-
80
- # attributes can be empty or have an attribute value
81
- ATTRIBUTE_PATTERN = %r{
82
- #{ATTRIBUTE_NAME_PATTERN} # attribute name
83
- (
84
- \s*=\s* # any whitespace around equals sign
85
- (#{ATTRIBUTE_VALUE_PATTERN}) # attribute value
86
- )? # attributes can be empty or have an assignemnt.
87
- }x
88
-
89
- # Start tag Patterns
90
- # https://www.w3.org/TR/html5/syntax.html#syntax-start-tag
91
-
92
- TAG_NAME_PATTERN = /[A-Za-z0-9]+/ # maybe add _ < ? etc later since it gets interpreted by some browsers
93
54
 
94
- START_TAG_PATTERN = %r{
95
- <(#{TAG_NAME_PATTERN}) # start of tag with tag name
96
- (
97
- (
98
- \s+ # required whitespace between tag name and first attribute and between attributes
99
- #{ATTRIBUTE_PATTERN} # attributes
100
- )*
101
- )? # having an attribute block is optional
102
- \/?> # void or foreign elements can have a slash before tag close
103
- }x
104
-
105
- # Represents and provides an interface for a start tag found in the HTML.
106
- class StartTag
107
- attr_accessor :tag_name, :attributes
108
-
109
- def initialize(tag_name, attributes)
110
- @tag_name = tag_name
111
- @attributes = attributes
55
+ def each_element_with_index(iterator)
56
+ iterator.nodes.each_with_index do |node, index|
57
+ yield node, index if node.element?
112
58
  end
113
59
  end
114
60
 
115
- # Represents and provides an interface for an attribute found in a start tag in the HTML.
116
- class Attribute
117
- ATTR_NAME_CLASS_PATTERN = /\Aclass\z/i # attribute names are case-insensitive
118
- attr_accessor :attribute_name, :value
119
-
120
- def initialize(attribute_name, value)
121
- @attribute_name = attribute_name
122
- @value = value
123
- end
61
+ def each_texthtml_script(iterator)
62
+ each_element_with_index(iterator) do |element, index|
63
+ type = element.find_attr('type')
64
+ next unless type
65
+ next unless 'text/html' == type.value_without_quotes
66
+ next_node = iterator.nodes[index + 1]
124
67
 
125
- def class?
126
- ATTR_NAME_CLASS_PATTERN.match(@attribute_name)
68
+ yield next_node if next_node&.text?
127
69
  end
128
70
  end
129
71
 
130
- class << self
131
- def start_tags(line)
132
- # TODO: Implement String Scanner to track quotes before the start tag begins to ensure that it is
133
- # not enclosed inside of a string. Alternatively this problem would be solved by using
134
- # a 3rd party parser like Nokogiri::XML
135
-
136
- start_tag_matching_groups = line.scan(/(#{START_TAG_PATTERN})/)
137
- start_tag_matching_groups.map do |start_tag_matching_group|
138
- tag_name = start_tag_matching_group[1]
139
-
140
- # attributes_string can be nil if there is no space after the tag name (and therefore no attributes).
141
- attributes_string = start_tag_matching_group[2] || ''
142
-
143
- attribute_list = attributes(attributes_string)
144
-
145
- StartTag.new(tag_name, attribute_list)
146
- end
72
+ def generate_errors(class_name, line_number)
73
+ violated_rules(class_name).map do |violated_rule|
74
+ suggestion = " #{violated_rule[:suggestion]}".rstrip
75
+ message = "Deprecated class `%s` detected matching the pattern `%s`.%s #{@addendum}".strip
76
+ {
77
+ line: line_number,
78
+ message: format(message, class_name, violated_rule[:class_expr], suggestion)
79
+ }
147
80
  end
81
+ end
148
82
 
149
- private
150
-
151
- def attributes(attributes_string)
152
- attributes_string.scan(/(#{ATTRIBUTE_PATTERN})/).map do |attribute_matching_group|
153
- entire_string = attribute_matching_group[0]
154
- value_with_equal_sign = attribute_matching_group[1] || '' # This can be nil if attribute is empty
155
- name = entire_string.sub(value_with_equal_sign, '')
156
-
157
- # The 3 captures [3..5] are the possibilities specified in ATTRIBUTE_VALUE_PATTERN
158
- possible_value_formats = attribute_matching_group[3..5]
159
- value = possible_value_formats.reduce { |a, e| a.nil? ? e : a }
160
-
161
- Attribute.new(name, value)
162
- end
83
+ def violated_rules(class_name)
84
+ @deprecated_ruleset.select do |deprecated_rule|
85
+ /\A#{deprecated_rule[:class_expr]}\z/.match(class_name)
163
86
  end
164
87
  end
165
88
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'better_html'
4
+ require 'better_html/test_helper/safe_erb_tester'
5
+
6
+ module ERBLint
7
+ module Linters
8
+ # Detect unsafe ruby interpolations into javascript.
9
+ class ErbSafety < Linter
10
+ include LinterRegistry
11
+ include BetterHtml::TestHelper::SafeErbTester
12
+
13
+ def initialize(config)
14
+ end
15
+
16
+ def lint_file(file_content)
17
+ errors = []
18
+ tester = Tester.new(file_content)
19
+ tester.errors.each do |error|
20
+ errors << format_error(error)
21
+ end
22
+ errors
23
+ end
24
+
25
+ private
26
+
27
+ def format_error(error)
28
+ {
29
+ line: error.token.location.line,
30
+ message: error.message
31
+ }
32
+ end
33
+ end
34
+ end
35
+ end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erb_lint
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Chan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-27 00:00:00.000000000 Z
11
+ date: 2017-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: html_tokenizer
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: better_html
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.5
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.5
13
41
  - !ruby/object:Gem::Dependency
14
42
  name: rspec
15
43
  requirement: !ruby/object:Gem::Requirement
@@ -49,6 +77,7 @@ files:
49
77
  - lib/erb_lint/linter.rb
50
78
  - lib/erb_lint/linter_registry.rb
51
79
  - lib/erb_lint/linters/deprecated_classes.rb
80
+ - lib/erb_lint/linters/erb_safety.rb
52
81
  - lib/erb_lint/linters/final_newline.rb
53
82
  - lib/erb_lint/runner.rb
54
83
  homepage: https://github.com/justinthec/erb-lint