better_html 0.0.9 → 0.0.10

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: 17ea4709e995bab97c314fd892b1926582788ab4
4
- data.tar.gz: 497c12a9e1e060b4564d2310695fe06d54e3af86
3
+ metadata.gz: b6246bfb4cf4ae99f87a12370d99b362b9b2737b
4
+ data.tar.gz: 67a8747a32552d237bacafe3cc782dc7b1815ffc
5
5
  SHA512:
6
- metadata.gz: 6cb55f55293eb9875635480ada4148fd3afb4a148284e24998c5cfa0a0648598f5659a8dccc41ea2329aa630f194fa8fe7d7f08bebea732310e8aebc7f80f5ff
7
- data.tar.gz: 8786bbc8fe5a6df5da740715413f6ef05e9b05302f4b9cf1fe5672f4eb98ef931519155e3f219b6b3dc53c5fd1142d626e7b8c5c6f008ca655f7e9eab8daba2c
6
+ metadata.gz: 07c548e1027d5f582ee796df6b536bd6f895edcd42c3c2898d0eb1da61c9adffaff6683bf83cbfee3e59d0f2acb2ed70c3371606cb772b39b3a8c4df30a75d8a
7
+ data.tar.gz: d5168282725b6e5ba210eae30eefcfa88b8270063422f0127be7f53cc888dfa1470c9a82db09971d2b9ec540024a28f57337cf9d4e092afb5aa86c092f9aef0a
data/lib/better_html.rb CHANGED
@@ -3,49 +3,21 @@ require 'active_support/core_ext/module/delegation'
3
3
  require 'active_support/core_ext/class/attribute_accessors'
4
4
 
5
5
  module BetterHtml
6
- class Config
7
- # regex to validate "foo" in "<foo>"
8
- cattr_accessor :partial_tag_name_pattern
9
- self.partial_tag_name_pattern = /\A[a-z0-9\-\:]+\z/
10
-
11
- # regex to validate "bar" in "<foo bar=1>"
12
- cattr_accessor :partial_attribute_name_pattern
13
- self.partial_attribute_name_pattern = /\A[a-zA-Z0-9\-\:]+\z/
14
-
15
- # true if "<foo bar='1'>" is valid syntax
16
- cattr_accessor :allow_single_quoted_attributes
17
- self.allow_single_quoted_attributes = false
18
-
19
- # true if "<foo bar=1>" is valid syntax
20
- cattr_accessor :allow_unquoted_attributes
21
- self.allow_unquoted_attributes = false
22
-
23
- # all methods that return "javascript-safe" strings
24
- cattr_accessor :javascript_safe_methods
25
- self.javascript_safe_methods = ['to_json']
26
-
27
- # name of all html attributes that may contain javascript
28
- cattr_accessor :javascript_attribute_names
29
- self.javascript_attribute_names = [/\Aon/i]
30
-
31
- cattr_accessor :template_exclusion_filter_block
32
-
33
- def self.template_exclusion_filter(&block)
34
- self.template_exclusion_filter_block = block
35
- end
36
-
37
- cattr_accessor :lodash_safe_javascript_expression
38
- self.lodash_safe_javascript_expression = [/\AJSON\.stringify\(/]
6
+ def self.configure
7
+ yield config if block_given?
39
8
  end
40
9
 
41
10
  def self.config
42
11
  @config ||= Config.new
43
- yield @config if block_given?
44
- @config
12
+ end
13
+
14
+ def self.config=(new_config)
15
+ @config = new_config
45
16
  end
46
17
  end
47
18
 
48
19
  require 'better_html/version'
20
+ require 'better_html/config'
49
21
  require 'better_html/helpers'
50
22
  require 'better_html/errors'
51
23
  require 'better_html/html_attributes'
@@ -52,7 +52,7 @@ class BetterHtml::BetterErb
52
52
  # Always make sure we return a String in the default_internal
53
53
  erb.encode!
54
54
 
55
- excluded_template = !!BetterHtml::Config.template_exclusion_filter_block&.call(template.identifier)
55
+ excluded_template = !!BetterHtml.config.template_exclusion_filter_block&.call(template.identifier)
56
56
  klass = BetterHtml::BetterErb.content_types[exts] unless excluded_template
57
57
  klass ||= self.class.erb_implementation
58
58
 
@@ -3,9 +3,10 @@ require 'action_view'
3
3
 
4
4
  class BetterHtml::BetterErb
5
5
  module RuntimeChecks
6
- def initialize(*)
6
+ def initialize(erb, config: BetterHtml.config, **options)
7
7
  @parser = HtmlTokenizer::Parser.new
8
- super
8
+ @config = config
9
+ super(erb, **options)
9
10
  end
10
11
 
11
12
  def validate!
@@ -112,26 +113,26 @@ class BetterHtml::BetterErb
112
113
  def check_tag_name(type, start, stop, line, column)
113
114
  text = @parser.extract(start, stop)
114
115
  return if text.upcase == "!DOCTYPE"
115
- return if BetterHtml.config.partial_tag_name_pattern === text
116
+ return if @config.partial_tag_name_pattern === text
116
117
 
117
118
  s = "Invalid tag name #{text.inspect} does not match "\
118
- "regular expression #{BetterHtml.config.partial_tag_name_pattern.inspect}\n"
119
+ "regular expression #{@config.partial_tag_name_pattern.inspect}\n"
119
120
  s << build_location(line, column, text.size)
120
121
  raise BetterHtml::HtmlError, s
121
122
  end
122
123
 
123
124
  def check_attribute_name(type, start, stop, line, column)
124
125
  text = @parser.extract(start, stop)
125
- return if BetterHtml.config.partial_attribute_name_pattern === text
126
+ return if @config.partial_attribute_name_pattern === text
126
127
 
127
128
  s = "Invalid attribute name #{text.inspect} does not match "\
128
- "regular expression #{BetterHtml.config.partial_attribute_name_pattern.inspect}\n"
129
+ "regular expression #{@config.partial_attribute_name_pattern.inspect}\n"
129
130
  s << build_location(line, column, text.size)
130
131
  raise BetterHtml::HtmlError, s
131
132
  end
132
133
 
133
134
  def check_quoted_value(type, start, stop, line, column)
134
- return if BetterHtml.config.allow_single_quoted_attributes
135
+ return if @config.allow_single_quoted_attributes
135
136
  text = @parser.extract(start, stop)
136
137
  return if text == '"'
137
138
 
@@ -141,7 +142,7 @@ class BetterHtml::BetterErb
141
142
  end
142
143
 
143
144
  def check_unquoted_value(type, start, stop, line, column)
144
- return if BetterHtml.config.allow_unquoted_attributes
145
+ return if @config.allow_unquoted_attributes
145
146
  s = "Unquoted attribute values are not allowed\n"
146
147
  s << build_location(line, column, stop-start)
147
148
  raise BetterHtml::HtmlError, s
@@ -0,0 +1,16 @@
1
+ require 'smart_properties'
2
+
3
+ module BetterHtml
4
+ class Config
5
+ include SmartProperties
6
+
7
+ property :partial_tag_name_pattern, default: /\A[a-z0-9\-\:]+\z/
8
+ property :partial_attribute_name_pattern, default: /\A[a-zA-Z0-9\-\:]+\z/
9
+ property :allow_single_quoted_attributes, default: true
10
+ property :allow_unquoted_attributes, default: false
11
+ property :javascript_safe_methods, default: ['to_json']
12
+ property :javascript_attribute_names, default: [/\Aon/i]
13
+ property :template_exclusion_filter
14
+ property :lodash_safe_javascript_expression, default: [/\AJSON\.stringify\(/]
15
+ end
16
+ end
@@ -28,10 +28,9 @@ module BetterHtml
28
28
  end
29
29
 
30
30
  def line_source_with_underline
31
- line_content = @document.lines[line-1]
32
- line_content = line_content.nil? ? "" : line_content.gsub(/\n$/, '')
31
+ line_content = extract_line(line: line)
33
32
  spaces = line_content.scan(/\A\s*/).first
34
- column_without_spaces = column - spaces.length
33
+ column_without_spaces = [column - spaces.length, 0].max
35
34
  underscore_length = [[stop - start, line_content.length - column_without_spaces].min, 1].max
36
35
  "#{line_content.gsub(/\A\s*/, '')}\n#{' ' * column_without_spaces}#{'^' * underscore_length}"
37
36
  end
@@ -45,6 +44,10 @@ module BetterHtml
45
44
  def calculate_column
46
45
  @document[0..start-1]&.split("\n", -1)&.last&.length || 0
47
46
  end
47
+
48
+ def extract_line(line:)
49
+ @document.split("\n", -1)[line - 1]&.gsub(/\n$/, '') || ""
50
+ end
48
51
  end
49
52
  end
50
53
  end
@@ -52,8 +52,9 @@ EOF
52
52
 
53
53
  VALID_JAVASCRIPT_TAG_TYPES = ['text/javascript', 'text/template', 'text/html']
54
54
 
55
- def initialize(data, **options)
55
+ def initialize(data, config: BetterHtml.config, **options)
56
56
  @data = data
57
+ @config = config
57
58
  @errors = Errors.new
58
59
  @options = options.present? ? options.dup : {}
59
60
  @options[:template_language] ||= :html
@@ -228,11 +229,11 @@ EOF
228
229
  end
229
230
 
230
231
  def javascript_attribute_name?(name)
231
- BetterHtml.config.javascript_attribute_names.any?{ |other| other === name.to_s }
232
+ @config.javascript_attribute_names.any?{ |other| other === name.to_s }
232
233
  end
233
234
 
234
235
  def javascript_safe_method?(name)
235
- BetterHtml.config.javascript_safe_methods.include?(name.to_s)
236
+ @config.javascript_safe_methods.include?(name.to_s)
236
237
  end
237
238
 
238
239
  def validate_script_tag_content(node)
@@ -240,19 +241,20 @@ EOF
240
241
  case token.type
241
242
  when :expr_literal, :expr_escaped
242
243
  expr = RubyExpr.parse(token.code)
243
- if expr.calls.empty?
244
- add_error(
245
- "erb interpolation in javascript tag must call '(...).to_json'",
246
- location: token.location,
247
- )
248
- else
249
- validate_script_expression(node, token, expr)
250
- end
244
+ validate_script_expression(node, token, expr)
251
245
  end
252
246
  end
253
247
  end
254
248
 
255
249
  def validate_script_expression(node, token, expr)
250
+ if expr.calls.empty?
251
+ add_error(
252
+ "erb interpolation in javascript tag must call '(...).to_json'",
253
+ location: token.location,
254
+ )
255
+ return
256
+ end
257
+
256
258
  expr.calls.each do |call|
257
259
  if call.method == :raw
258
260
  call.arguments.each do |argument_node|
@@ -25,8 +25,8 @@ Never use <script> tags inside lodash template.
25
25
  -----------
26
26
  EOF
27
27
 
28
- def assert_lodash_safety(data)
29
- tester = Tester.new(data)
28
+ def assert_lodash_safety(data, **options)
29
+ tester = Tester.new(data, **options)
30
30
 
31
31
  message = ""
32
32
  tester.errors.each do |error|
@@ -47,8 +47,9 @@ EOF
47
47
  class Tester
48
48
  attr_reader :errors
49
49
 
50
- def initialize(data)
50
+ def initialize(data, config: BetterHtml.config)
51
51
  @data = data
52
+ @config = config
52
53
  @errors = Errors.new
53
54
  @nodes = BetterHtml::NodeIterator.new(data, template_language: :lodash)
54
55
  validate!
@@ -109,11 +110,11 @@ EOF
109
110
  end
110
111
 
111
112
  def javascript_attribute_name?(name)
112
- BetterHtml.config.javascript_attribute_names.any?{ |other| other === name }
113
+ @config.javascript_attribute_names.any?{ |other| other === name }
113
114
  end
114
115
 
115
116
  def lodash_safe_javascript_expression?(code)
116
- BetterHtml.config.lodash_safe_javascript_expression.any?{ |other| other === code }
117
+ @config.lodash_safe_javascript_expression.any?{ |other| other === code }
117
118
  end
118
119
 
119
120
  def validate_no_statements(node)
@@ -1,3 +1,3 @@
1
1
  module BetterHtml
2
- VERSION = "0.0.9"
2
+ VERSION = "0.0.10"
3
3
  end
@@ -6,36 +6,36 @@ require 'json'
6
6
  class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
7
7
  test "simple template rendering" do
8
8
  assert_equal "<foo>some value<foo>",
9
- render("<foo><%= bar %><foo>", { bar: 'some value' })
9
+ render("<foo><%= bar %><foo>", locals: { bar: 'some value' })
10
10
  end
11
11
 
12
12
  test "html_safe interpolation" do
13
13
  assert_equal "<foo><bar /><foo>",
14
- render("<foo><%= bar %><foo>", { bar: '<bar />'.html_safe })
14
+ render("<foo><%= bar %><foo>", locals: { bar: '<bar />'.html_safe })
15
15
  end
16
16
 
17
17
  test "non html_safe interpolation" do
18
18
  assert_equal "<foo>&lt;bar /&gt;<foo>",
19
- render("<foo><%= bar %><foo>", { bar: '<bar />' })
19
+ render("<foo><%= bar %><foo>", locals: { bar: '<bar />' })
20
20
  end
21
21
 
22
22
  test "interpolate non-html_safe inside attribute is escaped" do
23
23
  assert_equal "<a href=\" &#39;&quot;&gt;x \">",
24
- render("<a href=\"<%= value %>\">", { value: ' \'">x ' })
24
+ render("<a href=\"<%= value %>\">", locals: { value: ' \'">x ' })
25
25
  end
26
26
 
27
27
  test "interpolate html_safe inside attribute is magically force-escaped" do
28
28
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
29
- render("<a href=\"<%= value %>\">", { value: ' \'">x '.html_safe })
29
+ render("<a href=\"<%= value %>\">", locals: { value: ' \'">x '.html_safe })
30
30
  end
31
31
  assert_equal "Detected invalid characters as part of the interpolation "\
32
32
  "into a quoted attribute value. The value cannot contain the character \".", e.message
33
33
  end
34
34
 
35
35
  test "interpolate html_safe inside single quoted attribute" do
36
- BetterHtml.config.stubs(:allow_single_quoted_attributes).returns(true)
36
+ config = build_config(allow_single_quoted_attributes: true)
37
37
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
38
- render("<a href=\'<%= value %>\'>", { value: ' \'">x '.html_safe })
38
+ render("<a href=\'<%= value %>\'>", config: config, locals: { value: ' \'">x '.html_safe })
39
39
  end
40
40
  assert_equal "Detected invalid characters as part of the interpolation "\
41
41
  "into a quoted attribute value. The value cannot contain the character '.", e.message
@@ -43,12 +43,12 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
43
43
 
44
44
  test "interpolate in attribute name" do
45
45
  assert_equal "<a data-safe-foo>",
46
- render("<a data-<%= value %>-foo>", { value: "safe" })
46
+ render("<a data-<%= value %>-foo>", locals: { value: "safe" })
47
47
  end
48
48
 
49
49
  test "interpolate in attribute name with unsafe value with spaces" do
50
50
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
51
- render("<a data-<%= value %>-foo>", { value: "un safe" })
51
+ render("<a data-<%= value %>-foo>", locals: { value: "un safe" })
52
52
  end
53
53
  assert_equal "Detected invalid characters as part of the interpolation "\
54
54
  "into a attribute name around 'data-<%= value %>'.", e.message
@@ -56,7 +56,7 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
56
56
 
57
57
  test "interpolate in attribute name with unsafe value with equal sign" do
58
58
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
59
- render("<a data-<%= value %>-foo>", { value: "un=safe" })
59
+ render("<a data-<%= value %>-foo>", locals: { value: "un=safe" })
60
60
  end
61
61
  assert_equal "Detected invalid characters as part of the "\
62
62
  "interpolation into a attribute name around 'data-<%= value %>'.", e.message
@@ -64,7 +64,7 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
64
64
 
65
65
  test "interpolate in attribute name with unsafe value with quote" do
66
66
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
67
- render("<a data-<%= value %>-foo>", { value: "un\"safe" })
67
+ render("<a data-<%= value %>-foo>", locals: { value: "un\"safe" })
68
68
  end
69
69
  assert_equal "Detected invalid characters as part of the "\
70
70
  "interpolation into a attribute name around 'data-<%= value %>'.", e.message
@@ -76,9 +76,9 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
76
76
  end
77
77
 
78
78
  test "interpolate after an attribute name with equal sign" do
79
- BetterHtml.config.stubs(:allow_unquoted_attributes).returns(true)
79
+ config = build_config(allow_unquoted_attributes: true)
80
80
  e = assert_raises(BetterHtml::DontInterpolateHere) do
81
- render("<a data-foo= <%= html_attributes(foo: 'bar') %>>")
81
+ render("<a data-foo= <%= html_attributes(foo: 'bar') %>>", config: config)
82
82
  end
83
83
  assert_equal "Do not interpolate without quotes after "\
84
84
  "attribute around 'data-foo=<%= html_attributes(foo: 'bar') %>'.", e.message
@@ -94,18 +94,18 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
94
94
  end
95
95
 
96
96
  test "interpolate in attribute without quotes" do
97
- BetterHtml.config.stubs(:allow_unquoted_attributes).returns(true)
97
+ config = build_config(allow_unquoted_attributes: true)
98
98
  e = assert_raises(BetterHtml::DontInterpolateHere) do
99
- render("<a href=<%= value %>>", { value: "un safe" })
99
+ render("<a href=<%= value %>>", config: config, locals: { value: "un safe" })
100
100
  end
101
101
  assert_equal "Do not interpolate without quotes after "\
102
102
  "attribute around 'href=<%= value %>'.", e.message
103
103
  end
104
104
 
105
105
  test "interpolate in attribute after value" do
106
- BetterHtml.config.stubs(:allow_unquoted_attributes).returns(true)
106
+ config = build_config(allow_unquoted_attributes: true)
107
107
  e = assert_raises(BetterHtml::DontInterpolateHere) do
108
- render("<a href=something<%= value %>>", { value: "" })
108
+ render("<a href=something<%= value %>>", config: config, locals: { value: "" })
109
109
  end
110
110
  assert_equal "Do not interpolate without quotes around this "\
111
111
  "attribute value. Instead of <a href=something<%= value %>> "\
@@ -114,12 +114,12 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
114
114
 
115
115
  test "interpolate in tag name" do
116
116
  assert_equal "<tag-safe-foo>",
117
- render("<tag-<%= value %>-foo>", { value: "safe" })
117
+ render("<tag-<%= value %>-foo>", locals: { value: "safe" })
118
118
  end
119
119
 
120
120
  test "interpolate in tag name with space" do
121
121
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
122
- render("<tag-<%= value %>-foo>", { value: "un safe" })
122
+ render("<tag-<%= value %>-foo>", locals: { value: "un safe" })
123
123
  end
124
124
  assert_equal "Detected invalid characters as part of the interpolation "\
125
125
  "into a tag name around: <tag-<%= value %>>.", e.message
@@ -127,7 +127,7 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
127
127
 
128
128
  test "interpolate in tag name with slash" do
129
129
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
130
- render("<tag-<%= value %>-foo>", { value: "un/safe" })
130
+ render("<tag-<%= value %>-foo>", locals: { value: "un/safe" })
131
131
  end
132
132
  assert_equal "Detected invalid characters as part of the interpolation "\
133
133
  "into a tag name around: <tag-<%= value %>>.", e.message
@@ -135,7 +135,7 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
135
135
 
136
136
  test "interpolate in tag name with end of tag" do
137
137
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
138
- render("<tag-<%= value %>-foo>", { value: "><script>" })
138
+ render("<tag-<%= value %>-foo>", locals: { value: "><script>" })
139
139
  end
140
140
  assert_equal "Detected invalid characters as part of the interpolation "\
141
141
  "into a tag name around: <tag-<%= value %>>.", e.message
@@ -143,12 +143,12 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
143
143
 
144
144
  test "interpolate in comment" do
145
145
  assert_equal "<!-- safe -->",
146
- render("<!-- <%= value %> -->", { value: "safe" })
146
+ render("<!-- <%= value %> -->", locals: { value: "safe" })
147
147
  end
148
148
 
149
149
  test "interpolate in comment with end-of-comment" do
150
150
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
151
- render("<!-- <%= value %> -->", { value: "-->".html_safe })
151
+ render("<!-- <%= value %> -->", locals: { value: "-->".html_safe })
152
152
  end
153
153
  assert_equal "Detected invalid characters as part of the interpolation "\
154
154
  "into a html comment around: <!-- <%= value %>.", e.message
@@ -156,18 +156,18 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
156
156
 
157
157
  test "non html_safe interpolation into comment tag" do
158
158
  assert_equal "<!-- --&gt; -->",
159
- render("<!-- <%= value %> -->", value: '-->')
159
+ render("<!-- <%= value %> -->", locals: { value: '-->' })
160
160
  end
161
161
 
162
162
  test "interpolate in script tag" do
163
163
  assert_equal "<script> foo safe bar<script>",
164
- render("<script> foo <%= value %> bar<script>", { value: "safe" })
164
+ render("<script> foo <%= value %> bar<script>", locals: { value: "safe" })
165
165
  end
166
166
 
167
167
  test "interpolate in script tag with start of comment" do
168
168
  skip "skip for now; causing problems"
169
169
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
170
- render("<script> foo <%= value %> bar<script>", { value: "<!--".html_safe })
170
+ render("<script> foo <%= value %> bar<script>", locals: { value: "<!--".html_safe })
171
171
  end
172
172
  assert_equal "Detected invalid characters as part of the interpolation "\
173
173
  "into a script tag around: <script> foo <%= value %>. "\
@@ -176,7 +176,7 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
176
176
 
177
177
  test "interpolate in script tag with start of script" do
178
178
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
179
- render("<script> foo <%= value %> bar<script>", { value: "<script".html_safe })
179
+ render("<script> foo <%= value %> bar<script>", locals: { value: "<script".html_safe })
180
180
  end
181
181
  assert_equal "Detected invalid characters as part of the interpolation "\
182
182
  "into a script tag around: <script> foo <%= value %>. "\
@@ -185,12 +185,12 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
185
185
 
186
186
  test "interpolate in script tag with raw interpolation" do
187
187
  assert_equal "<script> x = \"foo\" </script>",
188
- render("<script> x = <%== value %> </script>", { value: JSON.dump("foo") })
188
+ render("<script> x = <%== value %> </script>", locals: { value: JSON.dump("foo") })
189
189
  end
190
190
 
191
191
  test "interpolate in script tag with start of script case insensitive" do
192
192
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
193
- render("<script> foo <%= value %> bar<script>", { value: "<ScRIpT".html_safe })
193
+ render("<script> foo <%= value %> bar<script>", locals: { value: "<ScRIpT".html_safe })
194
194
  end
195
195
  assert_equal "Detected invalid characters as part of the interpolation "\
196
196
  "into a script tag around: <script> foo <%= value %>. "\
@@ -199,7 +199,7 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
199
199
 
200
200
  test "interpolate in script tag with end of script" do
201
201
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
202
- render("<script> foo <%= value %> bar<script>", { value: "</script".html_safe })
202
+ render("<script> foo <%= value %> bar<script>", locals: { value: "</script".html_safe })
203
203
  end
204
204
  assert_equal "Detected invalid characters as part of the interpolation "\
205
205
  "into a script tag around: <script> foo <%= value %>. "\
@@ -221,17 +221,17 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
221
221
 
222
222
  test "non html_safe interpolation into rawtext tag" do
223
223
  assert_equal "<title>&lt;/title&gt;</title>",
224
- render("<title><%= value %></title>", value: '</title>')
224
+ render("<title><%= value %></title>", locals: { value: '</title>' })
225
225
  end
226
226
 
227
227
  test "html_safe interpolation into rawtext tag" do
228
228
  assert_equal "<title><safe></title>",
229
- render("<title><%= value %></title>", value: '<safe>'.html_safe)
229
+ render("<title><%= value %></title>", locals: { value: '<safe>'.html_safe })
230
230
  end
231
231
 
232
232
  test "html_safe interpolation terminating the current tag" do
233
233
  e = assert_raises(BetterHtml::UnsafeHtmlError) do
234
- render("<title><%= value %></title>", value: '</title>'.html_safe)
234
+ render("<title><%= value %></title>", locals: { value: '</title>'.html_safe })
235
235
  end
236
236
  assert_equal "Detected invalid characters as part of the interpolation "\
237
237
  "into a title tag around: <title><%= value %>.", e.message
@@ -273,7 +273,7 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
273
273
 
274
274
  test "can interpolate method calls without parenthesis" do
275
275
  assert_equal "<div>foo</div>",
276
- render("<div><%= send 'value' %></div>", value: 'foo')
276
+ render("<div><%= send 'value' %></div>", locals: { value: 'foo' })
277
277
  end
278
278
 
279
279
  test "tag names are validated against tag_name_pattern regexp" do
@@ -290,16 +290,16 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
290
290
  e = assert_raises(BetterHtml::HtmlError) do
291
291
  render("<foo bar_baz=\"1\">")
292
292
  end
293
- assert_equal "Invalid attribute name \"bar_baz\" does not match regular expression #{BetterHtml.config.partial_attribute_name_pattern.inspect}\n"\
293
+ assert_equal "Invalid attribute name \"bar_baz\" does not match regular expression #{build_config.partial_attribute_name_pattern.inspect}\n"\
294
294
  "On line 1 column 5:\n"\
295
295
  "<foo bar_baz=\"1\">\n"\
296
296
  " ^^^^^^^", e.message
297
297
  end
298
298
 
299
299
  test "single quotes are disallowed when allow_single_quoted_attributes=false" do
300
- BetterHtml.config.stubs(:allow_single_quoted_attributes).returns(false)
300
+ config = build_config(allow_single_quoted_attributes: false)
301
301
  e = assert_raises(BetterHtml::HtmlError) do
302
- render("<foo bar='1'>")
302
+ render("<foo bar='1'>", config: config)
303
303
  end
304
304
  assert_equal "Single-quoted attributes are not allowed\n"\
305
305
  "On line 1 column 9:\n"\
@@ -308,16 +308,16 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
308
308
  end
309
309
 
310
310
  test "single quotes are allowed when allow_single_quoted_attributes=true" do
311
- BetterHtml.config.stubs(:allow_single_quoted_attributes).returns(true)
311
+ config = build_config(allow_single_quoted_attributes: true)
312
312
  assert_nothing_raised do
313
- render("<foo bar='1'>")
313
+ render("<foo bar='1'>", config: config)
314
314
  end
315
315
  end
316
316
 
317
317
  test "unquoted values are disallowed when allow_unquoted_attributes=false" do
318
- BetterHtml.config.stubs(:allow_unquoted_attributes).returns(false)
318
+ config = build_config(allow_unquoted_attributes: false)
319
319
  e = assert_raises(BetterHtml::HtmlError) do
320
- render("<foo bar=1>")
320
+ render("<foo bar=1>", config: config)
321
321
  end
322
322
  assert_equal "Unquoted attribute values are not allowed\n"\
323
323
  "On line 1 column 9:\n"\
@@ -326,9 +326,9 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
326
326
  end
327
327
 
328
328
  test "unquoted values are allowed when allow_unquoted_attributes=true" do
329
- BetterHtml.config.stubs(:allow_unquoted_attributes).returns(true)
329
+ config = build_config(allow_unquoted_attributes: true)
330
330
  assert_nothing_raised do
331
- render("<foo bar=1>")
331
+ render("<foo bar=1>", config: config)
332
332
  end
333
333
  end
334
334
 
@@ -382,9 +382,13 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
382
382
  end
383
383
  end
384
384
 
385
- def render(source, locals={})
385
+ def build_config(**options)
386
+ BetterHtml::Config.new(**options)
387
+ end
388
+
389
+ def render(source, config: build_config, locals: {})
386
390
  context = ViewContext.new(locals)
387
- impl = compile(source)
391
+ impl = compile(source, config: config)
388
392
  if ActionView.version < Gem::Version.new("5.1")
389
393
  impl.result(context.get_binding)
390
394
  else
@@ -392,11 +396,11 @@ class BetterHtml::BetterErb::ImplementationTest < ActiveSupport::TestCase
392
396
  end
393
397
  end
394
398
 
395
- def compile(source)
399
+ def compile(source, config: build_config)
396
400
  if ActionView.version < Gem::Version.new("5.1")
397
- BetterHtml::BetterErb::ErubisImplementation.new(source)
401
+ BetterHtml::BetterErb::ErubisImplementation.new(source, config: config)
398
402
  else
399
- BetterHtml::BetterErb::ErubiImplementation.new(source)
403
+ BetterHtml::BetterErb::ErubiImplementation.new(source, config: config)
400
404
  end
401
405
  end
402
406
  end
@@ -5,12 +5,10 @@ module BetterHtml
5
5
  module TestHelper
6
6
  class SafeErbTesterTest < ActiveSupport::TestCase
7
7
  setup do
8
- BetterHtml.config
9
- .stubs(:javascript_safe_methods)
10
- .returns(['j', 'escape_javascript', 'to_json'])
11
- BetterHtml.config
12
- .stubs(:javascript_attribute_names)
13
- .returns([/\Aon/i, 'data-eval'])
8
+ @config = BetterHtml::Config.new(
9
+ javascript_safe_methods: ['j', 'escape_javascript', 'to_json'],
10
+ javascript_attribute_names: [/\Aon/i, 'data-eval'],
11
+ )
14
12
  end
15
13
 
16
14
  test "string without interpolation is safe" do
@@ -390,9 +388,17 @@ module BetterHtml
390
388
  assert_equal "erb interpolation in javascript attribute must call '(...).to_json'", errors.first.message
391
389
  end
392
390
 
391
+ test "ivar missing .to_json is unsafe" do
392
+ errors = parse('<script><%= @feature.html_safe %></script>').errors
393
+
394
+ assert_equal 1, errors.size
395
+ assert_equal "<%= @feature.html_safe %>", errors.first.location.source
396
+ assert_equal "erb interpolation in javascript tag must call '(...).to_json'", errors.first.message
397
+ end
398
+
393
399
  private
394
400
  def parse(data, template_language: :html)
395
- SafeErbTester::Tester.new(data, template_language: template_language)
401
+ SafeErbTester::Tester.new(data, config: @config, template_language: template_language)
396
402
  end
397
403
  end
398
404
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_html
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Francois Chagnon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-06 00:00:00.000000000 Z
11
+ date: 2017-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erubi
@@ -66,6 +66,34 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: smart_properties
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: html_tokenizer
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: rake
71
99
  requirement: !ruby/object:Gem::Requirement
@@ -96,6 +124,7 @@ files:
96
124
  - lib/better_html/better_erb/erubis_implementation.rb
97
125
  - lib/better_html/better_erb/runtime_checks.rb
98
126
  - lib/better_html/better_erb/validated_output_buffer.rb
127
+ - lib/better_html/config.rb
99
128
  - lib/better_html/errors.rb
100
129
  - lib/better_html/helpers.rb
101
130
  - lib/better_html/html_attributes.rb