haml 3.0.16 → 3.0.17

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of haml might be problematic. Click here for more details.

data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.0.16
1
+ 3.0.17
@@ -99,7 +99,7 @@ module Haml
99
99
  @index = 0
100
100
 
101
101
  unless [:xhtml, :html4, :html5].include?(@options[:format])
102
- raise Haml::Error, "Invalid format #{@options[:format].inspect}"
102
+ raise Haml::Error, "Invalid output format #{@options[:format].inspect}"
103
103
  end
104
104
 
105
105
  if @options[:encoding] && @options[:encoding].is_a?(Encoding)
@@ -161,7 +161,7 @@ module Haml
161
161
  raise err if @options[:trace] || dep.nil? || dep.empty?
162
162
  $stderr.puts <<MESSAGE
163
163
  Required dependency #{dep} not found!
164
- Run "gem install #{dep}" to get it.
164
+ Run "gem install #{dep}" to get it.
165
165
  Use --trace for backtrace.
166
166
  MESSAGE
167
167
  exit 1
@@ -388,6 +388,12 @@ END
388
388
  ::Sass::Plugin.options.merge! @options[:for_engine]
389
389
  ::Sass::Plugin.options[:unix_newlines] = @options[:unix_newlines]
390
390
 
391
+ raise <<MSG if @args.empty?
392
+ What files should I watch? Did you mean something like:
393
+ sass --watch input.sass:output.css
394
+ sass --watch input-dir:output-dir
395
+ MSG
396
+
391
397
  if !colon_path?(@args[0]) && probably_dest_dir?(@args[1])
392
398
  flag = @options[:update] ? "--update" : "--watch"
393
399
  err =
@@ -396,9 +402,9 @@ END
396
402
  elsif @args[1] =~ /\.css$/
397
403
  "is a CSS file"
398
404
  end
399
- msg = <<MSG if err
405
+ raise <<MSG if err
400
406
  File #{@args[1]} #{err}.
401
- Did you mean: sass #{flag} #{@args[0]}:#{@args[1]}
407
+ Did you mean: sass #{flag} #{@args[0]}:#{@args[1]}
402
408
  MSG
403
409
  end
404
410
 
@@ -416,15 +422,18 @@ MSG
416
422
  end
417
423
  end
418
424
 
425
+ had_error = false
419
426
  ::Sass::Plugin.on_creating_directory {|dirname| puts_action :directory, :green, dirname}
420
427
  ::Sass::Plugin.on_deleting_css {|filename| puts_action :delete, :yellow, filename}
421
428
  ::Sass::Plugin.on_compilation_error do |error, _, _|
422
429
  raise error unless error.is_a?(::Sass::SyntaxError)
430
+ had_error = true
423
431
  puts_action :error, :red, "#{error.sass_filename} (Line #{error.sass_line}: #{error.message})"
424
432
  end
425
433
 
426
434
  if @options[:update]
427
435
  ::Sass::Plugin.update_stylesheets(files)
436
+ exit 1 if had_error
428
437
  return
429
438
  end
430
439
 
@@ -456,6 +465,7 @@ MSG
456
465
  # Whether path is likely to be meant as the destination
457
466
  # in a source:dest pair.
458
467
  def probably_dest_dir?(path)
468
+ return false unless path
459
469
  return false if colon_path?(path)
460
470
  return Dir.glob(File.join(path, "*.s[ca]ss")).empty?
461
471
  end
@@ -374,7 +374,7 @@ module Haml
374
374
  #
375
375
  # @return [Boolean]
376
376
  def windows?
377
- RbConfig::CONFIG['host_os'] =~ /mswin|windows/i
377
+ RbConfig::CONFIG['host_os'] =~ /mswin|windows|mingw/i
378
378
  end
379
379
 
380
380
  ## Cross-Ruby-Version Compatibility
@@ -114,7 +114,7 @@ module Sass::Script
114
114
  end
115
115
 
116
116
  unless (0..1).include?(@attrs[:alpha])
117
- raise Sass::SyntaxError.new("Alpha channel must between 0 and 1")
117
+ raise Sass::SyntaxError.new("Alpha channel must be between 0 and 1")
118
118
  end
119
119
  end
120
120
 
@@ -278,7 +278,7 @@ module Sass
278
278
 
279
279
  def color
280
280
  return unless s = scan(REGULAR_EXPRESSIONS[:color])
281
- raise Sass::SyntaxError.new(<<MESSAGE) unless s.size == 4 || s.size == 7
281
+ raise Sass::SyntaxError.new(<<MESSAGE.rstrip) unless s.size == 4 || s.size == 7
282
282
  Colors must have either three or six digits: '#{s}'
283
283
  MESSAGE
284
284
  value = s.scan(/^#(..?)(..?)(..?)$/).first.
@@ -7,6 +7,15 @@ module Sass
7
7
  # parent references, nested selectors, and so forth.
8
8
  # It does support all the same CSS hacks as the SCSS parser, though.
9
9
  class CssParser < StaticParser
10
+ # Parse a selector, and return its value as a string.
11
+ #
12
+ # @return [String, nil] The parsed selector, or nil if no selector was parsed
13
+ # @raise [Sass::SyntaxError] if there's a syntax error in the selector
14
+ def parse_selector_string
15
+ init_scanner!
16
+ str {return unless selector}
17
+ end
18
+
10
19
  private
11
20
 
12
21
  def parent_selector; nil; end
@@ -109,11 +109,10 @@ module Sass
109
109
  return dir
110
110
  end
111
111
 
112
- val = str do
113
- # Most at-rules take expressions (e.g. @import),
114
- # but some (e.g. @page) take selector-like arguments
115
- expr || selector
116
- end
112
+ # Most at-rules take expressions (e.g. @import),
113
+ # but some (e.g. @page) take selector-like arguments
114
+ val = str {break unless expr}
115
+ val ||= CssParser.new(@scanner, @line).parse_selector_string
117
116
  node = node(Sass::Tree::DirectiveNode.new("@#{name} #{val}".strip))
118
117
 
119
118
  if tok(/\{/)
@@ -644,11 +643,10 @@ MESSAGE
644
643
  unless e = tok(NUMBER) ||
645
644
  tok(URI) ||
646
645
  function ||
647
- interp_string ||
646
+ tok(STRING) ||
648
647
  tok(UNICODERANGE) ||
649
648
  tok(IDENT) ||
650
- tok(HEXCOLOR) ||
651
- interpolation
649
+ tok(HEXCOLOR)
652
650
 
653
651
  return unless op = unary_operator
654
652
  @expected = "number or function"
@@ -8,11 +8,9 @@ module Sass
8
8
  class StaticParser < Parser
9
9
  # Parses the text as a selector.
10
10
  #
11
- # @param line [Fixnum] The line on which the selector appears.
12
- # Used for error reporting
13
11
  # @param filename [String, nil] The file in which the selector appears,
14
12
  # or nil if there is no such file.
15
- # Used for error reporting
13
+ # Used for error reporting.
16
14
  # @return [Selector::CommaSequence] The parsed selector
17
15
  # @raise [Sass::SyntaxError] if there's a syntax error in the selector
18
16
  def parse_selector(filename)
@@ -167,7 +167,7 @@ module Sass::Tree
167
167
  def declaration(tabs = 0, opts = {:old => @prop_syntax == :old}, fmt = :sass)
168
168
  name = self.name.map {|n| n.is_a?(String) ? n : "\#{#{n.to_sass(opts)}}"}.join
169
169
  if name[0] == ?:
170
- raise Sass::SyntaxError.new("The \":#{name}: #{self.class.val_to_sass(value, opts)}\" hack is not allowed in the Sass indented syntax")
170
+ raise Sass::SyntaxError.new("The \"#{name}: #{self.class.val_to_sass(value, opts)}\" hack is not allowed in the Sass indented syntax")
171
171
  end
172
172
 
173
173
  old = opts[:old] && fmt == :sass
@@ -1236,7 +1236,9 @@ SASS
1236
1236
  end
1237
1237
 
1238
1238
  def test_arbitrary_output_option
1239
- assert_raise(Haml::Error, "Invalid output format :html1") { engine("%br", :format => :html1) }
1239
+ assert_raise_message(Haml::Error, "Invalid output format :html1") do
1240
+ engine("%br", :format => :html1)
1241
+ end
1240
1242
  end
1241
1243
 
1242
1244
  def test_static_hashes
@@ -1031,7 +1031,7 @@ SCSS
1031
1031
  end
1032
1032
 
1033
1033
  def test_disallowed_colon_hack
1034
- assert_raise(Sass::SyntaxError, '":foo: bar" is not allowed in the Sass syntax') do
1034
+ assert_raise_message(Sass::SyntaxError, 'The ":name: val" hack is not allowed in the Sass indented syntax') do
1035
1035
  to_sass("foo {:name: val;}", :syntax => :scss)
1036
1036
  end
1037
1037
  end
@@ -2057,7 +2057,7 @@ SASS
2057
2057
  end
2058
2058
 
2059
2059
  def test_mixin_no_arg_error
2060
- assert_raise(Sass::SyntaxError, 'Invalid CSS after "($bar,": expected variable name, was ")"') do
2060
+ assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "($bar,": expected variable (e.g. $foo), was ")"') do
2061
2061
  render(<<SASS)
2062
2062
  =foo($bar,)
2063
2063
  bip: bap
@@ -13,13 +13,13 @@ class SassScriptTest < Test::Unit::TestCase
13
13
  include Sass::Script
14
14
 
15
15
  def test_color_checks_input
16
- assert_raise(Sass::SyntaxError, "Color values must be between 0 and 255") {Color.new([1, 2, -1])}
17
- assert_raise(Sass::SyntaxError, "Color values must be between 0 and 255") {Color.new([256, 2, 3])}
16
+ assert_raise_message(Sass::SyntaxError, "Blue value must be between 0 and 255") {Color.new([1, 2, -1])}
17
+ assert_raise_message(Sass::SyntaxError, "Red value must be between 0 and 255") {Color.new([256, 2, 3])}
18
18
  end
19
19
 
20
20
  def test_color_checks_rgba_input
21
- assert_raise(Sass::SyntaxError, "Alpha channel must be between 0 and 1") {Color.new([1, 2, 3, 1.1])}
22
- assert_raise(Sass::SyntaxError, "Alpha channel must be between 0 and 1") {Color.new([1, 2, 3, -0.1])}
21
+ assert_raise_message(Sass::SyntaxError, "Alpha channel must be between 0 and 1") {Color.new([1, 2, 3, 1.1])}
22
+ assert_raise_message(Sass::SyntaxError, "Alpha channel must be between 0 and 1") {Color.new([1, 2, 3, -0.1])}
23
23
  end
24
24
 
25
25
  def test_string_escapes
@@ -63,13 +63,13 @@ class SassScriptTest < Test::Unit::TestCase
63
63
  assert_equal "rgba(50, 50, 100, 0.35)", resolve("rgba(1, 1, 2, 0.35) * rgba(50, 50, 50, 0.35)")
64
64
  assert_equal "rgba(52, 52, 52, 0.25)", resolve("rgba(2, 2, 2, 0.25) + rgba(50, 50, 50, 0.25)")
65
65
 
66
- assert_raise(Sass::SyntaxError, "Alpha channels must be equal: rgba(1, 2, 3, 0.15) + rgba(50, 50, 50, 0.75)") do
66
+ assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: rgba(1, 2, 3, 0.15) + rgba(50, 50, 50, 0.75)") do
67
67
  resolve("rgba(1, 2, 3, 0.15) + rgba(50, 50, 50, 0.75)")
68
68
  end
69
- assert_raise(Sass::SyntaxError, "Alpha channels must be equal: #123456 * rgba(50, 50, 50, 0.75)") do
69
+ assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: #123456 * rgba(50, 50, 50, 0.75)") do
70
70
  resolve("#123456 * rgba(50, 50, 50, 0.75)")
71
71
  end
72
- assert_raise(Sass::SyntaxError, "Alpha channels must be equal: #123456 / #123456") do
72
+ assert_raise_message(Sass::SyntaxError, "Alpha channels must be equal: rgba(50, 50, 50, 0.75) / #123456") do
73
73
  resolve("rgba(50, 50, 50, 0.75) / #123456")
74
74
  end
75
75
  end
@@ -360,15 +360,15 @@ SASS
360
360
  end
361
361
 
362
362
  def test_colors_with_wrong_number_of_digits
363
- assert_raise(Sass::SyntaxError,
363
+ assert_raise_message(Sass::SyntaxError,
364
364
  "Colors must have either three or six digits: '#0'") {eval("#0")}
365
- assert_raise(Sass::SyntaxError,
365
+ assert_raise_message(Sass::SyntaxError,
366
366
  "Colors must have either three or six digits: '#12'") {eval("#12")}
367
- assert_raise(Sass::SyntaxError,
367
+ assert_raise_message(Sass::SyntaxError,
368
368
  "Colors must have either three or six digits: '#abcd'") {eval("#abcd")}
369
- assert_raise(Sass::SyntaxError,
369
+ assert_raise_message(Sass::SyntaxError,
370
370
  "Colors must have either three or six digits: '#abcdE'") {eval("#abcdE")}
371
- assert_raise(Sass::SyntaxError,
371
+ assert_raise_message(Sass::SyntaxError,
372
372
  "Colors must have either three or six digits: '#abcdEFA'") {eval("#abcdEFA")}
373
373
  end
374
374
 
@@ -386,7 +386,7 @@ SASS
386
386
  end
387
387
 
388
388
  def test_misplaced_comma_in_funcall
389
- assert_raise(Sass::SyntaxError,
389
+ assert_raise_message(Sass::SyntaxError,
390
390
  'Invalid CSS after "foo(bar, ": expected function argument, was ")"') {eval('foo(bar, )')}
391
391
  end
392
392
 
@@ -965,7 +965,7 @@ SCSS
965
965
  end
966
966
 
967
967
  def test_parent_in_mid_selector_error
968
- assert_raise(Sass::SyntaxError, <<MESSAGE) {render <<SCSS}
968
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE) {render <<SCSS}
969
969
  Invalid CSS after ".foo": expected "{", was "&.bar"
970
970
 
971
971
  In Sass 3, the parent selector & can only be used where element names are valid,
@@ -978,8 +978,8 @@ SCSS
978
978
  end
979
979
 
980
980
  def test_parent_in_mid_selector_error
981
- assert_raise(Sass::SyntaxError, <<MESSAGE) {render <<SCSS}
982
- Invalid CSS after ".foo.bar": expected "{", was "&"
981
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE) {render <<SCSS}
982
+ Invalid CSS after " .foo.bar": expected "{", was "& {a: b}"
983
983
 
984
984
  In Sass 3, the parent selector & can only be used where element names are valid,
985
985
  since it could potentially be replaced by an element name.
@@ -991,8 +991,8 @@ SCSS
991
991
  end
992
992
 
993
993
  def test_double_parent_selector_error
994
- assert_raise(Sass::SyntaxError, <<MESSAGE) {render <<SCSS}
995
- Invalid CSS after "&": expected "{", was "&"
994
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE) {render <<SCSS}
995
+ Invalid CSS after " &": expected "{", was "& {a: b}"
996
996
 
997
997
  In Sass 3, the parent selector & can only be used where element names are valid,
998
998
  since it could potentially be replaced by an element name.
@@ -1003,6 +1003,26 @@ flim {
1003
1003
  SCSS
1004
1004
  end
1005
1005
 
1006
+ def test_no_interpolation_in_media_queries
1007
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1008
+ Invalid CSS after "...nd (min-width: ": expected expression (e.g. 1px, bold), was "\#{100}px) {"
1009
+ MESSAGE
1010
+ @media screen and (min-width: \#{100}px) {
1011
+ foo {bar: baz}
1012
+ }
1013
+ SCSS
1014
+ end
1015
+
1016
+ def test_no_interpolation_in_unrecognized_directives
1017
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1018
+ Invalid CSS after "@foo ": expected selector or at-rule, was "\#{100} {"
1019
+ MESSAGE
1020
+ @foo \#{100} {
1021
+ foo {bar: baz}
1022
+ }
1023
+ SCSS
1024
+ end
1025
+
1006
1026
  # Regression
1007
1027
 
1008
1028
  def test_weird_added_space
@@ -1029,8 +1049,8 @@ SCSS
1029
1049
  end
1030
1050
 
1031
1051
  def test_extra_comma_in_mixin_arglist_error
1032
- assert_raise(Sass::SyntaxError, <<MESSAGE) {render <<SCSS}
1033
- Invalid CSS after "@include foo(bar, ": expected mixin argument, was ")"
1052
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
1053
+ Invalid CSS after "...clude foo(bar, ": expected mixin argument, was ");"
1034
1054
  MESSAGE
1035
1055
  @mixin foo($a1, $a2) {
1036
1056
  baz: $a1 $a2;
@@ -78,4 +78,13 @@ class Test::Unit::TestCase
78
78
  return '' unless Haml::Util.ap_geq?("3.0.0.rc")
79
79
  return '<div style="margin:0;padding:0;display:inline"><input name="_snowman" type="hidden" value="&#9731;" /></div>'
80
80
  end
81
+
82
+ def assert_raise_message(klass, message)
83
+ yield
84
+ rescue Exception => e
85
+ assert_instance_of(klass, e)
86
+ assert_equal(message, e.message)
87
+ else
88
+ flunk "Expected exception #{klass}, none raised"
89
+ end
81
90
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haml
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.16
4
+ version: 3.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Weizenbaum
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2010-08-08 00:00:00 -07:00
14
+ date: 2010-08-14 00:00:00 -07:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency