haml-edge 2.3.39 → 2.3.40

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.
data/EDGE_GEM_VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.39
1
+ 2.3.40
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.39
1
+ 2.3.40
data/lib/haml/engine.rb CHANGED
@@ -96,6 +96,8 @@ module Haml
96
96
  @options[:encoding] = @options[:encoding].name
97
97
  end
98
98
 
99
+ check_encoding(template) {|msg, line| raise Haml::Error.new(msg, line)}
100
+
99
101
  # :eod is a special end-of-document marker
100
102
  @template = (template.rstrip).split(/\r\n|\r|\n/) + [:eod, :eod]
101
103
  @template_index = 0
@@ -111,7 +113,9 @@ module Haml
111
113
 
112
114
  precompile
113
115
  rescue Haml::Error => e
114
- e.backtrace.unshift "#{@options[:filename]}:#{(e.line ? e.line + 1 : @index) + @options[:line] - 1}" if @index
116
+ if @index || e.line
117
+ e.backtrace.unshift "#{@options[:filename]}:#{(e.line ? e.line + 1 : @index) + @options[:line] - 1}"
118
+ end
115
119
  raise
116
120
  end
117
121
 
data/lib/haml/exec.rb CHANGED
@@ -414,6 +414,9 @@ END
414
414
  @module_opts[:rhtml] &&= @options[:no_rhtml] != false
415
415
 
416
416
  output.write(::Haml::HTML.new(input, @module_opts).render)
417
+ rescue ::Haml::Error => e
418
+ raise "#{e.is_a?(::Haml::SyntaxError) ? "Syntax error" : "Error"} on line " +
419
+ "#{get_line e}: #{e.message}"
417
420
  end
418
421
  end
419
422
 
@@ -458,6 +461,9 @@ END
458
461
  output = @options[:output]
459
462
 
460
463
  output.write(::Sass::CSS.new(input, @module_opts).render)
464
+ rescue ::Sass::SyntaxError => e
465
+ raise e if @options[:trace]
466
+ raise "Syntax error on line #{get_line e}: #{e.message}\n Use --trace for backtrace"
461
467
  end
462
468
  end
463
469
  end
data/lib/haml/html.rb CHANGED
@@ -80,6 +80,8 @@ module Haml
80
80
  template = template.read
81
81
  end
82
82
 
83
+ Haml::Util.check_encoding(template) {|msg, line| raise Haml::Error.new(msg, line)}
84
+
83
85
  if @options[:rhtml]
84
86
  match_to_html(template, /<%=(.*?)-?%>/m, 'loud')
85
87
  match_to_html(template, /<%-?(.*?)-?%>/m, 'silent')
@@ -128,9 +130,7 @@ module Haml
128
130
  # @see Haml::HTML::Node#to_haml
129
131
  def to_haml(tabs, options)
130
132
  attrs = public_id.scan(/DTD\s+([^\s]+)\s*([^\s]*)\s*([^\s]*)\s*\/\//)[0]
131
- if attrs == nil
132
- raise Exception.new("Invalid doctype")
133
- end
133
+ raise Haml::SyntaxError.new("Invalid doctype") if attrs == nil
134
134
 
135
135
  type, version, strictness = attrs.map { |a| a.downcase }
136
136
  if type == "html"
data/lib/haml/util.rb CHANGED
@@ -129,6 +129,22 @@ module Haml
129
129
  Haml::Util::RUBY_VERSION[0] == 1 && Haml::Util::RUBY_VERSION[1] < 9
130
130
  end
131
131
 
132
+ def check_encoding(str)
133
+ return if ruby1_8?
134
+ return if str.valid_encoding?
135
+ encoding = str.encoding
136
+ newlines = Regexp.new("\r\n|\r|\n".encode(encoding).force_encoding("binary"))
137
+ str.force_encoding("binary").split(newlines).each_with_index do |line, i|
138
+ begin
139
+ line.encode(encoding)
140
+ rescue Encoding::UndefinedConversionError => e
141
+ yield <<MSG.rstrip, i + 1
142
+ Invalid #{encoding.name} character #{e.error_char.dump}
143
+ MSG
144
+ end
145
+ end
146
+ end
147
+
132
148
  # Checks to see if a class has a given method.
133
149
  # For example:
134
150
  #
data/lib/sass/css.rb CHANGED
@@ -62,11 +62,15 @@ module Sass
62
62
  # @option options :old [Boolean] (false)
63
63
  # Whether or not to output old property syntax
64
64
  # (`:color blue` as opposed to `color: blue`).
65
+ # @option options :filename [String]
66
+ # The filename of the CSS file being processed.
67
+ # Used for error reporting
65
68
  def initialize(template, options = {})
66
69
  if template.is_a? IO
67
70
  template = template.read
68
71
  end
69
72
 
73
+ @line = 1
70
74
  @options = options.dup
71
75
  # Backwards compatibility
72
76
  @options[:old] = true if @options[:alternate] == false
@@ -76,15 +80,16 @@ module Sass
76
80
  # Converts the CSS template into Sass code.
77
81
  #
78
82
  # @return [String] The resulting Sass code
83
+ # @raise [Sass::SyntaxError] if there's an error parsing the CSS template
79
84
  def render
80
- begin
81
- build_tree.to_sass(0, @options).strip + "\n"
82
- rescue Exception => err
83
- line = @template.string[0...@template.pos].split("\n").size
84
-
85
- err.backtrace.unshift "(css):#{line}"
86
- raise err
85
+ Haml::Util.check_encoding(@template.string) do |msg, line|
86
+ raise Sass::SyntaxError.new(msg, :line => line)
87
87
  end
88
+
89
+ build_tree.to_sass(0, @options).strip + "\n"
90
+ rescue Sass::SyntaxError => err
91
+ err.modify_backtrace(:filename => @options[:filename] || '(css)', :line => @line)
92
+ raise err
88
93
  end
89
94
 
90
95
  private
@@ -120,7 +125,7 @@ module Sass
120
125
  def rule
121
126
  rule = ""
122
127
  loop do
123
- token = @template.scan(/(?:[^\{\};\/\s]|\/[^*])+/)
128
+ token = scan(/(?:[^\{\};\/\s]|\/[^*])+/)
124
129
  if token.nil?
125
130
  return if rule.empty?
126
131
  break
@@ -136,7 +141,7 @@ module Sass
136
141
 
137
142
  if directive
138
143
  node = Tree::DirectiveNode.new(rule)
139
- return node if @template.scan(/;/)
144
+ return node if scan(/;/)
140
145
 
141
146
  assert_match /\{/
142
147
  whitespace
@@ -155,14 +160,14 @@ module Sass
155
160
  #
156
161
  # @param rule [Tree::RuleNode] The parent node of the properties
157
162
  def properties(rule)
158
- while @template.scan(/[^:\}\s]+/)
163
+ while scan(/[^:\}\s]+/)
159
164
  name = @template[0]
160
165
  whitespace
161
166
 
162
167
  assert_match /:/
163
168
 
164
169
  value = ''
165
- while @template.scan(/[^;\s\}]+/)
170
+ while scan(/[^;\s\}]+/)
166
171
  value << @template[0] << whitespace
167
172
  end
168
173
 
@@ -177,12 +182,12 @@ module Sass
177
182
  #
178
183
  # @return [String] The ignored whitespace
179
184
  def whitespace
180
- space = @template.scan(/\s*/) || ''
185
+ space = scan(/\s*/) || ''
181
186
 
182
187
  # If we've hit a comment,
183
188
  # go past it and look for more whitespace
184
- if @template.scan(/\/\*/)
185
- @template.scan_until(/\*\//)
189
+ if scan(/\/\*/)
190
+ scan_until(/\*\//)
186
191
  return space + whitespace
187
192
  end
188
193
  return space
@@ -193,26 +198,42 @@ module Sass
193
198
  #
194
199
  # @param re [Regexp] The regular expression to assert
195
200
  def assert_match(re)
196
- if @template.scan(re)
201
+ if scan(re)
197
202
  whitespace
198
203
  return
199
204
  end
200
205
 
201
- line = @template.string[0..@template.pos].count "\n"
202
206
  pos = @template.pos
203
207
 
204
- after = @template.string[pos - 15...pos]
208
+ after = @template.string[[pos - 15, 0].max...pos].gsub(/.*\n/m, '')
205
209
  after = "..." + after if pos >= 15
206
210
 
207
211
  # Display basic regexps as plain old strings
208
- expected = re.source == Regexp.escape(re.source) ? "\"#{re.source}\"" : re.inspect
212
+ string = re.source.gsub(/\\(.)/, '\1')
213
+ expected = re.source == Regexp.escape(string) ? string.inspect : re.inspect
209
214
 
210
- was = @template.rest[0...15]
215
+ was = @template.rest[0...15].gsub(/\n.*/m, '')
211
216
  was += "..." if @template.rest.size >= 15
212
- raise Exception.new(<<MESSAGE)
213
- Invalid CSS on line #{line + 1} after #{after.inspect}:
214
- expected #{expected}, was #{was.inspect}
215
- MESSAGE
217
+ raise Sass::SyntaxError.new(
218
+ "Invalid CSS after #{after.inspect}: expected #{expected}, was #{was.inspect}")
219
+ end
220
+
221
+ # Identical to `@template.scan`, except that it increments the line count.
222
+ # `@template.scan` should never be called directly;
223
+ # this should be used instead.
224
+ def scan(re)
225
+ str = @template.scan(re)
226
+ @line += str.count "\n" if str
227
+ str
228
+ end
229
+
230
+ # Identical to `@template.scan_until`, except that it increments the line count.
231
+ # `@template.scan_until` should never be called directly;
232
+ # this should be used instead.
233
+ def scan_until(re)
234
+ str = @template.scan_until(re)
235
+ @line += str.count "\n" if str
236
+ str
216
237
  end
217
238
 
218
239
  # Transform
data/lib/sass/engine.rb CHANGED
@@ -156,6 +156,8 @@ module Sass
156
156
  # @return [Sass::Tree::Node] The root of the parse tree.
157
157
  # @raise [Sass::SyntaxError] if there's an error in the document
158
158
  def to_tree
159
+ check_encoding(@template) {|msg, line| raise Sass::SyntaxError.new(msg, :line => line)}
160
+
159
161
  root = Tree::RootNode.new(@template)
160
162
  append_children(root, tree(tabulate(@template)).first, true)
161
163
  root.options = @options
@@ -1084,6 +1084,24 @@ HAML
1084
1084
  o.render
1085
1085
  end
1086
1086
  end
1087
+
1088
+ def test_encoding_error
1089
+ render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
1090
+ assert(false, "Expected exception")
1091
+ rescue Haml::Error => e
1092
+ assert_equal(3, e.line)
1093
+ assert_equal('Invalid UTF-8 character "\xFE"', e.message)
1094
+ end
1095
+
1096
+ def test_ascii_incompatible_encoding_error
1097
+ template = "foo\nbar\nb_z".encode("utf-16le")
1098
+ template[9] = "\xFE".force_encoding("utf-16le")
1099
+ render(template)
1100
+ assert(false, "Expected exception")
1101
+ rescue Haml::Error => e
1102
+ assert_equal(3, e.line)
1103
+ assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
1104
+ end
1087
1105
  end
1088
1106
 
1089
1107
  private
@@ -90,6 +90,28 @@ HAML
90
90
  HTML
91
91
  end
92
92
 
93
+ # Encodings
94
+
95
+ unless Haml::Util.ruby1_8?
96
+ def test_encoding_error
97
+ render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
98
+ assert(false, "Expected exception")
99
+ rescue Haml::Error => e
100
+ assert_equal(3, e.line)
101
+ assert_equal('Invalid UTF-8 character "\xFE"', e.message)
102
+ end
103
+
104
+ def test_ascii_incompatible_encoding_error
105
+ template = "foo\nbar\nb_z".encode("utf-16le")
106
+ template[9] = "\xFE".force_encoding("utf-16le")
107
+ render(template)
108
+ assert(false, "Expected exception")
109
+ rescue Haml::Error => e
110
+ assert_equal(3, e.line)
111
+ assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
112
+ end
113
+ end
114
+
93
115
  protected
94
116
 
95
117
  def render(text, options = {})
@@ -230,6 +230,62 @@ SASS
230
230
  CSS
231
231
  end
232
232
 
233
+ # Error reporting
234
+
235
+ def test_error_reporting
236
+ css2sass("foo")
237
+ assert(false, "Expected exception")
238
+ rescue Sass::SyntaxError => err
239
+ assert_equal(1, err.sass_line)
240
+ assert_equal('Invalid CSS after "foo": expected "{", was ""', err.message)
241
+ end
242
+
243
+ def test_error_reporting_in_line
244
+ css2sass("foo\nbar }\nbaz")
245
+ assert(false, "Expected exception")
246
+ rescue Sass::SyntaxError => err
247
+ assert_equal(2, err.sass_line)
248
+ assert_equal('Invalid CSS after "bar ": expected "{", was "}"', err.message)
249
+ end
250
+
251
+ def test_error_truncate_after
252
+ css2sass("#{"a" * 15}foo")
253
+ assert(false, "Expected exception")
254
+ rescue Sass::SyntaxError => err
255
+ assert_equal(1, err.sass_line)
256
+ assert_equal('Invalid CSS after "...aaaaaaaaaaaafoo": expected "{", was ""', err.message)
257
+ end
258
+
259
+ def test_error_truncate_was
260
+ css2sass("foo }#{"a" * 15}")
261
+ assert(false, "Expected exception")
262
+ rescue Sass::SyntaxError => err
263
+ assert_equal(1, err.sass_line)
264
+ assert_equal('Invalid CSS after "foo ": expected "{", was "}aaaaaaaaaaaaaa..."', err.message)
265
+ end
266
+
267
+ # Encodings
268
+
269
+ unless Haml::Util.ruby1_8?
270
+ def test_encoding_error
271
+ css2sass("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
272
+ assert(false, "Expected exception")
273
+ rescue Sass::SyntaxError => e
274
+ assert_equal(3, e.sass_line)
275
+ assert_equal('Invalid UTF-8 character "\xFE"', e.message)
276
+ end
277
+
278
+ def test_ascii_incompatible_encoding_error
279
+ template = "foo\nbar\nb_z".encode("utf-16le")
280
+ template[9] = "\xFE".force_encoding("utf-16le")
281
+ css2sass(template)
282
+ assert(false, "Expected exception")
283
+ rescue Sass::SyntaxError => e
284
+ assert_equal(3, e.sass_line)
285
+ assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
286
+ end
287
+ end
288
+
233
289
  private
234
290
 
235
291
  def css2sass(string, opts={})
@@ -901,6 +901,28 @@ a
901
901
  SASS
902
902
  end
903
903
 
904
+ # Encodings
905
+
906
+ unless Haml::Util.ruby1_8?
907
+ def test_encoding_error
908
+ render("foo\nbar\nb\xFEaz".force_encoding("utf-8"))
909
+ assert(false, "Expected exception")
910
+ rescue Sass::SyntaxError => e
911
+ assert_equal(3, e.sass_line)
912
+ assert_equal('Invalid UTF-8 character "\xFE"', e.message)
913
+ end
914
+
915
+ def test_ascii_incompatible_encoding_error
916
+ template = "foo\nbar\nb_z".encode("utf-16le")
917
+ template[9] = "\xFE".force_encoding("utf-16le")
918
+ render(template)
919
+ assert(false, "Expected exception")
920
+ rescue Sass::SyntaxError => e
921
+ assert_equal(3, e.sass_line)
922
+ assert_equal('Invalid UTF-16LE character "\xFE"', e.message)
923
+ end
924
+ end
925
+
904
926
  private
905
927
 
906
928
  def render(sass, options = {})
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haml-edge
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.39
4
+ version: 2.3.40
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Weizenbaum
@@ -44,8 +44,8 @@ extensions: []
44
44
 
45
45
  extra_rdoc_files:
46
46
  - README.md
47
- - REVISION
48
47
  - VERSION
48
+ - REVISION
49
49
  - CONTRIBUTING
50
50
  - MIT-LICENSE
51
51
  - VERSION_NAME
@@ -257,8 +257,8 @@ files:
257
257
  - init.rb
258
258
  - .yardopts
259
259
  - README.md
260
- - REVISION
261
260
  - VERSION
261
+ - REVISION
262
262
  - CONTRIBUTING
263
263
  - MIT-LICENSE
264
264
  - VERSION_NAME