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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac75570144a95e0a5a28f54dc99f265192ec4727d96b960ada7a97fd47851194
4
- data.tar.gz: a29a57f1969999dd394336dd785facc3ca5432e326397e0c4dcfb745f7df79b9
3
+ metadata.gz: 3f1644bc4ce488d46cba781f055a90e82b5660cd66600a0452070dedaeda9543
4
+ data.tar.gz: 053d1b7f7c078f5a3b7999480d180ccfd6eaddd0149bfe9c43086b1d77fb4e1f
5
5
  SHA512:
6
- metadata.gz: 0341b84eb8f09fe099f3aefe91edad0e99064113070336d76ebc6d4ffbd341189ee6c8cb41b2011c89ca1e42c63227d2fc41db736e3c3f3ac0474db071c02cf5
7
- data.tar.gz: 725880baa643e0589c6a781dcb28f8437e3ccab29b58d7a460ea1ec4e4bb3320dc6d9ef1b1a770a40909a8c3adaacda623bdb163ef4fa96819a7ec3f40ebca0f
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
- Rake::TestTask.new(:test) do |t|
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]
@@ -4,7 +4,7 @@
4
4
 
5
5
  static VALUE mHtmlTokenizer = Qnil;
6
6
 
7
- void Init_better_html_ext()
7
+ void Init_better_html_ext(void)
8
8
  {
9
9
  mHtmlTokenizer = rb_define_module("HtmlTokenizer");
10
10
  Init_html_tokenizer_tokenizer(mHtmlTokenizer);
@@ -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 = strdup(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 = +"On line #{line} column #{column}:\n"
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
- escape: escape,
58
- trim: (self.class.erb_trim_mode == "-")
68
+ **options,
59
69
  )
60
70
  generator.validate! if generator.respond_to?(:validate!)
61
71
  generator.src
@@ -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}\""
@@ -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(tokens,
187
- :attribute_quoted_value_start, :attribute_quoted_value,
188
- :attribute_quoted_value_end, :attribute_unquoted_value)
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 [:text, :tag_name, :attribute_name, :attribute_quoted_value,
302
- :attribute_unquoted_value,].include?(object.type)
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)
@@ -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 = ["title", "textarea", "script", "style", "xmp", "iframe", "noembed", "noframes", "listing",
11
- "plaintext",]
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, **options)
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(.*?)(-)?\z/m
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
@@ -96,7 +96,7 @@ module BetterHtml
96
96
  def add_token(type, begin_pos: nil, end_pos: nil)
97
97
  token = Token.new(
98
98
  type: type,
99
- loc: Location.new(@buffer, begin_pos, end_pos)
99
+ loc: Location.new(@buffer, begin_pos, end_pos),
100
100
  )
101
101
  @tokens << token
102
102
  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 = [[end_pos - begin_pos, source_line.length - column_without_spaces].min, 1].max
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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BetterHtml
4
- VERSION = "2.0.1"
4
+ VERSION = "2.1.0"
5
5
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # desc "Explaining what the task does"
3
4
  # task :better_html do
4
5
  # # Task goes here
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.1
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: 2022-08-16 00:00:00.000000000 Z
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.1
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: 2.7.0
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.3.3
188
+ rubygems_version: 3.5.6
189
189
  signing_key:
190
190
  specification_version: 4
191
191
  summary: Better HTML for Rails.