sass 3.3.0 → 3.4.0

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.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +58 -50
  4. data/Rakefile +1 -4
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/VERSION_NAME +1 -1
  8. data/bin/sass +1 -1
  9. data/bin/scss +1 -1
  10. data/lib/sass/cache_stores/filesystem.rb +6 -2
  11. data/lib/sass/css.rb +1 -3
  12. data/lib/sass/engine.rb +37 -46
  13. data/lib/sass/environment.rb +13 -17
  14. data/lib/sass/error.rb +6 -9
  15. data/lib/sass/exec/base.rb +187 -0
  16. data/lib/sass/exec/sass_convert.rb +264 -0
  17. data/lib/sass/exec/sass_scss.rb +424 -0
  18. data/lib/sass/exec.rb +5 -771
  19. data/lib/sass/features.rb +7 -0
  20. data/lib/sass/importers/base.rb +7 -2
  21. data/lib/sass/importers/filesystem.rb +9 -25
  22. data/lib/sass/importers.rb +0 -1
  23. data/lib/sass/media.rb +1 -4
  24. data/lib/sass/plugin/compiler.rb +200 -83
  25. data/lib/sass/plugin/staleness_checker.rb +1 -1
  26. data/lib/sass/plugin.rb +3 -3
  27. data/lib/sass/script/css_lexer.rb +1 -1
  28. data/lib/sass/script/functions.rb +622 -268
  29. data/lib/sass/script/lexer.rb +99 -34
  30. data/lib/sass/script/parser.rb +24 -23
  31. data/lib/sass/script/tree/funcall.rb +1 -1
  32. data/lib/sass/script/tree/interpolation.rb +20 -2
  33. data/lib/sass/script/tree/selector.rb +26 -0
  34. data/lib/sass/script/tree/string_interpolation.rb +1 -1
  35. data/lib/sass/script/tree.rb +1 -0
  36. data/lib/sass/script/value/base.rb +7 -5
  37. data/lib/sass/script/value/bool.rb +0 -5
  38. data/lib/sass/script/value/color.rb +39 -21
  39. data/lib/sass/script/value/helpers.rb +107 -0
  40. data/lib/sass/script/value/list.rb +0 -15
  41. data/lib/sass/script/value/null.rb +0 -5
  42. data/lib/sass/script/value/number.rb +62 -14
  43. data/lib/sass/script/value/string.rb +59 -11
  44. data/lib/sass/script/value.rb +0 -1
  45. data/lib/sass/scss/css_parser.rb +8 -2
  46. data/lib/sass/scss/parser.rb +190 -328
  47. data/lib/sass/scss/rx.rb +15 -6
  48. data/lib/sass/scss/static_parser.rb +298 -1
  49. data/lib/sass/selector/abstract_sequence.rb +28 -13
  50. data/lib/sass/selector/comma_sequence.rb +92 -13
  51. data/lib/sass/selector/pseudo.rb +256 -0
  52. data/lib/sass/selector/sequence.rb +94 -24
  53. data/lib/sass/selector/simple.rb +14 -25
  54. data/lib/sass/selector/simple_sequence.rb +97 -33
  55. data/lib/sass/selector.rb +57 -194
  56. data/lib/sass/shared.rb +1 -1
  57. data/lib/sass/source/map.rb +26 -12
  58. data/lib/sass/stack.rb +0 -6
  59. data/lib/sass/supports.rb +2 -3
  60. data/lib/sass/tree/at_root_node.rb +1 -0
  61. data/lib/sass/tree/charset_node.rb +1 -1
  62. data/lib/sass/tree/directive_node.rb +8 -2
  63. data/lib/sass/tree/error_node.rb +18 -0
  64. data/lib/sass/tree/extend_node.rb +1 -1
  65. data/lib/sass/tree/function_node.rb +4 -0
  66. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  67. data/lib/sass/tree/prop_node.rb +1 -1
  68. data/lib/sass/tree/rule_node.rb +12 -7
  69. data/lib/sass/tree/visitors/check_nesting.rb +38 -10
  70. data/lib/sass/tree/visitors/convert.rb +16 -18
  71. data/lib/sass/tree/visitors/cssize.rb +29 -29
  72. data/lib/sass/tree/visitors/deep_copy.rb +5 -0
  73. data/lib/sass/tree/visitors/perform.rb +45 -33
  74. data/lib/sass/tree/visitors/set_options.rb +14 -0
  75. data/lib/sass/tree/visitors/to_css.rb +15 -14
  76. data/lib/sass/util/subset_map.rb +1 -1
  77. data/lib/sass/util.rb +222 -99
  78. data/lib/sass/version.rb +5 -5
  79. data/lib/sass.rb +0 -5
  80. data/test/sass/cache_test.rb +62 -20
  81. data/test/sass/callbacks_test.rb +1 -1
  82. data/test/sass/compiler_test.rb +19 -10
  83. data/test/sass/conversion_test.rb +58 -1
  84. data/test/sass/css2sass_test.rb +23 -4
  85. data/test/sass/encoding_test.rb +219 -0
  86. data/test/sass/engine_test.rb +136 -199
  87. data/test/sass/exec_test.rb +2 -2
  88. data/test/sass/extend_test.rb +236 -19
  89. data/test/sass/functions_test.rb +295 -253
  90. data/test/sass/importer_test.rb +31 -21
  91. data/test/sass/logger_test.rb +1 -1
  92. data/test/sass/more_results/more_import.css +1 -1
  93. data/test/sass/plugin_test.rb +14 -13
  94. data/test/sass/results/compact.css +1 -1
  95. data/test/sass/results/complex.css +4 -4
  96. data/test/sass/results/expanded.css +1 -1
  97. data/test/sass/results/import.css +1 -1
  98. data/test/sass/results/import_charset_ibm866.css +2 -2
  99. data/test/sass/results/mixins.css +17 -17
  100. data/test/sass/results/nested.css +1 -1
  101. data/test/sass/results/parent_ref.css +2 -2
  102. data/test/sass/results/script.css +3 -3
  103. data/test/sass/results/scss_import.css +1 -1
  104. data/test/sass/script_conversion_test.rb +10 -7
  105. data/test/sass/script_test.rb +288 -74
  106. data/test/sass/scss/css_test.rb +141 -24
  107. data/test/sass/scss/rx_test.rb +4 -4
  108. data/test/sass/scss/scss_test.rb +457 -18
  109. data/test/sass/source_map_test.rb +115 -25
  110. data/test/sass/superselector_test.rb +191 -0
  111. data/test/sass/templates/scss_import.scss +2 -1
  112. data/test/sass/test_helper.rb +1 -1
  113. data/test/sass/util/multibyte_string_scanner_test.rb +1 -1
  114. data/test/sass/util/normalized_map_test.rb +1 -1
  115. data/test/sass/util/subset_map_test.rb +2 -2
  116. data/test/sass/util_test.rb +31 -1
  117. data/test/sass/value_helpers_test.rb +5 -7
  118. data/test/test_helper.rb +2 -2
  119. data/vendor/listen/CHANGELOG.md +1 -228
  120. data/vendor/listen/Gemfile +5 -15
  121. data/vendor/listen/README.md +111 -77
  122. data/vendor/listen/Rakefile +0 -42
  123. data/vendor/listen/lib/listen/adapter.rb +195 -82
  124. data/vendor/listen/lib/listen/adapters/bsd.rb +27 -64
  125. data/vendor/listen/lib/listen/adapters/darwin.rb +21 -58
  126. data/vendor/listen/lib/listen/adapters/linux.rb +23 -55
  127. data/vendor/listen/lib/listen/adapters/polling.rb +25 -34
  128. data/vendor/listen/lib/listen/adapters/windows.rb +50 -46
  129. data/vendor/listen/lib/listen/directory_record.rb +96 -61
  130. data/vendor/listen/lib/listen/listener.rb +135 -37
  131. data/vendor/listen/lib/listen/turnstile.rb +9 -5
  132. data/vendor/listen/lib/listen/version.rb +1 -1
  133. data/vendor/listen/lib/listen.rb +33 -19
  134. data/vendor/listen/listen.gemspec +6 -0
  135. data/vendor/listen/spec/listen/adapter_spec.rb +43 -77
  136. data/vendor/listen/spec/listen/adapters/polling_spec.rb +8 -8
  137. data/vendor/listen/spec/listen/directory_record_spec.rb +81 -56
  138. data/vendor/listen/spec/listen/listener_spec.rb +128 -39
  139. data/vendor/listen/spec/listen_spec.rb +15 -21
  140. data/vendor/listen/spec/spec_helper.rb +4 -0
  141. data/vendor/listen/spec/support/adapter_helper.rb +52 -15
  142. data/vendor/listen/spec/support/directory_record_helper.rb +7 -5
  143. data/vendor/listen/spec/support/listeners_helper.rb +30 -7
  144. metadata +25 -22
  145. data/ext/mkrf_conf.rb +0 -27
  146. data/lib/sass/importers/deprecated_path.rb +0 -51
  147. data/lib/sass/script/value/deprecated_false.rb +0 -55
  148. data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
  149. data/vendor/listen/lib/listen/multi_listener.rb +0 -143
  150. data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
  151. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
2
3
  require File.dirname(__FILE__) + '/../test_helper'
3
4
  require 'sass/engine'
4
5
 
@@ -17,34 +18,59 @@ module Sass::Script::Functions
17
18
  include Sass::Script::Functions::UserFunctions
18
19
  end
19
20
 
20
- class SassScriptTest < Test::Unit::TestCase
21
+ class SassScriptTest < MiniTest::Test
21
22
  include Sass::Script
22
23
 
23
- def test_color_checks_input
24
- assert_raise_message(ArgumentError, "Blue value -1 must be between 0 and 255") {Sass::Script::Value::Color.new([1, 2, -1])}
25
- assert_raise_message(ArgumentError, "Red value 256 must be between 0 and 255") {Sass::Script::Value::Color.new([256, 2, 3])}
24
+ def test_color_clamps_input
25
+ assert_equal 0, Sass::Script::Value::Color.new([1, 2, -1]).blue
26
+ assert_equal 255, Sass::Script::Value::Color.new([256, 2, 3]).red
26
27
  end
27
28
 
28
- def test_color_checks_rgba_input
29
- assert_raise_message(ArgumentError, "Alpha channel 1.1 must be between 0 and 1") {Sass::Script::Value::Color.new([1, 2, 3, 1.1])}
30
- assert_raise_message(ArgumentError, "Alpha channel -0.1 must be between 0 and 1") {Sass::Script::Value::Color.new([1, 2, 3, -0.1])}
29
+ def test_color_clamps_rgba_input
30
+ assert_equal 1, Sass::Script::Value::Color.new([1, 2, 3, 1.1]).alpha
31
+ assert_equal 0, Sass::Script::Value::Color.new([1, 2, 3, -0.1]).alpha
31
32
  end
32
33
 
33
34
  def test_string_escapes
34
35
  assert_equal "'", resolve("\"'\"")
35
36
  assert_equal '"', resolve("\"\\\"\"")
36
- assert_equal "\\\\", resolve("\"\\\\\"")
37
- assert_equal "\\02fa", resolve("\"\\02fa\"")
38
-
39
- assert_equal "'", resolve("'\\''")
40
- assert_equal '"', resolve("'\"'")
41
- assert_equal "\\\\", resolve("'\\\\'")
42
- assert_equal "\\02fa", resolve("'\\02fa'")
37
+ assert_equal "\\", resolve("\"\\\\\"")
38
+ assert_equal "", resolve("\"\\2603\"")
39
+ assert_equal "☃f", resolve("\"\\2603 f\"")
40
+ assert_equal "☃x", resolve("\"\\2603x\"")
41
+ assert_equal "\\2603", resolve("\"\\\\2603\"")
42
+
43
+ # U+FFFD is the replacement character, "".
44
+ assert_equal [0xFFFD].pack("U"), resolve("\"\\0\"")
45
+ assert_equal [0xFFFD].pack("U"), resolve("\"\\FFFFFF\"")
46
+ assert_equal [0xFFFD].pack("U"), resolve("\"\\D800\"")
47
+ assert_equal [0xD7FF].pack("U"), resolve("\"\\D7FF\"")
48
+ assert_equal [0xFFFD].pack("U"), resolve("\"\\DFFF\"")
49
+ assert_equal [0xE000].pack("U"), resolve("\"\\E000\"")
50
+ end
51
+
52
+ def test_string_escapes_are_resolved_before_operators
53
+ assert_equal "true", resolve('"abc" == "\61\62\63"')
54
+ end
55
+
56
+ def test_string_quote
57
+ assert_equal '"foo"', resolve_quoted('"foo"')
58
+ assert_equal "'f\"oo'", resolve_quoted('"f\"oo"')
59
+ assert_equal "\"f'oo\"", resolve_quoted("'f\\'oo'")
60
+ assert_equal "\"f'o\\\"o\"", resolve_quoted("'f\\'o\"o'")
61
+ assert_equal '"foo bar"', resolve_quoted('"foo\20 bar"')
62
+ assert_equal '"foo\a bar"', resolve_quoted('"foo\a bar"')
63
+ assert_equal '"x\ay"', resolve_quoted('"x\a y"')
64
+ assert_equal '"\a "', resolve_quoted('"\a\20"')
65
+ assert_equal '"\a abcdef"', resolve_quoted('"\a abcdef"')
66
+ assert_equal '"☃abcdef"', resolve_quoted('"\2603 abcdef"')
67
+ assert_equal '"\\\\"', resolve_quoted('"\\\\"')
68
+ assert_equal '"foobar"', resolve_quoted("\"foo\\\nbar\"")
43
69
  end
44
70
 
45
71
  def test_color_names
46
72
  assert_equal "white", resolve("white")
47
- assert_equal "white", resolve("#ffffff")
73
+ assert_equal "#ffffff", resolve("#ffffff")
48
74
  assert_equal "#fffffe", resolve("white - #000001")
49
75
  assert_equal "transparent", resolve("transparent")
50
76
  assert_equal "transparent", resolve("rgba(0, 0, 0, 0)")
@@ -93,7 +119,7 @@ class SassScriptTest < Test::Unit::TestCase
93
119
  assert_equal "#123", resolve("#112233", :style => :compressed)
94
120
  assert_equal "#000", resolve("black", :style => :compressed)
95
121
  assert_equal "red", resolve("#f00", :style => :compressed)
96
- assert_equal "blue", resolve("#00f", :style => :compressed)
122
+ assert_equal "blue", resolve("blue", :style => :compressed)
97
123
  assert_equal "navy", resolve("#000080", :style => :compressed)
98
124
  assert_equal "navy #fff", resolve("#000080 white", :style => :compressed)
99
125
  assert_equal "This color is #fff", resolve('"This color is #{ white }"', :style => :compressed)
@@ -180,6 +206,11 @@ class SassScriptTest < Test::Unit::TestCase
180
206
  assert_equal "foo1bar5baz4bang", resolve('\'foo#{1 + "bar#{2 + 3}baz" + 4}bang\'')
181
207
  end
182
208
 
209
+ def test_interpolation_with_newline
210
+ assert_equal "\nbang", resolve('"#{"\a "}bang"')
211
+ assert_equal "\n\nbang", resolve('"#{"\a "}\a bang"')
212
+ end
213
+
183
214
  def test_rule_interpolation
184
215
  assert_equal(<<CSS, render(<<SASS))
185
216
  foo bar baz bang {
@@ -255,8 +286,8 @@ SASS
255
286
  assert_equal eval('1 2 3.0'), eval('1 2 3')
256
287
  assert_equal eval('1, 2, 3.0'), eval('1, 2, 3')
257
288
  assert_equal eval('(1 2), (3, 4), (5 6)'), eval('(1 2), (3, 4), (5 6)')
258
- assert_not_equal eval('1, 2, 3'), eval('1 2 3')
259
- assert_not_equal eval('1'), eval('"1"')
289
+ refute_equal eval('1, 2, 3'), eval('1 2 3')
290
+ refute_equal eval('1'), eval('"1"')
260
291
  end
261
292
 
262
293
  def test_booleans
@@ -316,6 +347,7 @@ SASS
316
347
  assert_equal '"foo", "bar"', resolve("'foo' , 'bar'")
317
348
  assert_equal "true, 1", resolve('true , 1')
318
349
  assert_equal "foobar", resolve('"foo" + "bar"')
350
+ assert_equal "\nfoo\nxyz", resolve('"\a foo" + "\axyz"')
319
351
  assert_equal "true1", resolve('true + 1')
320
352
  assert_equal '"foo"-"bar"', resolve("'foo' - 'bar'")
321
353
  assert_equal "true-1", resolve('true - 1')
@@ -430,6 +462,36 @@ SASS
430
462
  assert_equal "true", resolve("1.1cm == 11mm")
431
463
  end
432
464
 
465
+ def test_length_units
466
+ assert_equal "2.54", resolve("(1in/1cm)")
467
+ assert_equal "2.3622", resolve("(1cm/1pc)")
468
+ assert_equal "4.23333", resolve("(1pc/1mm)")
469
+ assert_equal "2.83465", resolve("(1mm/1pt)")
470
+ assert_equal "1.33333", resolve("(1pt/1px)")
471
+ assert_equal "0.01042", resolve("(1px/1in)")
472
+ end
473
+
474
+ def test_angle_units
475
+ assert_equal "1.11111", resolve("(1deg/1grad)")
476
+ assert_equal "0.01571", resolve("(1grad/1rad)")
477
+ assert_equal "0.15915", resolve("(1rad/1turn)")
478
+ assert_equal "360", resolve("(1turn/1deg)")
479
+ end
480
+
481
+ def test_time_units
482
+ assert_equal "1000", resolve("(1s/1ms)")
483
+ end
484
+
485
+ def test_frequency_units
486
+ assert_equal "0.001", resolve("(1Hz/1kHz)")
487
+ end
488
+
489
+ def test_resolution_units
490
+ assert_equal "2.54", resolve("(1dpi/1dpcm)")
491
+ assert_equal "37.79528", resolve("(1dpcm/1dppx)")
492
+ assert_equal "0.01042", resolve("(1dppx/1dpi)")
493
+ end
494
+
433
495
  def test_operations_have_options
434
496
  assert_equal "Options defined!", resolve("assert_options(1 + 1)")
435
497
  assert_equal "Options defined!", resolve("assert_options('bar' + 'baz')")
@@ -462,22 +524,22 @@ SASS
462
524
  assert_equal "0.5", resolve("$var", {}, env("var" => eval("1px/2px")))
463
525
  end
464
526
 
465
- def test_colors_with_wrong_number_of_digits
527
+ def test_non_ident_colors_with_wrong_number_of_digits
466
528
  assert_raise_message(Sass::SyntaxError,
467
- "Colors must have either three or six digits: '#0'") {eval("#0")}
529
+ 'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#1"') {eval("#1")}
468
530
  assert_raise_message(Sass::SyntaxError,
469
- "Colors must have either three or six digits: '#12'") {eval("#12")}
531
+ 'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#12"') {eval("#12")}
470
532
  assert_raise_message(Sass::SyntaxError,
471
- "Colors must have either three or six digits: '#abcd'") {eval("#abcd")}
533
+ 'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#1234"') {eval("#1234")}
472
534
  assert_raise_message(Sass::SyntaxError,
473
- "Colors must have either three or six digits: '#abcdE'") {eval("#abcdE")}
474
- assert_raise_message(Sass::SyntaxError,
475
- "Colors must have either three or six digits: '#abcdEFA'") {eval("#abcdEFA")}
535
+ 'Invalid CSS after "": expected expression (e.g. 1px, bold), was "#12345"') {eval("#12345")}
536
+ assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "": expected expression (e.g. ' \
537
+ '1px, bold), was "#1234567"') {eval("#1234567")}
476
538
  end
477
539
 
478
540
  def test_case_insensitive_color_names
479
- assert_equal "blue", resolve("BLUE")
480
- assert_equal "red", resolve("rEd")
541
+ assert_equal "BLUE", resolve("BLUE")
542
+ assert_equal "rEd", resolve("rEd")
481
543
  assert_equal "#7f4000", resolve("mix(GrEeN, ReD)")
482
544
  end
483
545
 
@@ -523,7 +585,7 @@ SASS
523
585
  assert_raise_message(Sass::SyntaxError, 'Duplicate key 2px in map (2px: bar, 1px + 1px: baz).') do
524
586
  eval("(2px: bar, 1px + 1px: baz)")
525
587
  end
526
- assert_raise_message(Sass::SyntaxError, 'Duplicate key #0000ff in map (blue: bar, blue: baz).') do
588
+ assert_raise_message(Sass::SyntaxError, 'Duplicate key #0000ff in map (blue: bar, #00f: baz).') do
527
589
  eval("(blue: bar, #00f: baz)")
528
590
  end
529
591
  end
@@ -558,7 +620,7 @@ SASS
558
620
  return if RUBY_PLATFORM =~ /java/
559
621
 
560
622
  # Don't validate the message; it's different on Rubinius.
561
- assert_raise(ArgumentError) {resolve("arg-error()")}
623
+ assert_raises(ArgumentError) {resolve("arg-error()")}
562
624
  end
563
625
 
564
626
  def test_shallow_argument_error_unwrapped
@@ -570,49 +632,37 @@ SASS
570
632
  assert_equal "true", resolve("$ie or $undef", {}, env('ie' => Sass::Script::Value::Bool.new(true)))
571
633
  end
572
634
 
573
- def test_setting_global_variable_locally_warns
574
- assert_warning(<<WARNING) {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
575
- DEPRECATION WARNING on line 4 of test_setting_global_variable_locally_warns_inline.scss:
576
- Assigning to global variable "$var" by default is deprecated.
577
- In future versions of Sass, this will create a new local variable.
578
- If you want to assign to the global variable, use "$var: x !global" instead.
579
- Note that this will be incompatible with Sass 3.2.
580
- WARNING
581
- .foo {
582
- a: x; }
583
-
584
- .bar {
585
- b: x; }
586
- CSS
587
- $var: 1;
588
-
589
- .foo {
590
- $var: x;
591
- a: $var;
592
- }
593
-
594
- .bar {
595
- b: $var;
596
- }
597
- SCSS
598
- end
599
-
600
- def test_setting_global_variable_locally_warns_only_once
601
- assert_warning(<<WARNING) {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
602
- DEPRECATION WARNING on line 3 of test_setting_global_variable_locally_warns_only_once_inline.scss:
603
- Assigning to global variable "$var" by default is deprecated.
604
- In future versions of Sass, this will create a new local variable.
605
- If you want to assign to the global variable, use "$var: x !global" instead.
606
- Note that this will be incompatible with Sass 3.2.
607
- WARNING
608
- CSS
609
- $var: 1;
610
-
611
- @mixin foo {$var: x}
612
- @include foo;
613
- @include foo;
614
- @include foo;
615
- SCSS
635
+ def test_selector
636
+ env = Sass::Environment.new
637
+ assert_equal "true", resolve("& == null", {}, env)
638
+
639
+ env.selector = selector('.foo.bar .baz.bang, .bip.bop')
640
+ assert_equal ".foo.bar .baz.bang, .bip.bop", resolve("&", {}, env)
641
+ assert_equal ".foo.bar .baz.bang", resolve("nth(&, 1)", {}, env)
642
+ assert_equal ".bip.bop", resolve("nth(&, 2)", {}, env)
643
+ assert_equal ".foo.bar", resolve("nth(nth(&, 1), 1)", {}, env)
644
+ assert_equal ".baz.bang", resolve("nth(nth(&, 1), 2)", {}, env)
645
+ assert_equal ".bip.bop", resolve("nth(nth(&, 2), 1)", {}, env)
646
+ assert_equal "string", resolve("type-of(nth(nth(&, 1), 1))", {}, env)
647
+
648
+ env.selector = selector('.foo > .bar')
649
+ assert_equal ".foo > .bar", resolve("&", {}, env)
650
+ assert_equal ".foo > .bar", resolve("nth(&, 1)", {}, env)
651
+ assert_equal ".foo", resolve("nth(nth(&, 1), 1)", {}, env)
652
+ assert_equal ">", resolve("nth(nth(&, 1), 2)", {}, env)
653
+ assert_equal ".bar", resolve("nth(nth(&, 1), 3)", {}, env)
654
+ end
655
+
656
+ def test_selector_with_newlines
657
+ env = Sass::Environment.new
658
+ env.selector = selector(".foo.bar\n.baz.bang,\n\n.bip.bop")
659
+ assert_equal ".foo.bar .baz.bang, .bip.bop", resolve("&", {}, env)
660
+ assert_equal ".foo.bar .baz.bang", resolve("nth(&, 1)", {}, env)
661
+ assert_equal ".bip.bop", resolve("nth(&, 2)", {}, env)
662
+ assert_equal ".foo.bar", resolve("nth(nth(&, 1), 1)", {}, env)
663
+ assert_equal ".baz.bang", resolve("nth(nth(&, 1), 2)", {}, env)
664
+ assert_equal ".bip.bop", resolve("nth(nth(&, 2), 1)", {}, env)
665
+ assert_equal "string", resolve("type-of(nth(nth(&, 1), 1))", {}, env)
616
666
  end
617
667
 
618
668
  def test_setting_global_variable_globally
@@ -637,7 +687,7 @@ $var: 2;
637
687
  SCSS
638
688
  end
639
689
 
640
- def test_setting_global_variable_with_flag
690
+ def test_setting_global_variable_locally
641
691
  assert_no_warning {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
642
692
  .bar {
643
693
  a: x;
@@ -663,7 +713,7 @@ $var3: 3;
663
713
  SCSS
664
714
  end
665
715
 
666
- def test_setting_global_variable_with_flag_and_default
716
+ def test_setting_global_variable_locally_with_default
667
717
  assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
668
718
  .bar {
669
719
  a: 1;
@@ -688,10 +738,156 @@ $var1: 1;
688
738
  SCSS
689
739
  end
690
740
 
741
+ def test_setting_local_variable
742
+ assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
743
+ .a {
744
+ value: inside; }
745
+
746
+ .b {
747
+ value: outside; }
748
+ CSS
749
+ $var: outside;
750
+
751
+ .a {
752
+ $var: inside;
753
+ value: $var;
754
+ }
755
+
756
+ .b {
757
+ value: $var;
758
+ }
759
+ SCSS
760
+ end
761
+
762
+ def test_setting_local_variable_from_inner_scope
763
+ assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))
764
+ .a .b {
765
+ value: inside; }
766
+ .a .c {
767
+ value: inside; }
768
+ CSS
769
+ .a {
770
+ $var: outside;
771
+
772
+ .b {
773
+ $var: inside;
774
+ value: $var;
775
+ }
776
+
777
+ .c {
778
+ value: $var;
779
+ }
780
+ }
781
+ SCSS
782
+ end
783
+
784
+ def test_color_format_is_preserved_by_default
785
+ assert_equal "blue", resolve("blue")
786
+ assert_equal "bLuE", resolve("bLuE")
787
+ assert_equal "#00f", resolve("#00f")
788
+ assert_equal "blue #00F", resolve("blue #00F")
789
+ assert_equal "blue", resolve("nth(blue #00F, 1)")
790
+ assert_equal "#00F", resolve("nth(blue #00F, 2)")
791
+ end
792
+
793
+ def test_color_format_isnt_always_preserved_in_compressed_style
794
+ assert_equal "red", resolve("red", :style => :compressed)
795
+ assert_equal "red", resolve("#f00", :style => :compressed)
796
+ assert_equal "red red", resolve("red #f00", :style => :compressed)
797
+ assert_equal "red", resolve("nth(red #f00, 2)", :style => :compressed)
798
+ end
799
+
800
+ def test_color_format_is_sometimes_preserved_in_compressed_style
801
+ assert_equal "ReD", resolve("ReD", :style => :compressed)
802
+ assert_equal "blue", resolve("blue", :style => :compressed)
803
+ assert_equal "#00f", resolve("#00f", :style => :compressed)
804
+ end
805
+
806
+ def test_color_format_isnt_preserved_when_modified
807
+ assert_equal "magenta", resolve("#f00 + #00f")
808
+ end
809
+
810
+ def test_ids
811
+ assert_equal "#foo", resolve("#foo")
812
+ assert_equal "#abcd", resolve("#abcd")
813
+ assert_equal "#abc-def", resolve("#abc-def")
814
+ assert_equal "#abc_def", resolve("#abc_def")
815
+ assert_equal "#uvw-xyz", resolve("#uvw-xyz")
816
+ assert_equal "#uvw_xyz", resolve("#uvw_xyz")
817
+ assert_equal "#uvwxyz", resolve("#uvw + xyz")
818
+ end
819
+
820
+ def test_scientific_notation
821
+ assert_equal "2000", resolve("2e3")
822
+ assert_equal "2000", resolve("2E3")
823
+ assert_equal "2000", resolve("2e+3")
824
+ assert_equal "2000em", resolve("2e3em")
825
+ assert_equal "25000000000", resolve("2.5e10")
826
+ assert_equal "0.1234", resolve("1234e-4")
827
+ assert_equal "12.34", resolve("1.234e1")
828
+ end
829
+
830
+ def test_identifier_units
831
+ assert_equal "5-foo", resolve("2-foo + 3-foo")
832
+ assert_equal "5-foo-", resolve("2-foo- + 3-foo-")
833
+ assert_equal "5-\\u2603", resolve("2-\\u2603 + 3-\\u2603")
834
+ end
835
+
836
+ def test_backslash_newline_in_string
837
+ assert_equal 'foobar', resolve("\"foo\\\nbar\"")
838
+ assert_equal 'foobar', resolve("'foo\\\nbar'")
839
+ end
840
+
841
+ def test_unclosed_special_fun
842
+ assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "calc(foo()": expected ")", was ""') do
843
+ resolve("calc(foo()")
844
+ end
845
+ assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "calc(#{\')\'}": expected ")", was ""') do
846
+ resolve("calc(\#{')'}")
847
+ end
848
+ assert_raise_message(Sass::SyntaxError, 'Invalid CSS after "calc(#{foo": expected "}", was ""') do
849
+ resolve("calc(\#{foo")
850
+ end
851
+ end
852
+
853
+ def test_special_fun_with_interpolation
854
+ assert_equal "calc())", resolve("calc(\#{')'})")
855
+ assert_equal "calc(# {foo})", resolve("calc(# {foo})")
856
+ end
857
+
691
858
  # Regression Tests
692
859
 
860
+ def test_repeatedly_modified_color
861
+ assert_equal(<<CSS, render(<<SASS))
862
+ a {
863
+ link-color: #161C14;
864
+ link-color-hover: black;
865
+ link-color-tap: rgba(22, 28, 20, 0.3); }
866
+ CSS
867
+ $green: #161C14
868
+ $link-color: $green
869
+ $link-color-hover: darken($link-color, 10%)
870
+ $link-color-tap: rgba($green, 0.3)
871
+
872
+ a
873
+ link-color: $link-color
874
+ link-color-hover: $link-color-hover
875
+ link-color-tap: $link-color-tap
876
+ SASS
877
+ end
878
+
879
+ def test_inspect_divided_numbers
880
+ assert_equal "1px/2px", resolve("inspect(1px/2px)")
881
+ assert_equal "0.5", resolve("inspect((1px/2px))")
882
+ end
883
+
693
884
  def test_minus_without_whitespace
694
885
  assert_equal "5px", resolve("15px-10px")
886
+ assert_equal "5px-", resolve("15px--10px-")
887
+ end
888
+
889
+ def test_minus_preceded_by_comment
890
+ assert_equal "15px -10px", resolve("15px/**/-10px")
695
891
  end
696
892
 
697
893
  def test_user_defined_function_forces_division
@@ -732,6 +928,17 @@ end
732
928
  assert_equal "teal\\+bang(12)", resolve("teal\\+bang(12)")
733
929
  end
734
930
 
931
+ def test_and_or_not_disallowed_as_function_names
932
+ %w[and or not].each do |name|
933
+ assert_raise_message(Sass::SyntaxError, "Invalid function name \"#{name}\".") do
934
+ render(<<SASS)
935
+ @function #{name}()
936
+ @return null
937
+ SASS
938
+ end
939
+ end
940
+ end
941
+
735
942
  def test_interpolation_after_hash
736
943
  assert_equal "#2", resolve('"##{1 + 1}"')
737
944
  end
@@ -796,6 +1003,13 @@ end
796
1003
  val.is_a?(Sass::Script::Value::String) ? val.value : val.to_s
797
1004
  end
798
1005
 
1006
+ def resolve_quoted(str, opts = {}, environment = env)
1007
+ munge_filename opts
1008
+ val = eval(str, opts, environment)
1009
+ assert_kind_of Sass::Script::Value::Base, val
1010
+ val.to_s
1011
+ end
1012
+
799
1013
  def assert_unquoted(str, opts = {}, environment = env)
800
1014
  munge_filename opts
801
1015
  val = eval(str, opts, environment)