haml-edge 2.3.39 → 2.3.40

Sign up to get free protection for your applications and to get access to all the features.
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