sass 3.3.0 → 3.4.25

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 (208) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +3 -1
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/CONTRIBUTING.md +148 -0
  5. data/MIT-LICENSE +1 -1
  6. data/README.md +76 -62
  7. data/Rakefile +104 -24
  8. data/VERSION +1 -1
  9. data/VERSION_DATE +1 -1
  10. data/VERSION_NAME +1 -1
  11. data/bin/sass +1 -1
  12. data/bin/scss +1 -1
  13. data/extra/sass-spec-ref.sh +32 -0
  14. data/extra/update_watch.rb +1 -1
  15. data/lib/sass/cache_stores/filesystem.rb +9 -5
  16. data/lib/sass/cache_stores/memory.rb +4 -5
  17. data/lib/sass/callbacks.rb +2 -2
  18. data/lib/sass/css.rb +12 -13
  19. data/lib/sass/deprecation.rb +55 -0
  20. data/lib/sass/engine.rb +106 -70
  21. data/lib/sass/environment.rb +39 -19
  22. data/lib/sass/error.rb +17 -20
  23. data/lib/sass/exec/base.rb +199 -0
  24. data/lib/sass/exec/sass_convert.rb +283 -0
  25. data/lib/sass/exec/sass_scss.rb +440 -0
  26. data/lib/sass/exec.rb +5 -771
  27. data/lib/sass/features.rb +9 -2
  28. data/lib/sass/importers/base.rb +8 -3
  29. data/lib/sass/importers/filesystem.rb +30 -38
  30. data/lib/sass/logger/base.rb +8 -2
  31. data/lib/sass/logger/delayed.rb +50 -0
  32. data/lib/sass/logger.rb +8 -3
  33. data/lib/sass/media.rb +1 -4
  34. data/lib/sass/plugin/compiler.rb +224 -90
  35. data/lib/sass/plugin/configuration.rb +38 -22
  36. data/lib/sass/plugin/merb.rb +2 -2
  37. data/lib/sass/plugin/rack.rb +3 -3
  38. data/lib/sass/plugin/rails.rb +1 -1
  39. data/lib/sass/plugin/staleness_checker.rb +4 -4
  40. data/lib/sass/plugin.rb +6 -5
  41. data/lib/sass/script/css_lexer.rb +1 -1
  42. data/lib/sass/script/css_parser.rb +2 -3
  43. data/lib/sass/script/css_variable_warning.rb +52 -0
  44. data/lib/sass/script/functions.rb +739 -318
  45. data/lib/sass/script/lexer.rb +134 -54
  46. data/lib/sass/script/parser.rb +252 -56
  47. data/lib/sass/script/tree/funcall.rb +13 -6
  48. data/lib/sass/script/tree/interpolation.rb +127 -4
  49. data/lib/sass/script/tree/list_literal.rb +31 -4
  50. data/lib/sass/script/tree/literal.rb +4 -0
  51. data/lib/sass/script/tree/node.rb +21 -3
  52. data/lib/sass/script/tree/operation.rb +54 -1
  53. data/lib/sass/script/tree/selector.rb +26 -0
  54. data/lib/sass/script/tree/string_interpolation.rb +59 -38
  55. data/lib/sass/script/tree/variable.rb +1 -1
  56. data/lib/sass/script/tree.rb +1 -0
  57. data/lib/sass/script/value/base.rb +17 -14
  58. data/lib/sass/script/value/bool.rb +0 -5
  59. data/lib/sass/script/value/color.rb +78 -42
  60. data/lib/sass/script/value/helpers.rb +119 -2
  61. data/lib/sass/script/value/list.rb +0 -15
  62. data/lib/sass/script/value/map.rb +1 -1
  63. data/lib/sass/script/value/null.rb +0 -5
  64. data/lib/sass/script/value/number.rb +112 -31
  65. data/lib/sass/script/value/string.rb +102 -13
  66. data/lib/sass/script/value.rb +0 -1
  67. data/lib/sass/script.rb +3 -3
  68. data/lib/sass/scss/css_parser.rb +24 -4
  69. data/lib/sass/scss/parser.rb +290 -383
  70. data/lib/sass/scss/rx.rb +17 -9
  71. data/lib/sass/scss/static_parser.rb +306 -4
  72. data/lib/sass/scss.rb +0 -2
  73. data/lib/sass/selector/abstract_sequence.rb +35 -18
  74. data/lib/sass/selector/comma_sequence.rb +114 -19
  75. data/lib/sass/selector/pseudo.rb +266 -0
  76. data/lib/sass/selector/sequence.rb +146 -40
  77. data/lib/sass/selector/simple.rb +22 -33
  78. data/lib/sass/selector/simple_sequence.rb +122 -39
  79. data/lib/sass/selector.rb +57 -197
  80. data/lib/sass/shared.rb +2 -2
  81. data/lib/sass/source/map.rb +31 -14
  82. data/lib/sass/source/position.rb +4 -4
  83. data/lib/sass/stack.rb +2 -8
  84. data/lib/sass/supports.rb +10 -13
  85. data/lib/sass/tree/at_root_node.rb +1 -0
  86. data/lib/sass/tree/charset_node.rb +1 -1
  87. data/lib/sass/tree/comment_node.rb +1 -1
  88. data/lib/sass/tree/css_import_node.rb +9 -1
  89. data/lib/sass/tree/directive_node.rb +8 -2
  90. data/lib/sass/tree/error_node.rb +18 -0
  91. data/lib/sass/tree/extend_node.rb +1 -1
  92. data/lib/sass/tree/function_node.rb +9 -0
  93. data/lib/sass/tree/import_node.rb +6 -5
  94. data/lib/sass/tree/keyframe_rule_node.rb +15 -0
  95. data/lib/sass/tree/node.rb +5 -3
  96. data/lib/sass/tree/prop_node.rb +6 -7
  97. data/lib/sass/tree/rule_node.rb +26 -11
  98. data/lib/sass/tree/visitors/check_nesting.rb +56 -32
  99. data/lib/sass/tree/visitors/convert.rb +59 -44
  100. data/lib/sass/tree/visitors/cssize.rb +34 -30
  101. data/lib/sass/tree/visitors/deep_copy.rb +6 -1
  102. data/lib/sass/tree/visitors/extend.rb +15 -13
  103. data/lib/sass/tree/visitors/perform.rb +87 -50
  104. data/lib/sass/tree/visitors/set_options.rb +15 -1
  105. data/lib/sass/tree/visitors/to_css.rb +72 -43
  106. data/lib/sass/util/multibyte_string_scanner.rb +0 -2
  107. data/lib/sass/util/normalized_map.rb +0 -1
  108. data/lib/sass/util/subset_map.rb +2 -3
  109. data/lib/sass/util.rb +334 -154
  110. data/lib/sass/version.rb +7 -7
  111. data/lib/sass.rb +10 -8
  112. data/test/sass/cache_test.rb +62 -20
  113. data/test/sass/callbacks_test.rb +1 -1
  114. data/test/sass/compiler_test.rb +24 -11
  115. data/test/sass/conversion_test.rb +241 -50
  116. data/test/sass/css2sass_test.rb +73 -5
  117. data/test/sass/css_variable_test.rb +132 -0
  118. data/test/sass/encoding_test.rb +219 -0
  119. data/test/sass/engine_test.rb +343 -260
  120. data/test/sass/exec_test.rb +12 -2
  121. data/test/sass/extend_test.rb +333 -44
  122. data/test/sass/functions_test.rb +353 -260
  123. data/test/sass/importer_test.rb +40 -21
  124. data/test/sass/logger_test.rb +1 -1
  125. data/test/sass/more_results/more_import.css +1 -1
  126. data/test/sass/more_templates/more1.sass +10 -10
  127. data/test/sass/more_templates/more_import.sass +2 -2
  128. data/test/sass/plugin_test.rb +24 -21
  129. data/test/sass/results/compact.css +1 -1
  130. data/test/sass/results/complex.css +4 -4
  131. data/test/sass/results/expanded.css +1 -1
  132. data/test/sass/results/import.css +1 -1
  133. data/test/sass/results/import_charset_ibm866.css +2 -2
  134. data/test/sass/results/mixins.css +17 -17
  135. data/test/sass/results/nested.css +1 -1
  136. data/test/sass/results/parent_ref.css +2 -2
  137. data/test/sass/results/script.css +5 -5
  138. data/test/sass/results/scss_import.css +1 -1
  139. data/test/sass/script_conversion_test.rb +71 -39
  140. data/test/sass/script_test.rb +714 -123
  141. data/test/sass/scss/css_test.rb +213 -30
  142. data/test/sass/scss/rx_test.rb +8 -4
  143. data/test/sass/scss/scss_test.rb +766 -22
  144. data/test/sass/source_map_test.rb +263 -95
  145. data/test/sass/superselector_test.rb +210 -0
  146. data/test/sass/templates/_partial.sass +1 -1
  147. data/test/sass/templates/basic.sass +10 -10
  148. data/test/sass/templates/bork1.sass +1 -1
  149. data/test/sass/templates/bork5.sass +1 -1
  150. data/test/sass/templates/compact.sass +10 -10
  151. data/test/sass/templates/complex.sass +187 -187
  152. data/test/sass/templates/compressed.sass +10 -10
  153. data/test/sass/templates/expanded.sass +10 -10
  154. data/test/sass/templates/import.sass +2 -2
  155. data/test/sass/templates/importee.sass +3 -3
  156. data/test/sass/templates/mixins.sass +22 -22
  157. data/test/sass/templates/multiline.sass +4 -4
  158. data/test/sass/templates/nested.sass +13 -13
  159. data/test/sass/templates/parent_ref.sass +12 -12
  160. data/test/sass/templates/script.sass +70 -70
  161. data/test/sass/templates/scss_import.scss +2 -1
  162. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +1 -1
  163. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +2 -2
  164. data/test/sass/templates/subdir/subdir.sass +3 -3
  165. data/test/sass/templates/units.sass +10 -10
  166. data/test/sass/test_helper.rb +1 -1
  167. data/test/sass/util/multibyte_string_scanner_test.rb +11 -3
  168. data/test/sass/util/normalized_map_test.rb +1 -1
  169. data/test/sass/util/subset_map_test.rb +2 -2
  170. data/test/sass/util_test.rb +46 -45
  171. data/test/sass/value_helpers_test.rb +5 -7
  172. data/test/sass-spec.yml +3 -0
  173. data/test/test_helper.rb +7 -6
  174. data/vendor/listen/CHANGELOG.md +1 -228
  175. data/vendor/listen/Gemfile +5 -15
  176. data/vendor/listen/README.md +111 -77
  177. data/vendor/listen/Rakefile +0 -42
  178. data/vendor/listen/lib/listen/adapter.rb +195 -82
  179. data/vendor/listen/lib/listen/adapters/bsd.rb +27 -64
  180. data/vendor/listen/lib/listen/adapters/darwin.rb +21 -58
  181. data/vendor/listen/lib/listen/adapters/linux.rb +23 -55
  182. data/vendor/listen/lib/listen/adapters/polling.rb +25 -34
  183. data/vendor/listen/lib/listen/adapters/windows.rb +50 -46
  184. data/vendor/listen/lib/listen/directory_record.rb +96 -61
  185. data/vendor/listen/lib/listen/listener.rb +135 -37
  186. data/vendor/listen/lib/listen/turnstile.rb +9 -5
  187. data/vendor/listen/lib/listen/version.rb +1 -1
  188. data/vendor/listen/lib/listen.rb +33 -19
  189. data/vendor/listen/listen.gemspec +6 -0
  190. data/vendor/listen/spec/listen/adapter_spec.rb +43 -77
  191. data/vendor/listen/spec/listen/adapters/polling_spec.rb +8 -8
  192. data/vendor/listen/spec/listen/directory_record_spec.rb +81 -56
  193. data/vendor/listen/spec/listen/listener_spec.rb +128 -39
  194. data/vendor/listen/spec/listen_spec.rb +15 -21
  195. data/vendor/listen/spec/spec_helper.rb +4 -0
  196. data/vendor/listen/spec/support/adapter_helper.rb +52 -15
  197. data/vendor/listen/spec/support/directory_record_helper.rb +7 -5
  198. data/vendor/listen/spec/support/listeners_helper.rb +30 -7
  199. metadata +310 -300
  200. data/CONTRIBUTING +0 -3
  201. data/ext/mkrf_conf.rb +0 -27
  202. data/lib/sass/script/value/deprecated_false.rb +0 -55
  203. data/lib/sass/scss/script_lexer.rb +0 -15
  204. data/lib/sass/scss/script_parser.rb +0 -25
  205. data/vendor/listen/lib/listen/dependency_manager.rb +0 -126
  206. data/vendor/listen/lib/listen/multi_listener.rb +0 -143
  207. data/vendor/listen/spec/listen/dependency_manager_spec.rb +0 -107
  208. data/vendor/listen/spec/listen/multi_listener_spec.rb +0 -174
@@ -2,7 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
  require File.dirname(__FILE__) + '/test_helper'
4
4
 
5
- class ScssTest < Test::Unit::TestCase
5
+ class ScssTest < MiniTest::Test
6
6
  include ScssTestHelper
7
7
 
8
8
  ## One-Line Comments
@@ -115,6 +115,14 @@ SCSS
115
115
  end
116
116
  end
117
117
 
118
+ def test_error_directive
119
+ assert_raise_message(Sass::SyntaxError, "hello world!") {render(<<SCSS)}
120
+ foo {a: b}
121
+ @error "hello world!";
122
+ bar {c: d}
123
+ SCSS
124
+ end
125
+
118
126
  def test_warn_directive
119
127
  expected_warning = <<EXPECTATION
120
128
  WARNING: this is a warning
@@ -449,6 +457,15 @@ foo {a: 1 + // flang }
449
457
  SCSS
450
458
  end
451
459
 
460
+ def test_static_hyphenated_unit
461
+ assert_equal <<CSS, render(<<SCSS)
462
+ foo {
463
+ a: 0px; }
464
+ CSS
465
+ foo {a: 10px-10px }
466
+ SCSS
467
+ end
468
+
452
469
  ## Nested Rules
453
470
 
454
471
  def test_nested_rules
@@ -536,11 +553,17 @@ foo :baz {
536
553
  c: d; }
537
554
  foo bang:bop {
538
555
  e: f; }
556
+ foo ::qux {
557
+ g: h; }
558
+ foo zap::fblthp {
559
+ i: j; }
539
560
  CSS
540
561
  foo {
541
562
  .bar {a: b}
542
563
  :baz {c: d}
543
- bang:bop {e: f}}
564
+ bang:bop {e: f}
565
+ ::qux {g: h}
566
+ zap::fblthp {i: j}}
544
567
  SCSS
545
568
  end
546
569
 
@@ -645,7 +668,7 @@ SCSS
645
668
  end
646
669
 
647
670
  def test_parent_selector_with_subject
648
- assert_equal <<CSS, render(<<SCSS)
671
+ silence_warnings {assert_equal <<CSS, render(<<SCSS)}
649
672
  bar foo.baz! .bip {
650
673
  a: b; }
651
674
 
@@ -701,6 +724,26 @@ CSS
701
724
  SCSS
702
725
  end
703
726
 
727
+ def test_keyframe_bubbling
728
+ assert_equal(<<CSS, render(<<SCSS, :style => :nested))
729
+ @keyframes spin {
730
+ 0% {
731
+ transform: rotate(0deg); } }
732
+ @-webkit-keyframes spin {
733
+ 0% {
734
+ transform: rotate(0deg); } }
735
+ CSS
736
+ .foo {
737
+ @keyframes spin {
738
+ 0% {transform: rotate(0deg)}
739
+ }
740
+ @-webkit-keyframes spin {
741
+ 0% {transform: rotate(0deg)}
742
+ }
743
+ }
744
+ SCSS
745
+ end
746
+
704
747
  ## Namespace Properties
705
748
 
706
749
  def test_namespace_properties
@@ -799,18 +842,27 @@ SCSS
799
842
  def test_no_namespace_properties_without_space_even_when_its_unambiguous
800
843
  render(<<SCSS)
801
844
  foo {
802
- bar:1px {
845
+ bar:baz calc(1 + 2) {
803
846
  bip: bop }}
804
847
  SCSS
805
848
  assert(false, "Expected syntax error")
806
849
  rescue Sass::SyntaxError => e
807
- assert_equal <<MESSAGE, e.message
808
- Invalid CSS: a space is required between a property and its definition
809
- when it has other properties nested beneath it.
810
- MESSAGE
850
+ assert_equal 'Invalid CSS after "bar:baz calc": expected selector, was "(1 + 2)"', e.message
811
851
  assert_equal 2, e.sass_line
812
852
  end
813
853
 
854
+ def test_namespace_properties_without_space_allowed_for_non_identifier
855
+ assert_equal <<CSS, render(<<SCSS)
856
+ foo {
857
+ bar: 1px;
858
+ bar-bip: bop; }
859
+ CSS
860
+ foo {
861
+ bar:1px {
862
+ bip: bop }}
863
+ SCSS
864
+ end
865
+
814
866
  ## Mixins
815
867
 
816
868
  def test_basic_mixins
@@ -903,6 +955,33 @@ CSS
903
955
  SCSS
904
956
  end
905
957
 
958
+ def test_keyframes_rules_in_content
959
+ assert_equal <<CSS, render(<<SCSS)
960
+ @keyframes identifier {
961
+ 0% {
962
+ top: 0;
963
+ left: 0; }
964
+ 30% {
965
+ top: 50px; }
966
+ 68%, 72% {
967
+ left: 50px; }
968
+ 100% {
969
+ top: 100px;
970
+ left: 100%; } }
971
+ CSS
972
+ @mixin keyframes {
973
+ @keyframes identifier { @content }
974
+ }
975
+
976
+ @include keyframes {
977
+ 0% {top: 0; left: 0}
978
+ \#{"30%"} {top: 50px}
979
+ 68%, 72% {left: 50px}
980
+ 100% {top: 100px; left: 100%}
981
+ }
982
+ SCSS
983
+ end
984
+
906
985
  ## Functions
907
986
 
908
987
  def test_basic_function
@@ -935,6 +1014,78 @@ bar {
935
1014
  SASS
936
1015
  end
937
1016
 
1017
+ def test_disallowed_function_names
1018
+ Sass::Deprecation.allow_double_warnings do
1019
+ assert_warning(<<WARNING) {render(<<SCSS)}
1020
+ DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1021
+ Naming a function "calc" is disallowed and will be an error in future versions of Sass.
1022
+ This name conflicts with an existing CSS function with special parse rules.
1023
+ WARNING
1024
+ @function calc() {}
1025
+ SCSS
1026
+
1027
+ assert_warning(<<WARNING) {render(<<SCSS)}
1028
+ DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1029
+ Naming a function "-my-calc" is disallowed and will be an error in future versions of Sass.
1030
+ This name conflicts with an existing CSS function with special parse rules.
1031
+ WARNING
1032
+ @function -my-calc() {}
1033
+ SCSS
1034
+
1035
+ assert_warning(<<WARNING) {render(<<SCSS)}
1036
+ DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1037
+ Naming a function "element" is disallowed and will be an error in future versions of Sass.
1038
+ This name conflicts with an existing CSS function with special parse rules.
1039
+ WARNING
1040
+ @function element() {}
1041
+ SCSS
1042
+
1043
+ assert_warning(<<WARNING) {render(<<SCSS)}
1044
+ DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1045
+ Naming a function "-my-element" is disallowed and will be an error in future versions of Sass.
1046
+ This name conflicts with an existing CSS function with special parse rules.
1047
+ WARNING
1048
+ @function -my-element() {}
1049
+ SCSS
1050
+
1051
+ assert_warning(<<WARNING) {render(<<SCSS)}
1052
+ DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1053
+ Naming a function "expression" is disallowed and will be an error in future versions of Sass.
1054
+ This name conflicts with an existing CSS function with special parse rules.
1055
+ WARNING
1056
+ @function expression() {}
1057
+ SCSS
1058
+
1059
+ assert_warning(<<WARNING) {render(<<SCSS)}
1060
+ DEPRECATION WARNING on line 1 of test_disallowed_function_names_inline.scss:
1061
+ Naming a function "url" is disallowed and will be an error in future versions of Sass.
1062
+ This name conflicts with an existing CSS function with special parse rules.
1063
+ WARNING
1064
+ @function url() {}
1065
+ SCSS
1066
+ end
1067
+ end
1068
+
1069
+ def test_allowed_function_names
1070
+ assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
1071
+ .a {
1072
+ b: c; }
1073
+ CSS
1074
+ @function -my-expression() {@return c}
1075
+
1076
+ .a {b: -my-expression()}
1077
+ SCSS
1078
+
1079
+ assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
1080
+ .a {
1081
+ b: c; }
1082
+ CSS
1083
+ @function -my-url() {@return c}
1084
+
1085
+ .a {b: -my-url()}
1086
+ SCSS
1087
+ end
1088
+
938
1089
  ## Var Args
939
1090
 
940
1091
  def test_mixin_var_args
@@ -1459,6 +1610,17 @@ SCSS
1459
1610
  SCSS
1460
1611
  end
1461
1612
 
1613
+ def test_mixin_splat_too_many_args
1614
+ assert_warning(<<WARNING) {render <<SCSS}
1615
+ WARNING: Mixin foo takes 2 arguments but 4 were passed.
1616
+ on line 2 of #{filename_for_test(:scss)}
1617
+ This will be an error in future versions of Sass.
1618
+ WARNING
1619
+ @mixin foo($a, $b) {}
1620
+ @include foo((1, 2, 3, 4)...);
1621
+ SCSS
1622
+ end
1623
+
1462
1624
  def test_function_var_args
1463
1625
  assert_equal <<CSS, render(<<SCSS)
1464
1626
  .foo {
@@ -1880,14 +2042,25 @@ MESSAGE
1880
2042
  SCSS
1881
2043
  end
1882
2044
 
2045
+ def test_function_splat_too_many_args
2046
+ assert_warning(<<WARNING) {render <<SCSS}
2047
+ WARNING: Function foo takes 2 arguments but 4 were passed.
2048
+ on line 2 of #{filename_for_test(:scss)}
2049
+ This will be an error in future versions of Sass.
2050
+ WARNING
2051
+ @function foo($a, $b) {@return null}
2052
+ $var: foo((1, 2, 3, 4)...);
2053
+ SCSS
2054
+ end
2055
+
1883
2056
  ## Interpolation
1884
2057
 
1885
2058
  def test_basic_selector_interpolation
1886
2059
  assert_equal <<CSS, render(<<SCSS)
1887
- foo 3 baz {
2060
+ foo ab baz {
1888
2061
  a: b; }
1889
2062
  CSS
1890
- foo \#{1 + 2} baz {a: b}
2063
+ foo \#{'a' + 'b'} baz {a: b}
1891
2064
  SCSS
1892
2065
  assert_equal <<CSS, render(<<SCSS)
1893
2066
  foo.bar baz {
@@ -2001,7 +2174,7 @@ SCSS
2001
2174
  end
2002
2175
 
2003
2176
  def test_selector_interpolation_in_reference_combinator
2004
- assert_equal <<CSS, render(<<SCSS)
2177
+ silence_warnings {assert_equal <<CSS, render(<<SCSS)}
2005
2178
  .foo /a/ .bar /b|c/ .baz {
2006
2179
  a: b; }
2007
2180
  CSS
@@ -2013,7 +2186,7 @@ SCSS
2013
2186
  end
2014
2187
 
2015
2188
  def test_parent_selector_with_parent_and_subject
2016
- assert_equal <<CSS, render(<<SCSS)
2189
+ silence_warnings {assert_equal <<CSS, render(<<SCSS)}
2017
2190
  bar foo.baz! .bip {
2018
2191
  c: d; }
2019
2192
  CSS
@@ -2134,14 +2307,14 @@ SCSS
2134
2307
 
2135
2308
  def test_supports_with_expressions
2136
2309
  assert_equal <<CSS, render(<<SCSS)
2137
- @supports (feature1: val) and (feature2: val) or (not (feature23: val4)) {
2310
+ @supports ((feature1: val) and (feature2: val)) or (not (feature23: val4)) {
2138
2311
  foo {
2139
2312
  a: b; } }
2140
2313
  CSS
2141
2314
  $query: "(feature1: val)";
2142
2315
  $feature: feature2;
2143
2316
  $val: val;
2144
- @supports \#{$query} and ($feature: $val) or (not ($feature + 3: $val + 4)) {
2317
+ @supports (\#{$query} and ($feature: $val)) or (not ($feature + 3: $val + 4)) {
2145
2318
  foo {a: b}
2146
2319
  }
2147
2320
  SCSS
@@ -2186,6 +2359,69 @@ $domain: "sass-lang.com";
2186
2359
  SCSS
2187
2360
  end
2188
2361
 
2362
+ def test_color_interpolation_warning_in_selector
2363
+ assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
2364
+ WARNING on line 1, column 4 of #{filename_for_test(:scss)}:
2365
+ You probably don't mean to use the color value `blue' in interpolation here.
2366
+ It may end up represented as #0000ff, which will likely produce invalid CSS.
2367
+ Always quote color names when using them as strings (for example, "blue").
2368
+ If you really want to use the color value here, use `"" + blue'.
2369
+ WARNING
2370
+ fooblue {
2371
+ a: b; }
2372
+ CSS
2373
+ foo\#{blue} {a: b}
2374
+ SCSS
2375
+ end
2376
+
2377
+ def test_color_interpolation_warning_in_directive
2378
+ assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
2379
+ WARNING on line 1, column 12 of #{filename_for_test(:scss)}:
2380
+ You probably don't mean to use the color value `blue' in interpolation here.
2381
+ It may end up represented as #0000ff, which will likely produce invalid CSS.
2382
+ Always quote color names when using them as strings (for example, "blue").
2383
+ If you really want to use the color value here, use `"" + blue'.
2384
+ WARNING
2385
+ @fblthp fooblue {
2386
+ a: b; }
2387
+ CSS
2388
+ @fblthp foo\#{blue} {a: b}
2389
+ SCSS
2390
+ end
2391
+
2392
+ def test_color_interpolation_warning_in_property_name
2393
+ assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
2394
+ WARNING on line 1, column 8 of #{filename_for_test(:scss)}:
2395
+ You probably don't mean to use the color value `blue' in interpolation here.
2396
+ It may end up represented as #0000ff, which will likely produce invalid CSS.
2397
+ Always quote color names when using them as strings (for example, "blue").
2398
+ If you really want to use the color value here, use `"" + blue'.
2399
+ WARNING
2400
+ foo {
2401
+ a-blue: b; }
2402
+ CSS
2403
+ foo {a-\#{blue}: b}
2404
+ SCSS
2405
+ end
2406
+
2407
+ def test_no_color_interpolation_warning_in_property_value
2408
+ assert_no_warning {assert_equal <<CSS, render(<<SCSS)}
2409
+ foo {
2410
+ a: b-blue; }
2411
+ CSS
2412
+ foo {a: b-\#{blue}}
2413
+ SCSS
2414
+ end
2415
+
2416
+ def test_no_color_interpolation_warning_for_nameless_color
2417
+ assert_no_warning {assert_equal <<CSS, render(<<SCSS)}
2418
+ foo-#abcdef {
2419
+ a: b; }
2420
+ CSS
2421
+ foo-\#{#abcdef} {a: b}
2422
+ SCSS
2423
+ end
2424
+
2189
2425
  def test_nested_mixin_def
2190
2426
  assert_equal <<CSS, render(<<SCSS)
2191
2427
  foo {
@@ -2848,8 +3084,283 @@ CSS
2848
3084
  SCSS
2849
3085
  end
2850
3086
 
3087
+ def test_at_root_without_keyframes_in_keyframe_rule
3088
+ assert_equal <<CSS, render(<<SCSS)
3089
+ .foo {
3090
+ a: b; }
3091
+ CSS
3092
+ @keyframes identifier {
3093
+ 0% {
3094
+ @at-root (without: keyframes) {
3095
+ .foo {a: b}
3096
+ }
3097
+ }
3098
+ }
3099
+ SCSS
3100
+ end
3101
+
3102
+ def test_at_root_without_rule_in_keyframe_rule
3103
+ assert_equal <<CSS, render(<<SCSS)
3104
+ @keyframes identifier {
3105
+ 0% {
3106
+ a: b; } }
3107
+ CSS
3108
+ @keyframes identifier {
3109
+ 0% {
3110
+ @at-root (without: rule) {a: b}
3111
+ }
3112
+ }
3113
+ SCSS
3114
+ end
3115
+
3116
+ ## Selector Script
3117
+
3118
+ def test_selector_script
3119
+ assert_equal(<<CSS, render(<<SCSS))
3120
+ .foo .bar {
3121
+ content: ".foo .bar"; }
3122
+ CSS
3123
+ .foo .bar {
3124
+ content: "\#{&}";
3125
+ }
3126
+ SCSS
3127
+ end
3128
+
3129
+ def test_nested_selector_script
3130
+ assert_equal(<<CSS, render(<<SCSS))
3131
+ .foo .bar {
3132
+ content: ".foo .bar"; }
3133
+ CSS
3134
+ .foo {
3135
+ .bar {
3136
+ content: "\#{&}";
3137
+ }
3138
+ }
3139
+ SCSS
3140
+ end
3141
+
3142
+ def test_nested_selector_script_with_outer_comma_selector
3143
+ assert_equal(<<CSS, render(<<SCSS))
3144
+ .foo .baz, .bar .baz {
3145
+ content: ".foo .baz, .bar .baz"; }
3146
+ CSS
3147
+ .foo, .bar {
3148
+ .baz {
3149
+ content: "\#{&}";
3150
+ }
3151
+ }
3152
+ SCSS
3153
+ end
3154
+
3155
+ def test_nested_selector_script_with_inner_comma_selector
3156
+ assert_equal(<<CSS, render(<<SCSS))
3157
+ .foo .bar, .foo .baz {
3158
+ content: ".foo .bar, .foo .baz"; }
3159
+ CSS
3160
+ .foo {
3161
+ .bar, .baz {
3162
+ content: "\#{&}";
3163
+ }
3164
+ }
3165
+ SCSS
3166
+ end
3167
+
3168
+ def test_selector_script_through_mixin
3169
+ assert_equal(<<CSS, render(<<SCSS))
3170
+ .foo {
3171
+ content: ".foo"; }
3172
+ CSS
3173
+ @mixin mixin {
3174
+ content: "\#{&}";
3175
+ }
3176
+
3177
+ .foo {
3178
+ @include mixin;
3179
+ }
3180
+ SCSS
3181
+ end
3182
+
3183
+ def test_selector_script_through_content
3184
+ assert_equal(<<CSS, render(<<SCSS))
3185
+ .foo {
3186
+ content: ".foo"; }
3187
+ CSS
3188
+ @mixin mixin {
3189
+ @content;
3190
+ }
3191
+
3192
+ .foo {
3193
+ @include mixin {
3194
+ content: "\#{&}";
3195
+ }
3196
+ }
3197
+ SCSS
3198
+ end
3199
+
3200
+ def test_selector_script_through_function
3201
+ assert_equal(<<CSS, render(<<SCSS))
3202
+ .foo {
3203
+ content: ".foo"; }
3204
+ CSS
3205
+ @function fn() {
3206
+ @return "\#{&}";
3207
+ }
3208
+
3209
+ .foo {
3210
+ content: fn();
3211
+ }
3212
+ SCSS
3213
+ end
3214
+
3215
+ def test_selector_script_through_media
3216
+ assert_equal(<<CSS, render(<<SCSS))
3217
+ .foo {
3218
+ content: "outer"; }
3219
+ @media screen {
3220
+ .foo .bar {
3221
+ content: ".foo .bar"; } }
3222
+ CSS
3223
+ .foo {
3224
+ content: "outer";
3225
+ @media screen {
3226
+ .bar {
3227
+ content: "\#{&}";
3228
+ }
3229
+ }
3230
+ }
3231
+ SCSS
3232
+ end
3233
+
3234
+ def test_selector_script_save_and_reuse
3235
+ assert_equal(<<CSS, render(<<SCSS))
3236
+ .bar {
3237
+ content: ".foo"; }
3238
+ CSS
3239
+ $var: null;
3240
+ .foo {
3241
+ $var: & !global;
3242
+ }
3243
+
3244
+ .bar {
3245
+ content: "\#{$var}";
3246
+ }
3247
+ SCSS
3248
+ end
3249
+
3250
+ def test_selector_script_with_at_root
3251
+ assert_equal(<<CSS, render(<<SCSS))
3252
+ .foo-bar {
3253
+ a: b; }
3254
+ CSS
3255
+ .foo {
3256
+ @at-root \#{&}-bar {
3257
+ a: b;
3258
+ }
3259
+ }
3260
+ SCSS
3261
+ end
3262
+
3263
+ def test_multi_level_at_root_with_inner_selector_script
3264
+ assert_equal <<CSS, render(<<SCSS)
3265
+ .bar {
3266
+ a: b; }
3267
+ CSS
3268
+ .foo {
3269
+ @at-root .bar {
3270
+ @at-root \#{&} {
3271
+ a: b;
3272
+ }
3273
+ }
3274
+ }
3275
+ SCSS
3276
+ end
3277
+
3278
+ def test_at_root_with_at_root_through_mixin
3279
+ assert_equal(<<CSS, render(<<SCSS))
3280
+ .bar-baz {
3281
+ a: b; }
3282
+ CSS
3283
+ @mixin foo {
3284
+ .bar {
3285
+ @at-root \#{&}-baz {
3286
+ a: b;
3287
+ }
3288
+ }
3289
+ }
3290
+
3291
+ @include foo;
3292
+ SCSS
3293
+ end
3294
+
3295
+ # See https://github.com/sass/sass/issues/1294
3296
+ def test_extend_top_leveled_by_at_root
3297
+ render(<<SCSS)
3298
+ .span-10 {
3299
+ @at-root (without: all) {
3300
+ @extend %column;
3301
+ }
3302
+ }
3303
+ SCSS
3304
+
3305
+ assert(false, "Expected syntax error")
3306
+ rescue Sass::SyntaxError => e
3307
+ assert_equal "Extend directives may only be used within rules.", e.message
3308
+ assert_equal 3, e.sass_line
3309
+ end
3310
+
3311
+ def test_at_root_doesnt_always_break_blocks
3312
+ assert_equal <<CSS, render(<<SCSS)
3313
+ .foo {
3314
+ a: b; }
3315
+
3316
+ @media screen {
3317
+ .foo {
3318
+ c: d; }
3319
+ .bar {
3320
+ e: f; } }
3321
+ CSS
3322
+ %base {
3323
+ a: b;
3324
+ }
3325
+
3326
+ @media screen {
3327
+ .foo {
3328
+ c: d;
3329
+ @at-root (without: media) {
3330
+ @extend %base;
3331
+ }
3332
+ }
3333
+
3334
+ .bar {e: f}
3335
+ }
3336
+ SCSS
3337
+ end
3338
+
2851
3339
  ## Errors
2852
3340
 
3341
+ def test_keyframes_rule_outside_of_keyframes
3342
+ render <<SCSS
3343
+ 0% {
3344
+ top: 0; }
3345
+ SCSS
3346
+ assert(false, "Expected syntax error")
3347
+ rescue Sass::SyntaxError => e
3348
+ assert_equal 'Invalid CSS after "": expected selector, was "0%"', e.message
3349
+ assert_equal 1, e.sass_line
3350
+ end
3351
+
3352
+ def test_selector_rule_in_keyframes
3353
+ render <<SCSS
3354
+ @keyframes identifier {
3355
+ .foo {
3356
+ top: 0; } }
3357
+ SCSS
3358
+ assert(false, "Expected syntax error")
3359
+ rescue Sass::SyntaxError => e
3360
+ assert_equal 'Invalid CSS after "": expected keyframes selector (e.g. 10%), was ".foo"', e.message
3361
+ assert_equal 2, e.sass_line
3362
+ end
3363
+
2853
3364
  def test_nested_mixin_def_is_scoped
2854
3365
  render <<SCSS
2855
3366
  foo {
@@ -2904,7 +3415,7 @@ foo {
2904
3415
  SCSS
2905
3416
  assert(false, "Expected syntax error")
2906
3417
  rescue Sass::SyntaxError => e
2907
- assert_equal 'Invalid CSS after " .bar:baz ": expected "{", was "<fail>; }"', e.message
3418
+ assert_equal 'Invalid CSS after " .bar:baz <fail>": expected expression (e.g. 1px, bold), was "; }"', e.message
2908
3419
  assert_equal 2, e.sass_line
2909
3420
  end
2910
3421
 
@@ -3014,7 +3525,7 @@ SCSS
3014
3525
 
3015
3526
  def test_parent_in_mid_selector_error
3016
3527
  assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
3017
- Invalid CSS after " .foo": expected "{", was "&.bar {a: b}"
3528
+ Invalid CSS after ".foo": expected "{", was "&.bar"
3018
3529
 
3019
3530
  "&.bar" may only be used at the beginning of a compound selector.
3020
3531
  MESSAGE
@@ -3026,7 +3537,7 @@ SCSS
3026
3537
 
3027
3538
  def test_parent_after_selector_error
3028
3539
  assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
3029
- Invalid CSS after " .foo.bar": expected "{", was "& {a: b}"
3540
+ Invalid CSS after ".foo.bar": expected "{", was "&"
3030
3541
 
3031
3542
  "&" may only be used at the beginning of a compound selector.
3032
3543
  MESSAGE
@@ -3038,7 +3549,7 @@ SCSS
3038
3549
 
3039
3550
  def test_double_parent_selector_error
3040
3551
  assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render <<SCSS}
3041
- Invalid CSS after " &": expected "{", was "& {a: b}"
3552
+ Invalid CSS after "&": expected "{", was "&"
3042
3553
 
3043
3554
  "&" may only be used at the beginning of a compound selector.
3044
3555
  MESSAGE
@@ -3098,8 +3609,184 @@ MESSAGE
3098
3609
  SCSS
3099
3610
  end
3100
3611
 
3612
+ def test_empty_media_query_error
3613
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3614
+ Invalid CSS after "": expected media query list, was ""
3615
+ MESSAGE
3616
+ @media \#{""} {
3617
+ foo {a: b}
3618
+ }
3619
+ SCSS
3620
+ end
3621
+
3622
+ def test_newline_in_property_value
3623
+ assert_equal(<<CSS, render(<<SCSS))
3624
+ .foo {
3625
+ bar: "bazbang"; }
3626
+ CSS
3627
+ .foo {
3628
+ $var: "baz\\
3629
+ bang";
3630
+ bar: $var;
3631
+ }
3632
+ SCSS
3633
+ end
3634
+
3635
+ def test_raw_newline_warning
3636
+ assert_warning(<<MESSAGE.rstrip) {assert_equal(<<CSS, render(<<SCSS))}
3637
+ DEPRECATION WARNING on line 2, column 9 of #{filename_for_test :scss}:
3638
+ Unescaped multiline strings are deprecated and will be removed in a future version of Sass.
3639
+ To include a newline in a string, use "\\a" or "\\a " as in CSS.
3640
+ MESSAGE
3641
+ .foo {
3642
+ bar: "baz\\a bang"; }
3643
+ CSS
3644
+ .foo {
3645
+ $var: "baz
3646
+ bang";
3647
+ bar: $var;
3648
+ }
3649
+ SCSS
3650
+ end
3651
+
3101
3652
  # Regression
3102
-
3653
+
3654
+ # Regression test for #2031.
3655
+ def test_no_interpolation_warning_in_nested_selector
3656
+ assert_no_warning {assert_equal(<<CSS, render(<<SCSS))}
3657
+ z a:b(n+1) {
3658
+ x: y; }
3659
+ CSS
3660
+ z {
3661
+ a:b(n+\#{1}) {
3662
+ x: y;
3663
+ }
3664
+ }
3665
+ SCSS
3666
+ end
3667
+
3668
+ # Ensures that the fix for #2031 doesn't hide legitimate warnings.
3669
+ def test_interpolation_warning_in_selector_like_property
3670
+ assert_warning(<<WARNING) {assert_equal(<<CSS, render(<<SCSS))}
3671
+ DEPRECATION WARNING on line 2 of #{filename_for_test :scss}:
3672
+ \#{} interpolation near operators will be simplified in a future version of Sass.
3673
+ To preserve the current behavior, use quotes:
3674
+
3675
+ unquote("n+1")
3676
+
3677
+ You can use the sass-convert command to automatically fix most cases.
3678
+ WARNING
3679
+ z {
3680
+ a: b(n+1); }
3681
+ CSS
3682
+ z {
3683
+ a:b(n+\#{1});
3684
+ }
3685
+ SCSS
3686
+ end
3687
+
3688
+ def test_escape_in_selector
3689
+ assert_equal(<<CSS, render(".\\!foo {a: b}"))
3690
+ .\\!foo {
3691
+ a: b; }
3692
+ CSS
3693
+ end
3694
+
3695
+ def test_for_directive_with_float_bounds
3696
+ assert_equal(<<CSS, render(<<SCSS))
3697
+ .a {
3698
+ b: 0;
3699
+ b: 1;
3700
+ b: 2;
3701
+ b: 3;
3702
+ b: 4;
3703
+ b: 5; }
3704
+ CSS
3705
+ .a {
3706
+ @for $i from 0.0 through 5.0 {b: $i}
3707
+ }
3708
+ SCSS
3709
+
3710
+ assert_raise_message(Sass::SyntaxError, "0.5 is not an integer.") {render(<<SCSS)}
3711
+ .a {
3712
+ @for $i from 0.5 through 5.0 {b: $i}
3713
+ }
3714
+ SCSS
3715
+
3716
+ assert_raise_message(Sass::SyntaxError, "5.5 is not an integer.") {render(<<SCSS)}
3717
+ .a {
3718
+ @for $i from 0.0 through 5.5 {b: $i}
3719
+ }
3720
+ SCSS
3721
+ end
3722
+
3723
+ def test_parent_selector_in_function_pseudo_selector
3724
+ assert_equal <<CSS, render(<<SCSS)
3725
+ .bar:not(.foo) {
3726
+ a: b; }
3727
+
3728
+ .qux:nth-child(2n of .baz .bang) {
3729
+ c: d; }
3730
+ CSS
3731
+ .foo {
3732
+ .bar:not(&) {a: b}
3733
+ }
3734
+
3735
+ .baz .bang {
3736
+ .qux:nth-child(2n of &) {c: d}
3737
+ }
3738
+ SCSS
3739
+ end
3740
+
3741
+ def test_parent_selector_in_and_out_of_function_pseudo_selector
3742
+ # Regression test for https://github.com/sass/sass/issues/1464#issuecomment-70352288
3743
+ assert_equal(<<CSS, render(<<SCSS))
3744
+ .a:not(.a-b) {
3745
+ x: y; }
3746
+ CSS
3747
+ .a {
3748
+ &:not(&-b) {
3749
+ x: y;
3750
+ }
3751
+ }
3752
+ SCSS
3753
+
3754
+ assert_equal(<<CSS, render(<<SCSS))
3755
+ .a:nth-child(2n of .a-b) {
3756
+ x: y; }
3757
+ CSS
3758
+ .a {
3759
+ &:nth-child(2n of &-b) {
3760
+ x: y;
3761
+ }
3762
+ }
3763
+ SCSS
3764
+ end
3765
+
3766
+ def test_attribute_selector_in_selector_pseudoclass
3767
+ # Even though this is plain CSS, it only failed when given to the SCSS
3768
+ # parser.
3769
+ assert_equal(<<CSS, render(<<SCSS))
3770
+ [href^='http://'] {
3771
+ color: red; }
3772
+ CSS
3773
+ [href^='http://'] {
3774
+ color: red;
3775
+ }
3776
+ SCSS
3777
+ end
3778
+
3779
+ def test_top_level_unknown_directive_in_at_root
3780
+ assert_equal(<<CSS, render(<<SCSS))
3781
+ @fblthp {
3782
+ a: b; }
3783
+ CSS
3784
+ @at-root {
3785
+ @fblthp {a: b}
3786
+ }
3787
+ SCSS
3788
+ end
3789
+
3103
3790
  def test_parent_ref_with_newline
3104
3791
  assert_equal(<<CSS, render(<<SCSS))
3105
3792
  a.c
@@ -3173,7 +3860,19 @@ SCSS
3173
3860
  end
3174
3861
 
3175
3862
  def test_reference_combinator_with_parent_ref
3176
- assert_equal <<CSS, render(<<SCSS)
3863
+ silence_warnings {assert_equal <<CSS, render(<<SCSS)}
3864
+ a /foo/ b {
3865
+ c: d; }
3866
+ CSS
3867
+ a {& /foo/ b {c: d}}
3868
+ SCSS
3869
+ end
3870
+
3871
+ def test_reference_combinator_warning
3872
+ assert_warning(<<WARNING) {assert_equal <<CSS, render(<<SCSS)}
3873
+ DEPRECATION WARNING on line 1, column 8 of test_reference_combinator_warning_inline.scss:
3874
+ The reference combinator /foo/ is deprecated and will be removed in a future release.
3875
+ WARNING
3177
3876
  a /foo/ b {
3178
3877
  c: d; }
3179
3878
  CSS
@@ -3283,6 +3982,22 @@ CSS
3283
3982
  SCSS
3284
3983
  end
3285
3984
 
3985
+ def test_keyword_arg_scope
3986
+ assert_equal <<CSS, render(<<SCSS)
3987
+ .mixed {
3988
+ arg1: default;
3989
+ arg2: non-default; }
3990
+ CSS
3991
+ $arg1: default;
3992
+ $arg2: default;
3993
+ @mixin a-mixin($arg1: $arg1, $arg2: $arg2) {
3994
+ arg1: $arg1;
3995
+ arg2: $arg2;
3996
+ }
3997
+ .mixed { @include a-mixin($arg2: non-default); }
3998
+ SCSS
3999
+ end
4000
+
3286
4001
  def test_passing_required_args_as_a_keyword_arg
3287
4002
  assert_equal <<CSS, render(<<SCSS)
3288
4003
  .mixed {
@@ -3422,10 +4137,10 @@ SCSS
3422
4137
  }
3423
4138
  .aaa .aaa .aaa {
3424
4139
  background-color: black;
3425
- }
4140
+ }
3426
4141
  .bbb {
3427
4142
  @extend .aaa;
3428
- }
4143
+ }
3429
4144
  .xxx {
3430
4145
  @extend .bbb;
3431
4146
  }
@@ -3458,4 +4173,33 @@ CSS
3458
4173
  }
3459
4174
  SCSS
3460
4175
  end
4176
+
4177
+ def test_import_with_supports_clause_interp
4178
+ assert_equal(<<CSS, render(<<'SASS', :style => :compressed))
4179
+ @import url("fallback-layout.css") supports(not (display: flex))
4180
+ CSS
4181
+ $display-type: flex;
4182
+ @import url("fallback-layout.css") supports(not (display: #{$display-type}));
4183
+ SASS
4184
+ end
4185
+
4186
+ def test_import_with_supports_clause
4187
+ assert_equal(<<CSS, render(<<SASS, :style => :compressed))
4188
+ @import url("fallback-layout.css") supports(not (display: flex));.foo{bar:baz}
4189
+ CSS
4190
+ @import url("fallback-layout.css") supports(not (display: flex));
4191
+ .foo { bar: baz; }
4192
+ SASS
4193
+ end
4194
+
4195
+ def test_crlf
4196
+ # Attempt to reproduce https://github.com/sass/sass/issues/1985
4197
+ assert_equal(<<CSS, render(<<SCSS))
4198
+ p {
4199
+ margin: 0; }
4200
+ CSS
4201
+ p {\r\n margin: 0;\r\n}
4202
+ SCSS
4203
+ end
4204
+
3461
4205
  end