sass 3.4.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 (142) 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 +26 -20
  7. data/Rakefile +103 -20
  8. data/VERSION +1 -1
  9. data/VERSION_DATE +1 -1
  10. data/extra/sass-spec-ref.sh +32 -0
  11. data/extra/update_watch.rb +1 -1
  12. data/lib/sass/cache_stores/filesystem.rb +7 -7
  13. data/lib/sass/cache_stores/memory.rb +4 -5
  14. data/lib/sass/callbacks.rb +2 -2
  15. data/lib/sass/css.rb +11 -10
  16. data/lib/sass/deprecation.rb +55 -0
  17. data/lib/sass/engine.rb +83 -38
  18. data/lib/sass/environment.rb +26 -2
  19. data/lib/sass/error.rb +12 -12
  20. data/lib/sass/exec/base.rb +15 -3
  21. data/lib/sass/exec/sass_convert.rb +34 -15
  22. data/lib/sass/exec/sass_scss.rb +23 -7
  23. data/lib/sass/features.rb +2 -2
  24. data/lib/sass/importers/base.rb +1 -1
  25. data/lib/sass/importers/deprecated_path.rb +51 -0
  26. data/lib/sass/importers/filesystem.rb +24 -16
  27. data/lib/sass/importers.rb +1 -0
  28. data/lib/sass/logger/base.rb +8 -2
  29. data/lib/sass/logger/delayed.rb +50 -0
  30. data/lib/sass/logger.rb +8 -3
  31. data/lib/sass/plugin/compiler.rb +42 -25
  32. data/lib/sass/plugin/configuration.rb +38 -22
  33. data/lib/sass/plugin/merb.rb +2 -2
  34. data/lib/sass/plugin/rack.rb +3 -3
  35. data/lib/sass/plugin/rails.rb +1 -1
  36. data/lib/sass/plugin/staleness_checker.rb +3 -3
  37. data/lib/sass/plugin.rb +3 -2
  38. data/lib/sass/script/css_parser.rb +2 -3
  39. data/lib/sass/script/css_variable_warning.rb +52 -0
  40. data/lib/sass/script/functions.rb +140 -73
  41. data/lib/sass/script/lexer.rb +37 -22
  42. data/lib/sass/script/parser.rb +235 -40
  43. data/lib/sass/script/tree/funcall.rb +12 -5
  44. data/lib/sass/script/tree/interpolation.rb +109 -4
  45. data/lib/sass/script/tree/list_literal.rb +31 -4
  46. data/lib/sass/script/tree/literal.rb +4 -0
  47. data/lib/sass/script/tree/node.rb +21 -3
  48. data/lib/sass/script/tree/operation.rb +54 -1
  49. data/lib/sass/script/tree/string_interpolation.rb +58 -37
  50. data/lib/sass/script/tree/variable.rb +1 -1
  51. data/lib/sass/script/value/base.rb +10 -9
  52. data/lib/sass/script/value/color.rb +42 -24
  53. data/lib/sass/script/value/helpers.rb +16 -6
  54. data/lib/sass/script/value/map.rb +1 -1
  55. data/lib/sass/script/value/number.rb +52 -19
  56. data/lib/sass/script/value/string.rb +46 -5
  57. data/lib/sass/script.rb +3 -3
  58. data/lib/sass/scss/css_parser.rb +16 -2
  59. data/lib/sass/scss/parser.rb +120 -75
  60. data/lib/sass/scss/rx.rb +9 -10
  61. data/lib/sass/scss/static_parser.rb +19 -14
  62. data/lib/sass/scss.rb +0 -2
  63. data/lib/sass/selector/abstract_sequence.rb +8 -6
  64. data/lib/sass/selector/comma_sequence.rb +25 -9
  65. data/lib/sass/selector/pseudo.rb +45 -35
  66. data/lib/sass/selector/sequence.rb +54 -18
  67. data/lib/sass/selector/simple.rb +11 -11
  68. data/lib/sass/selector/simple_sequence.rb +34 -15
  69. data/lib/sass/selector.rb +7 -10
  70. data/lib/sass/shared.rb +1 -1
  71. data/lib/sass/source/map.rb +7 -4
  72. data/lib/sass/source/position.rb +4 -4
  73. data/lib/sass/stack.rb +2 -2
  74. data/lib/sass/supports.rb +8 -10
  75. data/lib/sass/tree/comment_node.rb +1 -1
  76. data/lib/sass/tree/css_import_node.rb +9 -1
  77. data/lib/sass/tree/function_node.rb +8 -3
  78. data/lib/sass/tree/import_node.rb +6 -5
  79. data/lib/sass/tree/node.rb +5 -3
  80. data/lib/sass/tree/prop_node.rb +5 -6
  81. data/lib/sass/tree/rule_node.rb +14 -4
  82. data/lib/sass/tree/visitors/check_nesting.rb +18 -22
  83. data/lib/sass/tree/visitors/convert.rb +43 -26
  84. data/lib/sass/tree/visitors/cssize.rb +5 -1
  85. data/lib/sass/tree/visitors/deep_copy.rb +1 -1
  86. data/lib/sass/tree/visitors/extend.rb +15 -13
  87. data/lib/sass/tree/visitors/perform.rb +42 -17
  88. data/lib/sass/tree/visitors/set_options.rb +1 -1
  89. data/lib/sass/tree/visitors/to_css.rb +58 -30
  90. data/lib/sass/util/multibyte_string_scanner.rb +0 -2
  91. data/lib/sass/util/normalized_map.rb +0 -1
  92. data/lib/sass/util/subset_map.rb +1 -2
  93. data/lib/sass/util.rb +125 -68
  94. data/lib/sass/version.rb +2 -2
  95. data/lib/sass.rb +10 -3
  96. data/test/sass/compiler_test.rb +6 -2
  97. data/test/sass/conversion_test.rb +187 -53
  98. data/test/sass/css2sass_test.rb +50 -1
  99. data/test/sass/css_variable_test.rb +132 -0
  100. data/test/sass/engine_test.rb +207 -61
  101. data/test/sass/exec_test.rb +10 -0
  102. data/test/sass/extend_test.rb +101 -29
  103. data/test/sass/functions_test.rb +60 -9
  104. data/test/sass/importer_test.rb +9 -0
  105. data/test/sass/more_templates/more1.sass +10 -10
  106. data/test/sass/more_templates/more_import.sass +2 -2
  107. data/test/sass/plugin_test.rb +10 -8
  108. data/test/sass/results/script.css +3 -3
  109. data/test/sass/script_conversion_test.rb +58 -29
  110. data/test/sass/script_test.rb +430 -53
  111. data/test/sass/scss/css_test.rb +73 -7
  112. data/test/sass/scss/rx_test.rb +4 -0
  113. data/test/sass/scss/scss_test.rb +309 -4
  114. data/test/sass/source_map_test.rb +152 -74
  115. data/test/sass/superselector_test.rb +19 -0
  116. data/test/sass/templates/_partial.sass +1 -1
  117. data/test/sass/templates/basic.sass +10 -10
  118. data/test/sass/templates/bork1.sass +1 -1
  119. data/test/sass/templates/bork5.sass +1 -1
  120. data/test/sass/templates/compact.sass +10 -10
  121. data/test/sass/templates/complex.sass +187 -187
  122. data/test/sass/templates/compressed.sass +10 -10
  123. data/test/sass/templates/expanded.sass +10 -10
  124. data/test/sass/templates/import.sass +2 -2
  125. data/test/sass/templates/importee.sass +3 -3
  126. data/test/sass/templates/mixins.sass +22 -22
  127. data/test/sass/templates/multiline.sass +4 -4
  128. data/test/sass/templates/nested.sass +13 -13
  129. data/test/sass/templates/parent_ref.sass +12 -12
  130. data/test/sass/templates/script.sass +70 -70
  131. data/test/sass/templates/subdir/nested_subdir/_nested_partial.sass +1 -1
  132. data/test/sass/templates/subdir/nested_subdir/nested_subdir.sass +2 -2
  133. data/test/sass/templates/subdir/subdir.sass +3 -3
  134. data/test/sass/templates/units.sass +10 -10
  135. data/test/sass/util/multibyte_string_scanner_test.rb +10 -2
  136. data/test/sass/util_test.rb +15 -44
  137. data/test/sass-spec.yml +3 -0
  138. data/test/test_helper.rb +5 -4
  139. metadata +302 -295
  140. data/CONTRIBUTING +0 -3
  141. data/lib/sass/scss/script_lexer.rb +0 -15
  142. data/lib/sass/scss/script_parser.rb +0 -25
@@ -167,42 +167,52 @@ SCSS
167
167
  end
168
168
 
169
169
  def test_universal_unification_with_namespaceless_universal_target
170
+ assert_extend_doesnt_match('ns|*', '.foo', :failed_to_unify, 2) do
171
+ render_unification '*.foo', 'ns|* {@extend .foo}'
172
+ end
173
+
170
174
  assert_unification '*.foo', '* {@extend .foo}', '*'
171
175
  assert_unification '*.foo', '*|* {@extend .foo}', '*'
172
176
  assert_unification '*|*.foo', '* {@extend .foo}', '*|*.foo, *'
173
177
  assert_unification '*|*.foo', '*|* {@extend .foo}', '*|*'
174
- assert_unification '*.foo', 'ns|* {@extend .foo}', '*.foo, ns|*'
175
178
  assert_unification '*|*.foo', 'ns|* {@extend .foo}', '*|*.foo, ns|*'
176
179
  end
177
180
 
178
181
  def test_universal_unification_with_namespaced_universal_target
179
- assert_unification 'ns|*.foo', '* {@extend .foo}', 'ns|*'
180
- assert_unification 'ns|*.foo', '*|* {@extend .foo}', 'ns|*'
182
+ assert_extend_doesnt_match('*', '.foo', :failed_to_unify, 2) do
183
+ render_unification 'ns|*.foo', '* {@extend .foo}'
184
+ end
181
185
 
182
186
  assert_extend_doesnt_match('ns2|*', '.foo', :failed_to_unify, 2) do
183
187
  render_unification 'ns1|*.foo', 'ns2|* {@extend .foo}'
184
188
  end
185
189
 
190
+ assert_unification 'ns|*.foo', '*|* {@extend .foo}', 'ns|*'
186
191
  assert_unification 'ns|*.foo', 'ns|* {@extend .foo}', 'ns|*'
187
192
  end
188
193
 
189
194
  def test_universal_unification_with_namespaceless_element_target
195
+ assert_extend_doesnt_match('ns|*', '.foo', :failed_to_unify, 2) do
196
+ render_unification 'a.foo', 'ns|* {@extend .foo}'
197
+ end
198
+
190
199
  assert_unification 'a.foo', '* {@extend .foo}', 'a'
191
200
  assert_unification 'a.foo', '*|* {@extend .foo}', 'a'
192
201
  assert_unification '*|a.foo', '* {@extend .foo}', '*|a.foo, a'
193
202
  assert_unification '*|a.foo', '*|* {@extend .foo}', '*|a'
194
- assert_unification 'a.foo', 'ns|* {@extend .foo}', 'a.foo, ns|a'
195
203
  assert_unification '*|a.foo', 'ns|* {@extend .foo}', '*|a.foo, ns|a'
196
204
  end
197
205
 
198
206
  def test_universal_unification_with_namespaced_element_target
199
- assert_unification 'ns|a.foo', '* {@extend .foo}', 'ns|a'
200
- assert_unification 'ns|a.foo', '*|* {@extend .foo}', 'ns|a'
207
+ assert_extend_doesnt_match('*', '.foo', :failed_to_unify, 2) do
208
+ render_unification 'ns|a.foo', '* {@extend .foo}'
209
+ end
201
210
 
202
211
  assert_extend_doesnt_match('ns2|*', '.foo', :failed_to_unify, 2) do
203
212
  render_unification 'ns1|a.foo', 'ns2|* {@extend .foo}'
204
213
  end
205
214
 
215
+ assert_unification 'ns|a.foo', '*|* {@extend .foo}', 'ns|a'
206
216
  assert_unification 'ns|a.foo', 'ns|* {@extend .foo}', 'ns|a'
207
217
  end
208
218
 
@@ -214,46 +224,56 @@ SCSS
214
224
  end
215
225
 
216
226
  def test_element_unification_with_namespaceless_universal_target
227
+ assert_extend_doesnt_match('ns|a', '.foo', :failed_to_unify, 2) do
228
+ render_unification '*.foo', 'ns|a {@extend .foo}'
229
+ end
230
+
217
231
  assert_unification '*.foo', 'a {@extend .foo}', '*.foo, a'
218
232
  assert_unification '*.foo', '*|a {@extend .foo}', '*.foo, a'
219
233
  assert_unification '*|*.foo', 'a {@extend .foo}', '*|*.foo, a'
220
234
  assert_unification '*|*.foo', '*|a {@extend .foo}', '*|*.foo, *|a'
221
- assert_unification '*.foo', 'ns|a {@extend .foo}', '*.foo, ns|a'
222
235
  assert_unification '*|*.foo', 'ns|a {@extend .foo}', '*|*.foo, ns|a'
223
236
  end
224
237
 
225
238
  def test_element_unification_with_namespaced_universal_target
226
- assert_unification 'ns|*.foo', 'a {@extend .foo}', 'ns|*.foo, ns|a'
227
- assert_unification 'ns|*.foo', '*|a {@extend .foo}', 'ns|*.foo, ns|a'
239
+ assert_extend_doesnt_match('a', '.foo', :failed_to_unify, 2) do
240
+ render_unification 'ns|*.foo', 'a {@extend .foo}'
241
+ end
228
242
 
229
243
  assert_extend_doesnt_match('ns2|a', '.foo', :failed_to_unify, 2) do
230
244
  render_unification 'ns1|*.foo', 'ns2|a {@extend .foo}'
231
245
  end
232
246
 
247
+ assert_unification 'ns|*.foo', '*|a {@extend .foo}', 'ns|*.foo, ns|a'
233
248
  assert_unification 'ns|*.foo', 'ns|a {@extend .foo}', 'ns|*.foo, ns|a'
234
249
  end
235
250
 
236
251
  def test_element_unification_with_namespaceless_element_target
252
+ assert_extend_doesnt_match('ns|a', '.foo', :failed_to_unify, 2) do
253
+ render_unification 'a.foo', 'ns|a {@extend .foo}'
254
+ end
255
+
256
+ assert_extend_doesnt_match('h1', '.foo', :failed_to_unify, 2) do
257
+ render_unification 'a.foo', 'h1 {@extend .foo}'
258
+ end
259
+
237
260
  assert_unification 'a.foo', 'a {@extend .foo}', 'a'
238
261
  assert_unification 'a.foo', '*|a {@extend .foo}', 'a'
239
262
  assert_unification '*|a.foo', 'a {@extend .foo}', '*|a.foo, a'
240
263
  assert_unification '*|a.foo', '*|a {@extend .foo}', '*|a'
241
- assert_unification 'a.foo', 'ns|a {@extend .foo}', 'a.foo, ns|a'
242
264
  assert_unification '*|a.foo', 'ns|a {@extend .foo}', '*|a.foo, ns|a'
243
-
244
- assert_extend_doesnt_match('h1', '.foo', :failed_to_unify, 2) do
245
- render_unification 'a.foo', 'h1 {@extend .foo}'
246
- end
247
265
  end
248
266
 
249
267
  def test_element_unification_with_namespaced_element_target
250
- assert_unification 'ns|a.foo', 'a {@extend .foo}', 'ns|a'
251
- assert_unification 'ns|a.foo', '*|a {@extend .foo}', 'ns|a'
268
+ assert_extend_doesnt_match('a', '.foo', :failed_to_unify, 2) do
269
+ render_unification 'ns|a.foo', 'a {@extend .foo}'
270
+ end
252
271
 
253
272
  assert_extend_doesnt_match('ns2|a', '.foo', :failed_to_unify, 2) do
254
273
  render_unification 'ns1|a.foo', 'ns2|a {@extend .foo}'
255
274
  end
256
275
 
276
+ assert_unification 'ns|a.foo', '*|a {@extend .foo}', 'ns|a'
257
277
  assert_unification 'ns|a.foo', 'ns|a {@extend .foo}', 'ns|a'
258
278
  end
259
279
 
@@ -333,8 +353,8 @@ SCSS
333
353
  end
334
354
 
335
355
  def test_extend_into_not
336
- assert_extends(':not(.foo)', '.x {@extend .foo}', ':not(.foo, .x)')
337
- assert_extends(':not(.foo.bar)', '.x {@extend .bar}', ':not(.foo.bar, .foo.x)')
356
+ assert_extends(':not(.foo)', '.x {@extend .foo}', ':not(.foo):not(.x)')
357
+ assert_extends(':not(.foo.bar)', '.x {@extend .bar}', ':not(.foo.bar):not(.foo.x)')
338
358
  assert_extends(
339
359
  ':not(.foo.bar, .baz.bar)',
340
360
  '.x {@extend .bar}',
@@ -362,7 +382,21 @@ SCSS
362
382
  end
363
383
 
364
384
  def test_complex_extend_into_pseudoclass
365
- assert_extends(':not(.bar)', '.x .y {@extend .bar}', ':not(.bar, .x .y)')
385
+ # Unlike other selectors, we don't allow complex selectors to be
386
+ # added to `:not` if they weren't there before. At time of
387
+ # writing, most browsers don't support that and will throw away
388
+ # the entire selector if it exists.
389
+ #assert_extends(':not(.bar)', '.x .y {@extend .bar}', ':not(.bar)')
390
+
391
+ # If the `:not()` already has a complex selector, we won't break
392
+ # anything by adding a new one.
393
+ assert_extends(':not(.baz .bar)', '.x .y {@extend .bar}',
394
+ ':not(.baz .bar):not(.baz .x .y):not(.x .baz .y)')
395
+
396
+ # If the `:not()` would only contain complex selectors, there's no
397
+ # harm in letting it continue to exist.
398
+ assert_extends(':not(%bar)', '.x .y {@extend %bar}', ':not(.x .y)')
399
+
366
400
  assert_extends(':matches(.bar)', '.x .y {@extend .bar}', ':matches(.bar, .x .y)')
367
401
  assert_extends(':current(.bar)', '.x .y {@extend .bar}', ':current(.bar, .x .y)')
368
402
  assert_extends(':has(.bar)', '.x .y {@extend .bar}', ':has(.bar, .x .y)')
@@ -458,7 +492,7 @@ SCSS
458
492
 
459
493
  def test_extend_into_not_and_normal_extend
460
494
  assert_equal <<CSS, render(<<SCSS)
461
- .x:not(.y, .bar), .foo:not(.y, .bar) {
495
+ .x:not(.y):not(.bar), .foo:not(.y):not(.bar) {
462
496
  a: b; }
463
497
  CSS
464
498
  .x:not(.y) {a: b}
@@ -489,6 +523,16 @@ CSS
489
523
  SCSS
490
524
  end
491
525
 
526
+ def test_root_only_allowed_at_root
527
+ assert_extends(':root .foo', '.bar .baz {@extend .foo}',
528
+ ':root .foo, :root .bar .baz')
529
+ assert_extends('.foo:root .bar', '.baz:root .bang {@extend .bar}',
530
+ '.foo:root .bar, .baz.foo:root .bang')
531
+ assert_extends('html:root .bar', 'xml:root .bang {@extend .bar}', 'html:root .bar')
532
+ assert_extends('.foo:root > .bar .x', '.baz:root .bang .y {@extend .x}',
533
+ '.foo:root > .bar .x, .baz.foo:root > .bar .bang .y')
534
+ end
535
+
492
536
  def test_comma_extendee
493
537
  assert_equal <<CSS, render(<<SCSS)
494
538
  .foo, .baz {
@@ -514,24 +558,42 @@ CSS
514
558
  SCSS
515
559
  end
516
560
 
561
+ def test_nested_pseudo_selectors
562
+ assert_equal <<CSS, render(<<SCSS)
563
+ .foo .bar:not(.baz), .bang .bar:not(.baz) {
564
+ a: b; }
565
+ CSS
566
+ .foo {
567
+ .bar:not(.baz) {a: b}
568
+ }
569
+ .bang {@extend .foo}
570
+ SCSS
571
+ end
572
+
517
573
  ## Long Extendees
518
574
 
519
575
  def test_long_extendee
520
- assert_extends '.foo.bar', '.baz {@extend .foo.bar}', '.foo.bar, .baz'
576
+ assert_warning(<<WARNING) {assert_extends '.foo.bar', '.baz {@extend .foo.bar}', '.foo.bar, .baz'}
577
+ DEPRECATION WARNING on line 2 of test_long_extendee_inline.scss:
578
+ Extending a compound selector, .foo.bar, is deprecated and will not be supported in a future release.
579
+ See https://github.com/sass/sass/issues/1599 for details.
580
+ WARNING
521
581
  end
522
582
 
523
583
  def test_long_extendee_requires_all_selectors
524
- assert_extend_doesnt_match('.baz', '.foo.bar', :not_found, 2) do
525
- render_extends '.foo', '.baz {@extend .foo.bar}'
584
+ silence_warnings do
585
+ assert_extend_doesnt_match('.baz', '.foo.bar', :not_found, 2) do
586
+ render_extends '.foo', '.baz {@extend .foo.bar}'
587
+ end
526
588
  end
527
589
  end
528
590
 
529
591
  def test_long_extendee_matches_supersets
530
- assert_extends '.foo.bar.bap', '.baz {@extend .foo.bar}', '.foo.bar.bap, .bap.baz'
592
+ silence_warnings {assert_extends '.foo.bar.bap', '.baz {@extend .foo.bar}', '.foo.bar.bap, .bap.baz'}
531
593
  end
532
594
 
533
595
  def test_long_extendee_runs_unification
534
- assert_extends 'ns|*.foo.bar', 'a.baz {@extend .foo.bar}', 'ns|*.foo.bar, ns|a.baz'
596
+ silence_warnings {assert_extends 'ns|*.foo.bar', '*|a.baz {@extend .foo.bar}', 'ns|*.foo.bar, ns|a.baz'}
535
597
  end
536
598
 
537
599
  ## Long Extenders
@@ -541,7 +603,7 @@ SCSS
541
603
  end
542
604
 
543
605
  def test_long_extender_runs_unification
544
- assert_extends 'ns|*.foo.bar', 'a.baz {@extend .foo}', 'ns|*.foo.bar, ns|a.bar.baz'
606
+ assert_extends 'ns|*.foo.bar', '*|a.baz {@extend .foo}', 'ns|*.foo.bar, ns|a.bar.baz'
545
607
  end
546
608
 
547
609
  def test_long_extender_aborts_unification
@@ -627,9 +689,9 @@ SCSS
627
689
  end
628
690
 
629
691
  def test_nested_extender_doesnt_find_common_selectors_around_reference_selector
630
- assert_extends 'a /for/ b c .c1', 'a c .c2 {@extend .c1}', 'a /for/ b c .c1, a /for/ b a c .c2, a a /for/ b c .c2'
631
- assert_extends 'a /for/ b c .c1', 'a b .c2 {@extend .c1}', 'a /for/ b c .c1, a a /for/ b c .c2'
632
- assert_extends 'a /for/ b c .c1', 'b c .c2 {@extend .c1}', 'a /for/ b c .c1, a /for/ b c .c2'
692
+ silence_warnings {assert_extends 'a /for/ b c .c1', 'a c .c2 {@extend .c1}', 'a /for/ b c .c1, a /for/ b a c .c2, a a /for/ b c .c2'}
693
+ silence_warnings {assert_extends 'a /for/ b c .c1', 'a b .c2 {@extend .c1}', 'a /for/ b c .c1, a a /for/ b c .c2'}
694
+ silence_warnings {assert_extends 'a /for/ b c .c1', 'b c .c2 {@extend .c1}', 'a /for/ b c .c1, a /for/ b c .c2'}
633
695
  end
634
696
 
635
697
  def test_nested_extender_with_early_child_selectors_doesnt_subseq_them
@@ -1312,6 +1374,16 @@ SCSS
1312
1374
 
1313
1375
  # Regression Tests
1314
1376
 
1377
+ def test_extend_with_middle_pseudo
1378
+ assert_equal(<<CSS, render(<<SCSS))
1379
+ .btn:active.focus, :active.focus:before {
1380
+ a: b; }
1381
+ CSS
1382
+ .btn:active.focus {a: b}
1383
+ :before {@extend .btn}
1384
+ SCSS
1385
+ end
1386
+
1315
1387
  def test_extend_parent_selector_suffix
1316
1388
  assert_equal <<CSS, render(<<SCSS)
1317
1389
  .a-b, .c {
@@ -122,6 +122,20 @@ class SassFunctionTest < MiniTest::Test
122
122
  assert_error_message("$alpha: \"foo\" is not a number for `hsla'", "hsla(10, 10, 10, \"foo\")");
123
123
  end
124
124
 
125
+ def test_hsla_percent_warning
126
+ assert_warning(<<WARNING) {evaluate("hsla(180, 60%, 50%, 40%)")}
127
+ DEPRECATION WARNING: Passing a percentage as the alpha value to hsla() will be
128
+ interpreted differently in future versions of Sass. For now, use 40 instead.
129
+ WARNING
130
+ end
131
+
132
+ def test_hsla_unit_warning
133
+ assert_warning(<<WARNING) {evaluate("hsla(180, 60%, 50%, 40em)")}
134
+ DEPRECATION WARNING: Passing a number with units as the alpha value to hsla() is
135
+ deprecated and will be an error in future versions of Sass. Use 40 instead.
136
+ WARNING
137
+ end
138
+
125
139
  def test_percentage
126
140
  assert_equal("50%", evaluate("percentage(.5)"))
127
141
  assert_equal("100%", evaluate("percentage(1)"))
@@ -140,6 +154,7 @@ class SassFunctionTest < MiniTest::Test
140
154
  assert_equal("5px", evaluate("round(4.8px)"))
141
155
  assert_equal("5px", evaluate("round(5.49px)"))
142
156
  assert_equal("5px", evaluate("round($number: 5.49px)"))
157
+ assert_equal("-6", evaluate("round(-5.5)"))
143
158
  end
144
159
 
145
160
  def test_round_checks_types
@@ -183,6 +198,7 @@ class SassFunctionTest < MiniTest::Test
183
198
  assert_equal("1", evaluate("min(3px, 2px, 1)"))
184
199
  assert_equal("4em", evaluate("min(4em)"))
185
200
  assert_equal("10cm", evaluate("min(10cm, 6in)"))
201
+ assert_equal("1q", evaluate("min(1cm, 1q)"))
186
202
 
187
203
  assert_error_message("#aaaaaa is not a number for `min'", "min(#aaa)")
188
204
  assert_error_message("Incompatible units: 'px' and 'em'.", "min(3em, 4em, 1px)")
@@ -193,6 +209,7 @@ class SassFunctionTest < MiniTest::Test
193
209
  assert_equal("3", evaluate("max(3, 2px, 1px)"))
194
210
  assert_equal("4em", evaluate("max(4em)"))
195
211
  assert_equal("6in", evaluate("max(10cm, 6in)"))
212
+ assert_equal("11mm", evaluate("max(11mm, 10q)"))
196
213
 
197
214
  assert_error_message("#aaaaaa is not a number for `max'", "max(#aaa)")
198
215
  assert_error_message("Incompatible units: 'px' and 'em'.", "max(3em, 4em, 1px)")
@@ -206,10 +223,10 @@ class SassFunctionTest < MiniTest::Test
206
223
  end
207
224
 
208
225
  def test_rgb_percent
209
- assert_equal("#123456", evaluate("rgb(7.1%, 20.4%, 34%)"))
226
+ assert_equal("#123457", evaluate("rgb(7.1%, 20.4%, 34%)"))
210
227
  assert_equal("#beaded", evaluate("rgb(74.7%, 173, 93%)"))
211
228
  assert_equal("#beaded", evaluate("rgb(190, 68%, 237)"))
212
- assert_equal("springgreen", evaluate("rgb(0%, 100%, 50%)"))
229
+ assert_equal("#00ff80", evaluate("rgb(0%, 100%, 50%)"))
213
230
  end
214
231
 
215
232
  def test_rgb_clamps_bounds
@@ -274,6 +291,20 @@ class SassFunctionTest < MiniTest::Test
274
291
  assert_error_message("wrong number of arguments (5 for 4) for `rgba'", "rgba(1, 2, 3, 0.4, 5)");
275
292
  end
276
293
 
294
+ def test_rgba_percent_warning
295
+ assert_warning(<<WARNING) {evaluate("rgba(1, 2, 3, 40%)")}
296
+ DEPRECATION WARNING: Passing a percentage as the alpha value to rgba() will be
297
+ interpreted differently in future versions of Sass. For now, use 40 instead.
298
+ WARNING
299
+ end
300
+
301
+ def test_rgba_unit_warning
302
+ assert_warning(<<WARNING) {evaluate("rgba(1, 2, 3, 40em)")}
303
+ DEPRECATION WARNING: Passing a number with units as the alpha value to rgba() is
304
+ deprecated and will be an error in future versions of Sass. Use 40 instead.
305
+ WARNING
306
+ end
307
+
277
308
  def test_red
278
309
  assert_equal("18", evaluate("red(#123456)"))
279
310
  assert_equal("18", evaluate("red($color: #123456)"))
@@ -785,11 +816,11 @@ class SassFunctionTest < MiniTest::Test
785
816
  end
786
817
 
787
818
  def test_mix
788
- assert_equal("#7f007f", evaluate("mix(#f00, #00f)"))
789
- assert_equal("#7f7f7f", evaluate("mix(#f00, #0ff)"))
790
- assert_equal("#7f9055", evaluate("mix(#f70, #0aa)"))
791
- assert_equal("#3f00bf", evaluate("mix(#f00, #00f, 25%)"))
792
- assert_equal("rgba(63, 0, 191, 0.75)", evaluate("mix(rgba(255, 0, 0, 0.5), #00f)"))
819
+ assert_equal("purple", evaluate("mix(#f00, #00f)"))
820
+ assert_equal("gray", evaluate("mix(#f00, #0ff)"))
821
+ assert_equal("#809155", evaluate("mix(#f70, #0aa)"))
822
+ assert_equal("#4000bf", evaluate("mix(#f00, #00f, 25%)"))
823
+ assert_equal("rgba(64, 0, 191, 0.75)", evaluate("mix(rgba(255, 0, 0, 0.5), #00f)"))
793
824
  assert_equal("red", evaluate("mix(#f00, #00f, 100%)"))
794
825
  assert_equal("blue", evaluate("mix(#f00, #00f, 0%)"))
795
826
  assert_equal("rgba(255, 0, 0, 0.5)", evaluate("mix(#f00, transparentize(#00f, 1))"))
@@ -857,6 +888,12 @@ class SassFunctionTest < MiniTest::Test
857
888
  assert_equal('foo', evaluate('unquote("foo")'))
858
889
  assert_equal('foo', evaluate('unquote(foo)'))
859
890
  assert_equal('foo', evaluate('unquote($string: foo)'))
891
+ assert_warning <<MESSAGE do
892
+ DEPRECATION WARNING: Passing blue, a non-string value, to unquote()
893
+ will be an error in future versions of Sass.
894
+ MESSAGE
895
+ assert_equal('blue', evaluate('unquote(blue)'))
896
+ end
860
897
  end
861
898
 
862
899
  def test_quote
@@ -1593,6 +1630,9 @@ SCSS
1593
1630
  assert_equal "null", evaluate("inspect(null)")
1594
1631
  assert_equal "1px null 3px", evaluate("inspect(1px null 3px)")
1595
1632
  assert_equal "(a: 1, b: 2)", evaluate("inspect((a: 1, b: 2))")
1633
+ assert_equal "(a: 1, b: (c: 2))", evaluate("inspect((a: 1, b: (c: 2)))")
1634
+ assert_equal "(a: 1, b: (2, 3))", evaluate("inspect((a: 1, b: (2, 3)))")
1635
+ assert_equal "(a: 1, b: 2 3)", evaluate("inspect((a: 1, b: 2 3))")
1596
1636
  end
1597
1637
 
1598
1638
  def test_random
@@ -1627,6 +1667,14 @@ SCSS
1627
1667
  assert_error_message("Expected $limit to be an integer but got 1.5 for `random'", "random(1.5)")
1628
1668
  end
1629
1669
 
1670
+ # Regression test for #1638.
1671
+ def test_random_with_float_integer_limit
1672
+ result = perform("random(1.0)")
1673
+ assert_kind_of Sass::Script::Number, result
1674
+ assert result.value >= 0, "Random number was below 0"
1675
+ assert result.value <= 1, "Random number was above 1"
1676
+ end
1677
+
1630
1678
  # This could *possibly* fail, but exceedingly unlikely
1631
1679
  def test_random_is_semi_unique
1632
1680
  if Sass::Script::Functions.instance_variable_defined?("@random_number_generator")
@@ -1793,8 +1841,11 @@ WARNING
1793
1841
  assert_equal(".bar", evaluate("selector-replace('.foo', '.foo', '.bar')"))
1794
1842
  assert_equal(".foo.baz", evaluate("selector-replace('.foo.bar', '.bar', '.baz')"))
1795
1843
  assert_equal(".a .foo.baz", evaluate("selector-replace('.foo.bar', '.bar', '.a .baz')"))
1796
- assert_equal(".foo.bar", evaluate("selector-replace('.foo.bar', '.baz.bar', '.qux')"))
1797
- assert_equal(".bar.qux", evaluate("selector-replace('.foo.bar.baz', '.foo.baz', '.qux')"))
1844
+
1845
+ # These shouldn't warn since we still support componud targets for selector
1846
+ # functions.
1847
+ assert_no_warning {assert_equal(".foo.bar", evaluate("selector-replace('.foo.bar', '.baz.bar', '.qux')"))}
1848
+ assert_no_warning {assert_equal(".bar.qux", evaluate("selector-replace('.foo.bar.baz', '.foo.baz', '.qux')"))}
1798
1849
 
1799
1850
  assert_equal(":not(.bar)", evaluate("selector-replace(':not(.foo)', '.foo', '.bar')"))
1800
1851
  assert_equal(".bar", evaluate("selector-replace(':not(.foo)', ':not(.foo)', '.bar')"))
@@ -405,6 +405,15 @@ MESSAGE
405
405
  File.join(fixture_dir, path)
406
406
  end
407
407
 
408
+ def test_filesystem_importer_eql
409
+ importer = Sass::Importers::Filesystem.new('.')
410
+ assert importer.eql?(Sass::Importers::Filesystem.new('.'))
411
+ assert importer.eql?(ReversedExtImporter.new('.'))
412
+ assert !importer.eql?(Sass::Importers::Filesystem.new('foo'))
413
+ assert !importer.eql?(nil)
414
+ assert !importer.eql?('foo')
415
+ end
416
+
408
417
  def test_absolute_files_across_template_locations
409
418
  importer = Sass::Importers::Filesystem.new(absolutize 'templates')
410
419
  refute_nil importer.mtime(absolutize('more_templates/more1.sass'), {})
@@ -1,23 +1,23 @@
1
1
 
2
2
 
3
3
  body
4
- :font Arial
5
- :background blue
4
+ font: Arial
5
+ background: blue
6
6
 
7
7
  #page
8
- :width 700px
9
- :height 100
8
+ width: 700px
9
+ height: 100
10
10
  #header
11
- :height 300px
11
+ height: 300px
12
12
  h1
13
- :font-size 50px
14
- :color blue
13
+ font-size: 50px
14
+ color: blue
15
15
 
16
16
  #content.user.show
17
17
  #container.top
18
18
  #column.left
19
- :width 100px
19
+ width: 100px
20
20
  #column.right
21
- :width 600px
21
+ width: 600px
22
22
  #container.bottom
23
- :background brown
23
+ background: brown
@@ -6,6 +6,6 @@ $preconst: hello
6
6
  @import importee, basic, basic.css, ../results/complex.css, more_partial
7
7
 
8
8
  nonimported
9
- :myconst $preconst
10
- :otherconst $postconst
9
+ myconst: $preconst
10
+ otherconst: $postconst
11
11
  +postmixin
@@ -29,8 +29,8 @@ class SassPluginTest < MiniTest::Test
29
29
  @@cache_store = Sass::CacheStores::Memory.new
30
30
 
31
31
  def setup
32
- FileUtils.mkdir_p tempfile_loc
33
- FileUtils.mkdir_p tempfile_loc(nil,"more_")
32
+ Sass::Util.retry_on_windows {FileUtils.mkdir_p tempfile_loc}
33
+ Sass::Util.retry_on_windows {FileUtils.mkdir_p tempfile_loc(nil,"more_")}
34
34
  set_plugin_opts
35
35
  check_for_updates!
36
36
  reset_mtimes
@@ -39,13 +39,13 @@ class SassPluginTest < MiniTest::Test
39
39
  def teardown
40
40
  clean_up_sassc
41
41
  Sass::Plugin.reset!
42
- FileUtils.rm_r tempfile_loc
43
- FileUtils.rm_r tempfile_loc(nil,"more_")
42
+ Sass::Util.retry_on_windows {FileUtils.rm_r tempfile_loc}
43
+ Sass::Util.retry_on_windows {FileUtils.rm_r tempfile_loc(nil,"more_")}
44
44
  end
45
45
 
46
46
  @@templates.each do |name|
47
47
  define_method("test_template_renders_correctly (#{name})") do
48
- assert_renders_correctly(name)
48
+ silence_warnings {assert_renders_correctly(name)}
49
49
  end
50
50
  end
51
51
 
@@ -117,7 +117,7 @@ Error: Undefined variable: "$bork".
117
117
  on line 2 of #{template_loc('bork1')}
118
118
 
119
119
  1: bork
120
- 2: :bork $bork
120
+ 2: bork: $bork
121
121
  CSS
122
122
  end
123
123
  File.delete(tempfile_loc('bork1'))
@@ -134,7 +134,7 @@ Error: Undefined variable: "$bork".
134
134
 
135
135
  1: bork
136
136
  2: /* foo *\\/
137
- 3: :bork $bork
137
+ 3: bork: $bork
138
138
  CSS
139
139
  end
140
140
  File.delete(tempfile_loc('bork1'))
@@ -501,7 +501,9 @@ WARNING
501
501
  Sass::Plugin::StalenessChecker.dependencies_cache = {}
502
502
  atime = Time.now
503
503
  mtime = Time.now - 5
504
- Dir["{#{template_loc},#{tempfile_loc}}/**/*.{css,sass,scss}"].each {|f| File.utime(atime, mtime, f)}
504
+ Dir["{#{template_loc},#{tempfile_loc}}/**/*.{css,sass,scss}"].each do |f|
505
+ Sass::Util.retry_on_windows {File.utime(atime, mtime, f)}
506
+ end
505
507
  end
506
508
 
507
509
  def template_loc(name = nil, prefix = nil)
@@ -1,13 +1,13 @@
1
1
  #main { content: Hello\!; qstr: 'Quo"ted"!'; hstr: Hyph-en\!; width: 30em; background-color: #000; color: #ffa; short-color: #123; named-color: olive; con: "foo" bar 9 hi there "boom"; con2: "noquo" quo; }
2
2
  #main #sidebar { background-color: #00ff98; num-normal: 10; num-dec: 10.2; num-dec0: 99; num-neg: -10; esc: 10\+12; many: 6; order: 7; complex: #4c9db1hi16; }
3
3
 
4
- #plus { num-num: 7; num-num-un: 25em; num-num-un2: 23em; num-num-neg: 9.87; num-str: 100px; num-col: #b7b7b7; num-perc: 31%; str-str: "hi there"; str-str2: "hi there"; str-col: "14em solid #123"; str-num: "times: 13"; col-num: #ff7b9d; col-col: #5173ff; }
4
+ #plus { num-num: 7; num-num-un: 25em; num-num-un2: 23em; num-num-neg: 9.87; num-str: 100px; num-col: #b7b7b7; num-perc: 31%; str-str: "hi there"; str-str2: "hi there"; str-col: "14em solid #123"; str-num: "times: 13"; col-num: #ff7c9e; col-col: #5173ff; }
5
5
 
6
- #minus { num-num: 900; col-num: #f9f9f4; col-col: #000035; unary-num: -1; unary-const: 10; unary-paren: -11; unary-two: 12; unary-many: 12; unary-crazy: -15; }
6
+ #minus { num-num: 900; col-num: #fafaf5; col-col: #000035; unary-num: -1; unary-const: 10; unary-paren: -11; unary-two: 12; unary-many: 12; unary-crazy: -15; }
7
7
 
8
8
  #times { num-num: 7; num-col: #7496b8; col-num: #092345; col-col: #243648; }
9
9
 
10
- #div { num-num: 3.33333; num-num2: 3.33333; col-num: #092345; col-col: #0b0d0f; comp: 1px; }
10
+ #div { num-num: 3.33333; num-num2: 3.33333; col-num: #092345; col-col: #0b0e10; comp: 1px; }
11
11
 
12
12
  #mod { num-num: 2; col-col: #0f0e05; col-num: #020001; }
13
13