better_html 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +7 -1
- data/ext/better_html_ext/html_tokenizer.c +1 -1
- data/ext/better_html_ext/parser.c +2 -1
- data/lib/better_html/better_erb/runtime_checks.rb +4 -3
- data/lib/better_html/better_erb/validated_output_buffer.rb +17 -17
- data/lib/better_html/better_erb.rb +12 -2
- data/lib/better_html/config.rb +1 -0
- data/lib/better_html/html_attributes.rb +1 -1
- data/lib/better_html/parser.rb +16 -7
- data/lib/better_html/railtie.rb +4 -0
- data/lib/better_html/test_helper/safe_erb/allowed_script_type.rb +2 -2
- data/lib/better_html/test_helper/safe_erb/tag_interpolation.rb +21 -11
- data/lib/better_html/test_helper/safe_erb_tester.rb +1 -1
- data/lib/better_html/test_helper/safe_lodash_tester.rb +6 -6
- data/lib/better_html/tokenizer/base_erb.rb +2 -2
- data/lib/better_html/tokenizer/html_lodash.rb +1 -1
- data/lib/better_html/tokenizer/location.rb +1 -1
- data/lib/better_html/version.rb +1 -1
- data/lib/tasks/better_html_tasks.rake +1 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f1644bc4ce488d46cba781f055a90e82b5660cd66600a0452070dedaeda9543
|
4
|
+
data.tar.gz: 053d1b7f7c078f5a3b7999480d180ccfd6eaddd0149bfe9c43086b1d77fb4e1f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d764cd009cec9d23f767a69ddde688f7949a1236809942e9fd927c10f6f5efbcad2ae8a6adec0395e959ac8284f38a606b44dd3962b980ca56c7dea256752050
|
7
|
+
data.tar.gz: 92b47eb924dcbb7ac773176765b8bfb486d9f851e54958485622064de757e33a1167afc4112ff58f343ab23fcee98de24228d17b8c10d515b436bca07eea8039
|
data/Rakefile
CHANGED
@@ -8,7 +8,9 @@ rescue LoadError
|
|
8
8
|
end
|
9
9
|
|
10
10
|
require "rake/extensiontask"
|
11
|
+
require "ruby_memcheck"
|
11
12
|
|
13
|
+
RubyMemcheck.config(binary_name: "better_html_ext")
|
12
14
|
Rake::ExtensionTask.new("better_html_ext")
|
13
15
|
|
14
16
|
require "rdoc/task"
|
@@ -23,11 +25,15 @@ end
|
|
23
25
|
|
24
26
|
require "rake/testtask"
|
25
27
|
|
26
|
-
|
28
|
+
test_config = lambda do |t|
|
27
29
|
t.libs << "lib"
|
28
30
|
t.libs << "test"
|
29
31
|
t.pattern = "test/**/*_test.rb"
|
30
32
|
t.verbose = false
|
31
33
|
end
|
34
|
+
Rake::TestTask.new(test: :compile, &test_config)
|
35
|
+
namespace :test do
|
36
|
+
RubyMemcheck::TestTask.new(valgrind: :compile, &test_config)
|
37
|
+
end
|
32
38
|
|
33
39
|
task default: [:compile, :test]
|
@@ -1,4 +1,5 @@
|
|
1
1
|
#include <ruby.h>
|
2
|
+
#include <ruby/util.h>
|
2
3
|
#include <ruby/encoding.h>
|
3
4
|
#include "html_tokenizer.h"
|
4
5
|
#include "parser.h"
|
@@ -81,7 +82,7 @@ static inline void parser_append_ref(struct token_reference_t *dest, struct toke
|
|
81
82
|
static void parser_add_error(struct parser_t *parser, const char *message)
|
82
83
|
{
|
83
84
|
REALLOC_N(parser->errors, struct parser_document_error_t, parser->errors_count + 1);
|
84
|
-
parser->errors[parser->errors_count].message =
|
85
|
+
parser->errors[parser->errors_count].message = ruby_strdup(message);
|
85
86
|
parser->errors[parser->errors_count].pos = parser->tk.scan.cursor;
|
86
87
|
parser->errors[parser->errors_count].mb_pos = parser->tk.scan.mb_cursor;
|
87
88
|
parser->errors[parser->errors_count].line_number = parser->doc.line_number;
|
@@ -119,7 +119,7 @@ module BetterHtml
|
|
119
119
|
return if text.upcase == "!DOCTYPE"
|
120
120
|
return if @config.partial_tag_name_pattern.match?(text)
|
121
121
|
|
122
|
-
s = +"Invalid tag name #{text.inspect} does not match "\
|
122
|
+
s = +"Invalid tag name #{text.inspect} does not match " \
|
123
123
|
"regular expression #{@config.partial_tag_name_pattern.inspect}\n"
|
124
124
|
s << build_location(line, column, text.size)
|
125
125
|
raise BetterHtml::HtmlError, s
|
@@ -129,7 +129,7 @@ module BetterHtml
|
|
129
129
|
text = @parser.document[start...stop]
|
130
130
|
return if @config.partial_attribute_name_pattern.match?(text)
|
131
131
|
|
132
|
-
s = +"Invalid attribute name #{text.inspect} does not match "\
|
132
|
+
s = +"Invalid attribute name #{text.inspect} does not match " \
|
133
133
|
"regular expression #{@config.partial_attribute_name_pattern.inspect}\n"
|
134
134
|
s << build_location(line, column, text.size)
|
135
135
|
raise BetterHtml::HtmlError, s
|
@@ -155,7 +155,8 @@ module BetterHtml
|
|
155
155
|
end
|
156
156
|
|
157
157
|
def build_location(line, column, length)
|
158
|
-
s = +"
|
158
|
+
s = filename ? +"In #{filename}\n" : +""
|
159
|
+
s << "On line #{line} column #{column}:\n"
|
159
160
|
s << "#{extract_line(line)}\n"
|
160
161
|
s << "#{" " * column}#{"^" * length}"
|
161
162
|
end
|
@@ -17,7 +17,7 @@ module BetterHtml
|
|
17
17
|
value = properly_escaped(value)
|
18
18
|
|
19
19
|
if value.include?(@context[:quote_character])
|
20
|
-
raise UnsafeHtmlError, "Detected invalid characters as part of the interpolation "\
|
20
|
+
raise UnsafeHtmlError, "Detected invalid characters as part of the interpolation " \
|
21
21
|
"into a quoted attribute value. The value cannot contain the character #{@context[:quote_character]}."
|
22
22
|
end
|
23
23
|
|
@@ -25,15 +25,15 @@ module BetterHtml
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def safe_unquoted_value_append=(value)
|
28
|
-
raise DontInterpolateHere, "Do not interpolate without quotes around this "\
|
29
|
-
"attribute value. Instead of "\
|
30
|
-
"<#{@context[:tag_name]} #{@context[:attribute_name]}=#{@context[:attribute_value]}<%=#{@code}%>> "\
|
28
|
+
raise DontInterpolateHere, "Do not interpolate without quotes around this " \
|
29
|
+
"attribute value. Instead of " \
|
30
|
+
"<#{@context[:tag_name]} #{@context[:attribute_name]}=#{@context[:attribute_value]}<%=#{@code}%>> " \
|
31
31
|
"try <#{@context[:tag_name]} #{@context[:attribute_name]}=\"#{@context[:attribute_value]}<%=#{@code}%>\">."
|
32
32
|
end
|
33
33
|
|
34
34
|
def safe_space_after_attribute_append=(value)
|
35
|
-
raise DontInterpolateHere, "Add a space after this attribute value. Instead of "\
|
36
|
-
"<#{@context[:tag_name]} #{@context[:attribute_name]}=\"#{@context[:attribute_value]}\"<%=#{@code}%>> "\
|
35
|
+
raise DontInterpolateHere, "Add a space after this attribute value. Instead of " \
|
36
|
+
"<#{@context[:tag_name]} #{@context[:attribute_name]}=\"#{@context[:attribute_value]}\"<%=#{@code}%>> " \
|
37
37
|
"try <#{@context[:tag_name]} #{@context[:attribute_name]}=\"#{@context[:attribute_value]}\" <%=#{@code}%>>."
|
38
38
|
end
|
39
39
|
|
@@ -43,7 +43,7 @@ module BetterHtml
|
|
43
43
|
value = value.to_s
|
44
44
|
|
45
45
|
unless value =~ /\A[a-z0-9\-]*\z/
|
46
|
-
raise UnsafeHtmlError, "Detected invalid characters as part of the interpolation "\
|
46
|
+
raise UnsafeHtmlError, "Detected invalid characters as part of the interpolation " \
|
47
47
|
"into a attribute name around '#{@context[:attribute_name]}<%=#{@code}%>'."
|
48
48
|
end
|
49
49
|
|
@@ -54,8 +54,8 @@ module BetterHtml
|
|
54
54
|
return if value.nil?
|
55
55
|
|
56
56
|
unless value.is_a?(BetterHtml::HtmlAttributes)
|
57
|
-
raise DontInterpolateHere, "Do not interpolate #{value.class} in a tag. "\
|
58
|
-
"Instead of <#{@context[:tag_name]} <%=#{@code}%>> please "\
|
57
|
+
raise DontInterpolateHere, "Do not interpolate #{value.class} in a tag. " \
|
58
|
+
"Instead of <#{@context[:tag_name]} <%=#{@code}%>> please " \
|
59
59
|
"try <#{@context[:tag_name]} <%= html_attributes(attr: value) %>>."
|
60
60
|
end
|
61
61
|
|
@@ -63,7 +63,7 @@ module BetterHtml
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def safe_after_equal_append=(value)
|
66
|
-
raise DontInterpolateHere, "Do not interpolate without quotes after "\
|
66
|
+
raise DontInterpolateHere, "Do not interpolate without quotes after " \
|
67
67
|
"attribute around '#{@context[:attribute_name]}=<%=#{@code}%>'."
|
68
68
|
end
|
69
69
|
|
@@ -71,8 +71,8 @@ module BetterHtml
|
|
71
71
|
return if value.nil?
|
72
72
|
|
73
73
|
unless value.is_a?(BetterHtml::HtmlAttributes)
|
74
|
-
raise DontInterpolateHere, "Do not interpolate #{value.class} in a tag. "\
|
75
|
-
"Instead of <#{@context[:tag_name]} <%=#{@code}%>> please "\
|
74
|
+
raise DontInterpolateHere, "Do not interpolate #{value.class} in a tag. " \
|
75
|
+
"Instead of <#{@context[:tag_name]} <%=#{@code}%>> please " \
|
76
76
|
"try <#{@context[:tag_name]} <%= html_attributes(attr: value) %>>."
|
77
77
|
end
|
78
78
|
|
@@ -85,7 +85,7 @@ module BetterHtml
|
|
85
85
|
value = value.to_s
|
86
86
|
|
87
87
|
unless value =~ /\A[a-z0-9\:\-]*\z/
|
88
|
-
raise UnsafeHtmlError, "Detected invalid characters as part of the interpolation "\
|
88
|
+
raise UnsafeHtmlError, "Detected invalid characters as part of the interpolation " \
|
89
89
|
"into a tag name around: <#{@context[:tag_name]}<%=#{@code}%>>."
|
90
90
|
end
|
91
91
|
|
@@ -100,12 +100,12 @@ module BetterHtml
|
|
100
100
|
if @context[:tag_name].downcase == "script" &&
|
101
101
|
(value =~ /<script/i || value =~ %r{</script}i)
|
102
102
|
# https://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements
|
103
|
-
raise UnsafeHtmlError, "Detected invalid characters as part of the interpolation "\
|
104
|
-
"into a script tag around: <#{@context[:tag_name]}>#{@context[:rawtext_text]}<%=#{@code}%>. "\
|
103
|
+
raise UnsafeHtmlError, "Detected invalid characters as part of the interpolation " \
|
104
|
+
"into a script tag around: <#{@context[:tag_name]}>#{@context[:rawtext_text]}<%=#{@code}%>. " \
|
105
105
|
"A script tag cannot contain <script or </script anywhere inside of it."
|
106
106
|
elsif value =~ /<#{Regexp.escape(@context[:tag_name].downcase)}/i ||
|
107
107
|
value =~ %r{</#{Regexp.escape(@context[:tag_name].downcase)}}i
|
108
|
-
raise UnsafeHtmlError, "Detected invalid characters as part of the interpolation "\
|
108
|
+
raise UnsafeHtmlError, "Detected invalid characters as part of the interpolation " \
|
109
109
|
"into a #{@context[:tag_name].downcase} tag around: " \
|
110
110
|
"<#{@context[:tag_name]}>#{@context[:rawtext_text]}<%=#{@code}%>."
|
111
111
|
end
|
@@ -120,7 +120,7 @@ module BetterHtml
|
|
120
120
|
|
121
121
|
# in a <!-- ...here --> we disallow -->
|
122
122
|
if value =~ /-->/
|
123
|
-
raise UnsafeHtmlError, "Detected invalid characters as part of the interpolation "\
|
123
|
+
raise UnsafeHtmlError, "Detected invalid characters as part of the interpolation " \
|
124
124
|
"into a html comment around: <!--#{@context[:comment_text]}<%=#{@code}%>."
|
125
125
|
end
|
126
126
|
|
@@ -52,10 +52,20 @@ module BetterHtml
|
|
52
52
|
klass ||= self.class.erb_implementation
|
53
53
|
|
54
54
|
escape = self.class.escape_ignore_list.include?(template.type)
|
55
|
+
|
56
|
+
options = {
|
57
|
+
escape: escape,
|
58
|
+
trim: (self.class.erb_trim_mode == "-"),
|
59
|
+
}
|
60
|
+
if BetterHtml.config.annotate_rendered_view_with_filenames && template.format == :html
|
61
|
+
options[:preamble] = "@output_buffer.safe_append='<!-- BEGIN #{template.short_identifier} -->';"
|
62
|
+
options[:postamble] = "@output_buffer.safe_append='<!-- END #{template.short_identifier} -->';" \
|
63
|
+
"@output_buffer.to_s"
|
64
|
+
end
|
65
|
+
|
55
66
|
generator = klass.new(
|
56
67
|
erb,
|
57
|
-
|
58
|
-
trim: (self.class.erb_trim_mode == "-")
|
68
|
+
**options,
|
59
69
|
)
|
60
70
|
generator.validate! if generator.respond_to?(:validate!)
|
61
71
|
generator.src
|
data/lib/better_html/config.rb
CHANGED
@@ -15,6 +15,7 @@ module BetterHtml
|
|
15
15
|
property :template_exclusion_filter
|
16
16
|
property :lodash_safe_javascript_expression, default: -> { [/\AJSON\.stringify\(/] }
|
17
17
|
property :disable_parser_validation, default: false
|
18
|
+
property :annotate_rendered_view_with_filenames, default: false
|
18
19
|
|
19
20
|
def javascript_attribute_name?(name)
|
20
21
|
javascript_attribute_names.any? { |other| other === name.to_s } # rubocop:disable Style/CaseEquality
|
@@ -19,7 +19,7 @@ module BetterHtml
|
|
19
19
|
value = value.to_s
|
20
20
|
escaped_value = value.html_safe? ? value : CGI.escapeHTML(value)
|
21
21
|
if escaped_value.include?('"')
|
22
|
-
raise ArgumentError, "The value provided for attribute '#{key}' contains a `\"` "\
|
22
|
+
raise ArgumentError, "The value provided for attribute '#{key}' contains a `\"` " \
|
23
23
|
"character which is not allowed. Did you call .html_safe without properly escaping this data?"
|
24
24
|
end
|
25
25
|
"#{key}=\"#{escaped_value}\""
|
data/lib/better_html/parser.rb
CHANGED
@@ -53,7 +53,7 @@ module BetterHtml
|
|
53
53
|
@erb.parser.errors.map do |error|
|
54
54
|
Error.new(
|
55
55
|
error.message,
|
56
|
-
location: Tokenizer::Location.new(@buffer, error.position, error.position + 1)
|
56
|
+
location: Tokenizer::Location.new(@buffer, error.position, error.position + 1),
|
57
57
|
)
|
58
58
|
end
|
59
59
|
end
|
@@ -183,9 +183,13 @@ module BetterHtml
|
|
183
183
|
end
|
184
184
|
|
185
185
|
def build_attribute_value_node(tokens)
|
186
|
-
children = shift_all_with_interpolation(
|
187
|
-
|
188
|
-
:
|
186
|
+
children = shift_all_with_interpolation(
|
187
|
+
tokens,
|
188
|
+
:attribute_quoted_value_start,
|
189
|
+
:attribute_quoted_value,
|
190
|
+
:attribute_quoted_value_end,
|
191
|
+
:attribute_unquoted_value,
|
192
|
+
)
|
189
193
|
|
190
194
|
build_node(:attribute_value, children)
|
191
195
|
end
|
@@ -199,7 +203,7 @@ module BetterHtml
|
|
199
203
|
BetterHtml::AST::Node.new(
|
200
204
|
type,
|
201
205
|
tokens.present? ? wrap_tokens(tokens) : [],
|
202
|
-
loc: tokens.present? ? build_location([pre, *tokens, post]) : empty_location
|
206
|
+
loc: tokens.present? ? build_location([pre, *tokens, post]) : empty_location,
|
203
207
|
)
|
204
208
|
end
|
205
209
|
|
@@ -298,8 +302,13 @@ module BetterHtml
|
|
298
302
|
|
299
303
|
if object.is_a?(::AST::Node)
|
300
304
|
object
|
301
|
-
elsif [
|
302
|
-
|
305
|
+
elsif [
|
306
|
+
:text,
|
307
|
+
:tag_name,
|
308
|
+
:attribute_name,
|
309
|
+
:attribute_quoted_value,
|
310
|
+
:attribute_unquoted_value,
|
311
|
+
].include?(object.type)
|
303
312
|
object.loc.source
|
304
313
|
elsif [:attribute_quoted_value_start, :attribute_quoted_value_end].include?(object.type)
|
305
314
|
BetterHtml::AST::Node.new(:quote, [object.loc.source], loc: object.loc)
|
data/lib/better_html/railtie.rb
CHANGED
@@ -6,6 +6,10 @@ module BetterHtml
|
|
6
6
|
class Railtie < Rails::Railtie
|
7
7
|
initializer "better_html.better_erb.initialization" do
|
8
8
|
BetterHtml::BetterErb.prepend!
|
9
|
+
|
10
|
+
ActiveSupport.on_load(:action_view) do
|
11
|
+
BetterHtml.config.annotate_rendered_view_with_filenames = ActionView::Base.annotate_rendered_view_with_filenames
|
12
|
+
end
|
9
13
|
end
|
10
14
|
end
|
11
15
|
end
|
@@ -6,7 +6,7 @@ module BetterHtml
|
|
6
6
|
module TestHelper
|
7
7
|
module SafeErb
|
8
8
|
class AllowedScriptType < Base
|
9
|
-
VALID_JAVASCRIPT_TAG_TYPES = ["application/ld+json", "text/javascript", "text/template", "text/html"]
|
9
|
+
VALID_JAVASCRIPT_TAG_TYPES = ["application/ld+json", "text/javascript", "text/template", "text/html", "module"]
|
10
10
|
|
11
11
|
def validate
|
12
12
|
script_tags.each do |tag, _|
|
@@ -24,7 +24,7 @@ module BetterHtml
|
|
24
24
|
|
25
25
|
add_error(
|
26
26
|
"#{type_attribute.value} is not a valid type, valid types are #{VALID_JAVASCRIPT_TAG_TYPES.join(", ")}",
|
27
|
-
location: type_attribute.loc
|
27
|
+
location: type_attribute.loc,
|
28
28
|
)
|
29
29
|
end
|
30
30
|
end
|
@@ -7,8 +7,18 @@ module BetterHtml
|
|
7
7
|
module TestHelper
|
8
8
|
module SafeErb
|
9
9
|
class TagInterpolation < Base
|
10
|
-
NO_HTML_TAGS = [
|
11
|
-
|
10
|
+
NO_HTML_TAGS = [
|
11
|
+
"title",
|
12
|
+
"textarea",
|
13
|
+
"script",
|
14
|
+
"style",
|
15
|
+
"xmp",
|
16
|
+
"iframe",
|
17
|
+
"noembed",
|
18
|
+
"noframes",
|
19
|
+
"listing",
|
20
|
+
"plaintext",
|
21
|
+
]
|
12
22
|
|
13
23
|
def validate
|
14
24
|
@parser.nodes_with_type(:tag).each do |tag_node|
|
@@ -28,8 +38,8 @@ module BetterHtml
|
|
28
38
|
def no_html_tag?(node)
|
29
39
|
ast = @parser.ast.to_a
|
30
40
|
index = ast.find_index(node)
|
31
|
-
return unless (previous_node = ast[index - 1])
|
32
|
-
return unless previous_node.type == :tag
|
41
|
+
return false unless (previous_node = ast[index - 1])
|
42
|
+
return false unless previous_node.type == :tag
|
33
43
|
|
34
44
|
tag = BetterHtml::Tree::Tag.from_node(previous_node)
|
35
45
|
NO_HTML_TAGS.include?(tag.name) && !tag.closing?
|
@@ -57,7 +67,7 @@ module BetterHtml
|
|
57
67
|
elsif indicator == "=="
|
58
68
|
add_error(
|
59
69
|
"erb interpolation with '<%==' inside html attribute is never safe",
|
60
|
-
location: erb_node.loc
|
70
|
+
location: erb_node.loc,
|
61
71
|
)
|
62
72
|
end
|
63
73
|
end
|
@@ -122,14 +132,14 @@ module BetterHtml
|
|
122
132
|
if method_calls.empty?
|
123
133
|
add_error(
|
124
134
|
"erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'",
|
125
|
-
location: nested_location(parent_node, ruby_node)
|
135
|
+
location: nested_location(parent_node, ruby_node),
|
126
136
|
)
|
127
137
|
true
|
128
138
|
elsif unsafe_calls.any?
|
129
139
|
unsafe_calls.each do |call_node|
|
130
140
|
add_error(
|
131
141
|
"erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'",
|
132
|
-
location: nested_location(parent_node, call_node)
|
142
|
+
location: nested_location(parent_node, call_node),
|
133
143
|
)
|
134
144
|
end
|
135
145
|
true
|
@@ -148,7 +158,7 @@ module BetterHtml
|
|
148
158
|
|
149
159
|
add_error(
|
150
160
|
"erb interpolation in javascript attribute must be wrapped in safe helper such as '(...).to_json'",
|
151
|
-
location: nested_location(parent_node, ruby_node)
|
161
|
+
location: nested_location(parent_node, ruby_node),
|
152
162
|
)
|
153
163
|
end
|
154
164
|
end
|
@@ -158,12 +168,12 @@ module BetterHtml
|
|
158
168
|
if call.method_name?(:raw)
|
159
169
|
add_error(
|
160
170
|
"erb interpolation with '<%= raw(...) %>' in this context is never safe",
|
161
|
-
location: nested_location(parent_node, ruby_node)
|
171
|
+
location: nested_location(parent_node, ruby_node),
|
162
172
|
)
|
163
173
|
elsif call.method_name?(:html_safe)
|
164
174
|
add_error(
|
165
175
|
"erb interpolation with '<%= (...).html_safe %>' in this context is never safe",
|
166
|
-
location: nested_location(parent_node, ruby_node)
|
176
|
+
location: nested_location(parent_node, ruby_node),
|
167
177
|
)
|
168
178
|
end
|
169
179
|
end
|
@@ -173,7 +183,7 @@ module BetterHtml
|
|
173
183
|
Tokenizer::Location.new(
|
174
184
|
parent_node.loc.source_buffer,
|
175
185
|
parent_node.loc.begin_pos + ruby_node.loc.expression.begin_pos,
|
176
|
-
parent_node.loc.begin_pos + ruby_node.loc.expression.end_pos
|
186
|
+
parent_node.loc.begin_pos + ruby_node.loc.expression.end_pos,
|
177
187
|
)
|
178
188
|
end
|
179
189
|
end
|
@@ -41,7 +41,7 @@ module BetterHtml
|
|
41
41
|
options[:template_language] ||= :html
|
42
42
|
buffer = ::Parser::Source::Buffer.new(options[:filename] || "(buffer)")
|
43
43
|
buffer.source = data
|
44
|
-
parser = BetterHtml::Parser.new(buffer,
|
44
|
+
parser = BetterHtml::Parser.new(buffer, template_language: options[:template_language])
|
45
45
|
|
46
46
|
tester_classes = [
|
47
47
|
SafeErb::NoStatements,
|
@@ -35,7 +35,7 @@ module BetterHtml
|
|
35
35
|
buffer.source = data
|
36
36
|
tester = Tester.new(buffer, **options)
|
37
37
|
|
38
|
-
message = ""
|
38
|
+
message = +""
|
39
39
|
tester.errors.each do |error|
|
40
40
|
message << <<~EOL
|
41
41
|
On line #{error.location.line}
|
@@ -74,7 +74,7 @@ module BetterHtml
|
|
74
74
|
|
75
75
|
add_error(
|
76
76
|
"No script tags allowed nested in lodash templates",
|
77
|
-
location: tag_node.loc
|
77
|
+
location: tag_node.loc,
|
78
78
|
)
|
79
79
|
end
|
80
80
|
|
@@ -104,7 +104,7 @@ module BetterHtml
|
|
104
104
|
elsif indicator_node.loc.source == "!"
|
105
105
|
add_error(
|
106
106
|
"lodash interpolation with '[%!' inside html attribute is never safe",
|
107
|
-
location: lodash_node.loc
|
107
|
+
location: lodash_node.loc,
|
108
108
|
)
|
109
109
|
end
|
110
110
|
end
|
@@ -116,9 +116,9 @@ module BetterHtml
|
|
116
116
|
source = code_node.loc.source.strip
|
117
117
|
if @config.javascript_attribute_name?(attribute.name) && !@config.lodash_safe_javascript_expression?(source)
|
118
118
|
add_error(
|
119
|
-
"lodash interpolation in javascript attribute "\
|
119
|
+
"lodash interpolation in javascript attribute " \
|
120
120
|
"`#{attribute.name}` must call `JSON.stringify(#{source})`",
|
121
|
-
location: lodash_node.loc
|
121
|
+
location: lodash_node.loc,
|
122
122
|
)
|
123
123
|
end
|
124
124
|
end
|
@@ -132,7 +132,7 @@ module BetterHtml
|
|
132
132
|
def add_no_statement_error(loc)
|
133
133
|
add_error(
|
134
134
|
"javascript statement not allowed here; did you mean '[%=' ?",
|
135
|
-
location: loc
|
135
|
+
location: loc,
|
136
136
|
)
|
137
137
|
end
|
138
138
|
end
|
@@ -10,7 +10,7 @@ module BetterHtml
|
|
10
10
|
class BaseErb < ::Erubi::Engine
|
11
11
|
REGEXP_WITHOUT_TRIM = /<%(={1,2})?(.*?)()?%>([ \t]*\r?\n)?/m
|
12
12
|
STMT_TRIM_MATCHER = /\A(-|#)?(.*?)([-=])?\z/m
|
13
|
-
EXPR_TRIM_MATCHER = /\A(.*?)(
|
13
|
+
EXPR_TRIM_MATCHER = /\A(.*?)([-=])?\z/m
|
14
14
|
|
15
15
|
attr_reader :tokens
|
16
16
|
attr_reader :current_position
|
@@ -80,7 +80,7 @@ module BetterHtml
|
|
80
80
|
def add_token(type, begin_pos, end_pos)
|
81
81
|
token = Token.new(
|
82
82
|
type: type,
|
83
|
-
loc: Location.new(@buffer, begin_pos, end_pos)
|
83
|
+
loc: Location.new(@buffer, begin_pos, end_pos),
|
84
84
|
)
|
85
85
|
@tokens << token
|
86
86
|
token
|
@@ -39,7 +39,7 @@ module BetterHtml
|
|
39
39
|
def line_source_with_underline
|
40
40
|
spaces = source_line.scan(/\A\s*/).first
|
41
41
|
column_without_spaces = [column - spaces.length, 0].max
|
42
|
-
underscore_length =
|
42
|
+
underscore_length = (end_pos - begin_pos).clamp(1, (source_line.length - column_without_spaces))
|
43
43
|
"#{source_line.gsub(/\A\s*/, "")}\n#{" " * column_without_spaces}#{"^" * underscore_length}"
|
44
44
|
end
|
45
45
|
|
data/lib/better_html/version.rb
CHANGED
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: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Francois Chagnon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionview
|
@@ -168,7 +168,7 @@ licenses:
|
|
168
168
|
metadata:
|
169
169
|
bug_tracker_uri: https://github.com/Shopify/better-html/issues
|
170
170
|
changelog_uri: https://github.com/Shopify/better-html/releases
|
171
|
-
source_code_uri: https://github.com/Shopify/better-html/tree/v2.0
|
171
|
+
source_code_uri: https://github.com/Shopify/better-html/tree/v2.1.0
|
172
172
|
allowed_push_host: https://rubygems.org
|
173
173
|
post_install_message:
|
174
174
|
rdoc_options: []
|
@@ -178,14 +178,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
178
178
|
requirements:
|
179
179
|
- - ">="
|
180
180
|
- !ruby/object:Gem::Version
|
181
|
-
version:
|
181
|
+
version: 3.0.0
|
182
182
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
183
|
requirements:
|
184
184
|
- - ">="
|
185
185
|
- !ruby/object:Gem::Version
|
186
186
|
version: '0'
|
187
187
|
requirements: []
|
188
|
-
rubygems_version: 3.
|
188
|
+
rubygems_version: 3.5.6
|
189
189
|
signing_key:
|
190
190
|
specification_version: 4
|
191
191
|
summary: Better HTML for Rails.
|