sass 3.3.0.rc.2 → 3.3.0.rc.3

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 (76) hide show
  1. checksums.yaml +15 -0
  2. data/CONTRIBUTING +1 -1
  3. data/README.md +7 -7
  4. data/Rakefile +4 -2
  5. data/VERSION +1 -1
  6. data/VERSION_DATE +1 -1
  7. data/bin/sass +5 -1
  8. data/bin/sass-convert +5 -1
  9. data/bin/scss +5 -1
  10. data/ext/mkrf_conf.rb +23 -0
  11. data/lib/sass/css.rb +1 -1
  12. data/lib/sass/engine.rb +19 -9
  13. data/lib/sass/environment.rb +8 -0
  14. data/lib/sass/exec.rb +4 -4
  15. data/lib/sass/features.rb +0 -1
  16. data/lib/sass/importers/base.rb +13 -6
  17. data/lib/sass/importers/deprecated_path.rb +8 -2
  18. data/lib/sass/importers/filesystem.rb +33 -7
  19. data/lib/sass/logger.rb +1 -4
  20. data/lib/sass/logger/base.rb +0 -2
  21. data/lib/sass/logger/log_level.rb +0 -2
  22. data/lib/sass/plugin.rb +2 -2
  23. data/lib/sass/plugin/compiler.rb +23 -11
  24. data/lib/sass/plugin/configuration.rb +0 -1
  25. data/lib/sass/railtie.rb +1 -0
  26. data/lib/sass/script/css_lexer.rb +0 -1
  27. data/lib/sass/script/css_parser.rb +0 -1
  28. data/lib/sass/script/functions.rb +158 -96
  29. data/lib/sass/script/lexer.rb +29 -35
  30. data/lib/sass/script/parser.rb +10 -3
  31. data/lib/sass/script/tree.rb +0 -1
  32. data/lib/sass/script/tree/funcall.rb +21 -5
  33. data/lib/sass/script/tree/list_literal.rb +0 -1
  34. data/lib/sass/script/value/arg_list.rb +7 -3
  35. data/lib/sass/script/value/bool.rb +0 -1
  36. data/lib/sass/script/value/null.rb +0 -1
  37. data/lib/sass/script/value/number.rb +2 -6
  38. data/lib/sass/scss/css_parser.rb +0 -1
  39. data/lib/sass/scss/parser.rb +5 -5
  40. data/lib/sass/scss/script_lexer.rb +0 -1
  41. data/lib/sass/scss/script_parser.rb +0 -1
  42. data/lib/sass/selector.rb +11 -1
  43. data/lib/sass/selector/comma_sequence.rb +3 -4
  44. data/lib/sass/selector/sequence.rb +11 -7
  45. data/lib/sass/selector/simple_sequence.rb +42 -11
  46. data/lib/sass/source/map.rb +6 -19
  47. data/lib/sass/tree/at_root_node.rb +1 -1
  48. data/lib/sass/tree/mixin_node.rb +2 -2
  49. data/lib/sass/tree/prop_node.rb +0 -1
  50. data/lib/sass/tree/variable_node.rb +0 -5
  51. data/lib/sass/tree/visitors/check_nesting.rb +0 -1
  52. data/lib/sass/tree/visitors/convert.rb +2 -2
  53. data/lib/sass/tree/visitors/cssize.rb +184 -84
  54. data/lib/sass/tree/visitors/deep_copy.rb +0 -1
  55. data/lib/sass/tree/visitors/perform.rb +14 -44
  56. data/lib/sass/util.rb +59 -12
  57. data/lib/sass/util/cross_platform_random.rb +19 -0
  58. data/lib/sass/util/normalized_map.rb +17 -1
  59. data/test/sass/compiler_test.rb +10 -0
  60. data/test/sass/conversion_test.rb +36 -0
  61. data/test/sass/css2sass_test.rb +19 -0
  62. data/test/sass/engine_test.rb +54 -105
  63. data/test/sass/functions_test.rb +233 -26
  64. data/test/sass/importer_test.rb +72 -10
  65. data/test/sass/plugin_test.rb +14 -0
  66. data/test/sass/script_conversion_test.rb +4 -4
  67. data/test/sass/script_test.rb +58 -21
  68. data/test/sass/scss/css_test.rb +8 -1
  69. data/test/sass/scss/scss_test.rb +376 -179
  70. data/test/sass/source_map_test.rb +8 -0
  71. data/test/sass/templates/subdir/import_up1.scss +1 -0
  72. data/test/sass/templates/subdir/import_up2.scss +1 -0
  73. data/test/sass/util_test.rb +16 -0
  74. data/test/test_helper.rb +12 -4
  75. metadata +269 -287
  76. data/lib/sass/script/tree/selector.rb +0 -30
@@ -164,6 +164,20 @@ CSS
164
164
  end
165
165
  end
166
166
 
167
+ def test_import_name_cleanup
168
+ File.delete(tempfile_loc('subdir/import_up1'))
169
+ check_for_updates!
170
+ File.open(tempfile_loc('subdir/import_up1')) do |file|
171
+ assert_equal(<<CSS.strip, file.read.split("\n")[0...5].join("\n"))
172
+ /*
173
+ Syntax error: File to import not found or unreadable: ../subdir/import_up3.scss.
174
+ Load path: #{template_loc}
175
+ on line 1 of #{template_loc 'subdir/import_up2'}
176
+ from line 1 of #{template_loc 'subdir/import_up1'}
177
+ CSS
178
+ end
179
+ end
180
+
167
181
  def test_nonfull_exception_handling
168
182
  old_full_exception = Sass::Plugin.options[:full_exception]
169
183
  Sass::Plugin.options[:full_exception] = false
@@ -58,6 +58,10 @@ class SassScriptConversionTest < Test::Unit::TestCase
58
58
  assert_renders "foo($karg1: val, $karg2: val2)"
59
59
  end
60
60
 
61
+ def test_funcall_with_hyphen_conversion_keyword_arg
62
+ assert_renders "foo($a-b_c: val)"
63
+ end
64
+
61
65
  def test_url
62
66
  assert_renders "url(foo.gif)"
63
67
  assert_renders "url($var)"
@@ -105,10 +109,6 @@ class SassScriptConversionTest < Test::Unit::TestCase
105
109
  assert_renders "(foo: (bar, baz), bip: bop)"
106
110
  end
107
111
 
108
- def test_selector
109
- assert_renders "&"
110
- end
111
-
112
112
  def self.test_precedence(outer, inner)
113
113
  op_outer = Sass::Script::Lexer::OPERATORS_REVERSE[outer]
114
114
  op_inner = Sass::Script::Lexer::OPERATORS_REVERSE[inner]
@@ -401,6 +401,12 @@ SASS
401
401
  assert_equal "true", resolve('() != null')
402
402
  end
403
403
 
404
+ def test_mod
405
+ assert_equal "5", resolve("29 % 12")
406
+ assert_equal "5px", resolve("29px % 12")
407
+ assert_equal "5px", resolve("29px % 12px")
408
+ end
409
+
404
410
  def test_operation_precedence
405
411
  assert_equal "false true", resolve("true and false false or true")
406
412
  assert_equal "true", resolve("false and true or true and true")
@@ -564,27 +570,6 @@ SASS
564
570
  assert_equal "true", resolve("$ie or $undef", {}, env('ie' => Sass::Script::Value::Bool.new(true)))
565
571
  end
566
572
 
567
- def test_selector
568
- env = Sass::Environment.new
569
- assert_equal "true", resolve("& == null", {}, env)
570
-
571
- env.selector = selector('.foo.bar .baz.bang, .bip.bop')
572
- assert_equal ".foo.bar .baz.bang, .bip.bop", resolve("&", {}, env)
573
- assert_equal ".foo.bar .baz.bang", resolve("nth(&, 1)", {}, env)
574
- assert_equal ".bip.bop", resolve("nth(&, 2)", {}, env)
575
- assert_equal ".foo.bar", resolve("nth(nth(&, 1), 1)", {}, env)
576
- assert_equal ".baz.bang", resolve("nth(nth(&, 1), 2)", {}, env)
577
- assert_equal ".bip.bop", resolve("nth(nth(&, 2), 1)", {}, env)
578
- assert_equal "string", resolve("type-of(nth(nth(&, 1), 1))", {}, env)
579
-
580
- env.selector = selector('.foo > .bar')
581
- assert_equal ".foo > .bar", resolve("&", {}, env)
582
- assert_equal ".foo > .bar", resolve("nth(&, 1)", {}, env)
583
- assert_equal ".foo", resolve("nth(nth(&, 1), 1)", {}, env)
584
- assert_equal ">", resolve("nth(nth(&, 1), 2)", {}, env)
585
- assert_equal ".bar", resolve("nth(nth(&, 1), 3)", {}, env)
586
- end
587
-
588
573
  def test_setting_global_variable_locally_warns
589
574
  assert_warning(<<WARNING) {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
590
575
  DEPRECATION WARNING on line 4 of test_setting_global_variable_locally_warns_inline.scss:
@@ -611,6 +596,23 @@ $var: 1;
611
596
  SCSS
612
597
  end
613
598
 
599
+ def test_setting_global_variable_locally_warns_only_once
600
+ assert_warning(<<WARNING) {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
601
+ DEPRECATION WARNING on line 3 of test_setting_global_variable_locally_warns_only_once_inline.scss:
602
+ Assigning to global variable "$var" by default is deprecated.
603
+ In future versions of Sass, this will create a new local variable.
604
+ If you want to assign to the global variable, use "$var: x !global" instead.
605
+ WARNING
606
+ CSS
607
+ $var: 1;
608
+
609
+ @mixin foo {$var: x}
610
+ @include foo;
611
+ @include foo;
612
+ @include foo;
613
+ SCSS
614
+ end
615
+
614
616
  def test_setting_global_variable_globally
615
617
  assert_no_warning {assert_equal(<<CSS, render(<<SCSS, :syntax => :scss))}
616
618
  .foo {
@@ -686,6 +688,34 @@ SCSS
686
688
 
687
689
  # Regression Tests
688
690
 
691
+ def test_minus_without_whitespace
692
+ assert_equal "5px", resolve("15px-10px")
693
+ end
694
+
695
+ def test_user_defined_function_forces_division
696
+ assert_equal(<<CSS, render(<<SASS))
697
+ a {
698
+ b: 10px; }
699
+ CSS
700
+ @function foo()
701
+ @return 20px
702
+
703
+ a
704
+ b: (foo() / 2)
705
+ SASS
706
+
707
+ assert_equal(<<CSS, render(<<SASS))
708
+ a {
709
+ b: 10px; }
710
+ CSS
711
+ @function foo()
712
+ @return 20px
713
+
714
+ a
715
+ b: foo() / 2
716
+ SASS
717
+ end
718
+
689
719
  def test_funcall_has_higher_precedence_than_color_name
690
720
  assert_equal "teal(12)", resolve("teal(12)")
691
721
  assert_equal "tealbang(12)", resolve("tealbang(12)")
@@ -693,6 +723,13 @@ SCSS
693
723
  assert_equal "teal\\+bang(12)", resolve("teal\\+bang(12)")
694
724
  end
695
725
 
726
+ def test_funcall_has_higher_precedence_than_true_false_null
727
+ assert_equal "teal(12)", resolve("teal(12)")
728
+ assert_equal "tealbang(12)", resolve("tealbang(12)")
729
+ assert_equal "teal-bang(12)", resolve("teal-bang(12)")
730
+ assert_equal "teal\\+bang(12)", resolve("teal\\+bang(12)")
731
+ end
732
+
696
733
  def test_interpolation_after_hash
697
734
  assert_equal "#2", resolve('"##{1 + 1}"')
698
735
  end
@@ -505,13 +505,20 @@ SCSS
505
505
  assert_parses '@import url(foo.css);'
506
506
  end
507
507
 
508
- def test_import_directive_with_media
508
+ def test_string_import_directive_with_media
509
509
  assert_parses '@import "foo.css" screen;'
510
510
  assert_parses '@import "foo.css" screen, print;'
511
511
  assert_parses '@import "foo.css" screen, print and (foo: 0);'
512
512
  assert_parses '@import "foo.css" screen, only print, screen and (foo: 0);'
513
513
  end
514
514
 
515
+ def test_url_import_directive_with_media
516
+ assert_parses '@import url("foo.css") screen;'
517
+ assert_parses '@import url("foo.css") screen, print;'
518
+ assert_parses '@import url("foo.css") screen, print and (foo: 0);'
519
+ assert_parses '@import url("foo.css") screen, only print, screen and (foo: 0);'
520
+ end
521
+
515
522
  def test_page_directive
516
523
  assert_parses <<SCSS
517
524
  @page {
@@ -163,6 +163,51 @@ CSS
163
163
  SCSS
164
164
  end
165
165
 
166
+ def test_for_directive_with_same_start_and_end
167
+ assert_equal <<CSS, render(<<SCSS)
168
+ CSS
169
+ .foo {
170
+ @for $var from 1 to 1 {a: $var;}
171
+ }
172
+ SCSS
173
+
174
+ assert_equal <<CSS, render(<<SCSS)
175
+ .foo {
176
+ a: 1; }
177
+ CSS
178
+ .foo {
179
+ @for $var from 1 through 1 {a: $var;}
180
+ }
181
+ SCSS
182
+ end
183
+
184
+ def test_decrementing_estfor_directive
185
+ assert_equal <<CSS, render(<<SCSS)
186
+ .foo {
187
+ a: 5;
188
+ a: 4;
189
+ a: 3;
190
+ a: 2;
191
+ a: 1; }
192
+ CSS
193
+ .foo {
194
+ @for $var from 5 through 1 {a: $var;}
195
+ }
196
+ SCSS
197
+
198
+ assert_equal <<CSS, render(<<SCSS)
199
+ .foo {
200
+ a: 5;
201
+ a: 4;
202
+ a: 3;
203
+ a: 2; }
204
+ CSS
205
+ .foo {
206
+ @for $var from 5 to 1 {a: $var;}
207
+ }
208
+ SCSS
209
+ end
210
+
166
211
  def test_if_directive
167
212
  assert_equal <<CSS, render(<<SCSS)
168
213
  foo {
@@ -295,6 +340,20 @@ SCSS
295
340
  assert_equal "@import url(foo.css);\n", render('@import url(foo.css);')
296
341
  end
297
342
 
343
+ def test_css_string_import_directive_with_media
344
+ assert_parses '@import "foo.css" screen;'
345
+ assert_parses '@import "foo.css" screen, print;'
346
+ assert_parses '@import "foo.css" screen, print and (foo: 0);'
347
+ assert_parses '@import "foo.css" screen, only print, screen and (foo: 0);'
348
+ end
349
+
350
+ def test_css_url_import_directive_with_media
351
+ assert_parses '@import url("foo.css") screen;'
352
+ assert_parses '@import url("foo.css") screen, print;'
353
+ assert_parses '@import url("foo.css") screen, print and (foo: 0);'
354
+ assert_parses '@import url("foo.css") screen, only print, screen and (foo: 0);'
355
+ end
356
+
298
357
  def test_media_import
299
358
  assert_equal("@import \"./fonts.sass\" all;\n", render("@import \"./fonts.sass\" all;"))
300
359
  end
@@ -333,6 +392,44 @@ SCSS
333
392
  assert_equal("@import url(fonts.sass);\n", render("@import url(fonts.sass);"))
334
393
  end
335
394
 
395
+ def test_css_import_doesnt_move_through_comments
396
+ assert_equal <<CSS, render(<<SCSS)
397
+ /* Comment 1 */
398
+ @import url("foo.css");
399
+ /* Comment 2 */
400
+ @import url("bar.css");
401
+ CSS
402
+ /* Comment 1 */
403
+ @import url("foo.css");
404
+
405
+ /* Comment 2 */
406
+ @import url("bar.css");
407
+ SCSS
408
+ end
409
+
410
+ def test_css_import_movement_stops_at_comments
411
+ assert_equal <<CSS, render(<<SCSS)
412
+ /* Comment 1 */
413
+ @import url("foo.css");
414
+ /* Comment 2 */
415
+ @import url("bar.css");
416
+ .foo {
417
+ a: b; }
418
+
419
+ /* Comment 3 */
420
+ CSS
421
+ /* Comment 1 */
422
+ @import url("foo.css");
423
+
424
+ /* Comment 2 */
425
+
426
+ .foo {a: b}
427
+
428
+ /* Comment 3 */
429
+ @import url("bar.css");
430
+ SCSS
431
+ end
432
+
336
433
  def test_block_comment_in_script
337
434
  assert_equal <<CSS, render(<<SCSS)
338
435
  foo {
@@ -563,6 +660,33 @@ foo bar {
563
660
  SCSS
564
661
  end
565
662
 
663
+ def test_parent_selector_with_suffix
664
+ assert_equal <<CSS, render(<<SCSS)
665
+ .foo-bar {
666
+ a: b; }
667
+ .foo_bar {
668
+ c: d; }
669
+ .foobar {
670
+ e: f; }
671
+ .foo123 {
672
+ e: f; }
673
+
674
+ :hover-suffix {
675
+ g: h; }
676
+ CSS
677
+ .foo {
678
+ &-bar {a: b}
679
+ &_bar {c: d}
680
+ &bar {e: f}
681
+ &123 {e: f}
682
+ }
683
+
684
+ :hover {
685
+ &-suffix {g: h}
686
+ }
687
+ SCSS
688
+ end
689
+
566
690
  def test_unknown_directive_bubbling
567
691
  assert_equal(<<CSS, render(<<SCSS, :style => :nested))
568
692
  @fblthp {
@@ -1174,6 +1298,49 @@ CSS
1174
1298
  SCSS
1175
1299
  end
1176
1300
 
1301
+ def test_mixin_map_splat_converts_hyphens_and_underscores_for_real_args
1302
+ assert_equal <<CSS, render(<<SCSS)
1303
+ .foo {
1304
+ a: 1;
1305
+ b: 2;
1306
+ c: 3;
1307
+ d: 4; }
1308
+ CSS
1309
+ @mixin foo($a-1, $b-2, $c_3, $d_4) {
1310
+ a: $a-1;
1311
+ b: $b-2;
1312
+ c: $c_3;
1313
+ d: $d_4;
1314
+ }
1315
+
1316
+ .foo {
1317
+ $map: (a-1: 1, b_2: 2, c-3: 3, d_4: 4);
1318
+ @include foo($map...);
1319
+ }
1320
+ SCSS
1321
+ end
1322
+
1323
+ def test_mixin_map_splat_doesnt_convert_hyphens_and_underscores_for_var_args
1324
+ assert_equal <<CSS, render(<<SCSS)
1325
+ .foo {
1326
+ a-1: 1;
1327
+ b_2: 2;
1328
+ c-3: 3;
1329
+ d_4: 4; }
1330
+ CSS
1331
+ @mixin foo($args...) {
1332
+ @each $key, $value in keywords($args) {
1333
+ \#{$key}: $value;
1334
+ }
1335
+ }
1336
+
1337
+ .foo {
1338
+ $map: (a-1: 1, b_2: 2, c-3: 3, d_4: 4);
1339
+ @include foo($map...);
1340
+ }
1341
+ SCSS
1342
+ end
1343
+
1177
1344
  def test_mixin_conflicting_splat_after_keyword_args
1178
1345
  assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
1179
1346
  Mixin foo was passed argument $b both by position and by name.
@@ -2167,6 +2334,123 @@ CSS
2167
2334
  SCSS
2168
2335
  end
2169
2336
 
2337
+ def test_comments_in_at_root
2338
+ assert_equal <<CSS, render(<<SCSS)
2339
+ /* foo */
2340
+ .bar {
2341
+ a: b; }
2342
+
2343
+ /* baz */
2344
+ CSS
2345
+ .foo {
2346
+ @at-root {
2347
+ /* foo */
2348
+ .bar {a: b}
2349
+ /* baz */
2350
+ }
2351
+ }
2352
+ SCSS
2353
+ end
2354
+
2355
+ def test_comments_in_at_root_in_media
2356
+ assert_equal <<CSS, render(<<SCSS)
2357
+ @media screen {
2358
+ /* foo */
2359
+ .bar {
2360
+ a: b; }
2361
+
2362
+ /* baz */ }
2363
+ CSS
2364
+ @media screen {
2365
+ .foo {
2366
+ @at-root {
2367
+ /* foo */
2368
+ .bar {a: b}
2369
+ /* baz */
2370
+ }
2371
+ }
2372
+ }
2373
+ SCSS
2374
+ end
2375
+
2376
+ def test_comments_in_at_root_in_unknown_directive
2377
+ assert_equal <<CSS, render(<<SCSS)
2378
+ @fblthp {
2379
+ /* foo */
2380
+ .bar {
2381
+ a: b; }
2382
+
2383
+ /* baz */ }
2384
+ CSS
2385
+ @fblthp {
2386
+ .foo {
2387
+ @at-root {
2388
+ /* foo */
2389
+ .bar {a: b}
2390
+ /* baz */
2391
+ }
2392
+ }
2393
+ }
2394
+ SCSS
2395
+ end
2396
+
2397
+ def test_media_directive_in_at_root
2398
+ assert_equal <<CSS, render(<<SCSS)
2399
+ @media screen {
2400
+ .bar {
2401
+ a: b; } }
2402
+ CSS
2403
+ .foo {
2404
+ @at-root {
2405
+ @media screen {.bar {a: b}}
2406
+ }
2407
+ }
2408
+ SCSS
2409
+ end
2410
+
2411
+ def test_bubbled_media_directive_in_at_root
2412
+ assert_equal <<CSS, render(<<SCSS)
2413
+ @media screen {
2414
+ .bar .baz {
2415
+ a: b; } }
2416
+ CSS
2417
+ .foo {
2418
+ @at-root {
2419
+ .bar {
2420
+ @media screen {.baz {a: b}}
2421
+ }
2422
+ }
2423
+ }
2424
+ SCSS
2425
+ end
2426
+
2427
+ def test_unknown_directive_in_at_root
2428
+ assert_equal <<CSS, render(<<SCSS)
2429
+ @fblthp {
2430
+ .bar {
2431
+ a: b; } }
2432
+ CSS
2433
+ .foo {
2434
+ @at-root {
2435
+ @fblthp {.bar {a: b}}
2436
+ }
2437
+ }
2438
+ SCSS
2439
+ end
2440
+
2441
+ def test_at_root_in_at_root
2442
+ assert_equal <<CSS, render(<<SCSS)
2443
+ .bar {
2444
+ a: b; }
2445
+ CSS
2446
+ .foo {
2447
+ @at-root {
2448
+ @at-root .bar {a: b}
2449
+ }
2450
+ }
2451
+ SCSS
2452
+ end
2453
+
2170
2454
  def test_at_root_with_parent_ref
2171
2455
  assert_equal <<CSS, render(<<SCSS)
2172
2456
  .foo {
@@ -2212,6 +2496,45 @@ CSS
2212
2496
  SCSS
2213
2497
  end
2214
2498
 
2499
+ def test_at_root_beneath_comma_selector
2500
+ assert_equal(<<CSS, render(<<SCSS))
2501
+ .baz {
2502
+ a: b; }
2503
+ CSS
2504
+ .foo, .bar {
2505
+ @at-root .baz {
2506
+ a: b;
2507
+ }
2508
+ }
2509
+ SCSS
2510
+ end
2511
+
2512
+ def test_at_root_with_parent_ref_and_class
2513
+ assert_equal(<<CSS, render(<<SCSS))
2514
+ .foo.bar {
2515
+ a: b; }
2516
+ CSS
2517
+ .foo {
2518
+ @at-root &.bar {
2519
+ a: b;
2520
+ }
2521
+ }
2522
+ SCSS
2523
+ end
2524
+
2525
+ def test_at_root_beneath_comma_selector_with_parent_ref
2526
+ assert_equal(<<CSS, render(<<SCSS))
2527
+ .foo.baz, .bar.baz {
2528
+ a: b; }
2529
+ CSS
2530
+ .foo, .bar {
2531
+ @at-root &.baz {
2532
+ a: b;
2533
+ }
2534
+ }
2535
+ SCSS
2536
+ end
2537
+
2215
2538
  ## @at-root (...)
2216
2539
 
2217
2540
  def test_at_root_without_media
@@ -2268,6 +2591,7 @@ SCSS
2268
2591
 
2269
2592
  def test_at_root_without_unknown_directive
2270
2593
  assert_equal <<CSS, render(<<SCSS)
2594
+ @fblthp {}
2271
2595
  .foo .bar {
2272
2596
  a: b; }
2273
2597
  CSS
@@ -2305,6 +2629,8 @@ SCSS
2305
2629
 
2306
2630
  def test_at_root_without_all
2307
2631
  assert_equal <<CSS, render(<<SCSS)
2632
+ @supports (foo: bar) {
2633
+ @fblthp {} }
2308
2634
  .bar {
2309
2635
  a: b; }
2310
2636
  CSS
@@ -2325,6 +2651,7 @@ SCSS
2325
2651
  def test_at_root_with_media
2326
2652
  assert_equal <<CSS, render(<<SCSS)
2327
2653
  @media screen {
2654
+ @fblthp {}
2328
2655
  .bar {
2329
2656
  a: b; } }
2330
2657
  CSS
@@ -2346,6 +2673,8 @@ SCSS
2346
2673
 
2347
2674
  def test_at_root_with_rule
2348
2675
  assert_equal <<CSS, render(<<SCSS)
2676
+ @media screen {
2677
+ @fblthp {} }
2349
2678
  .foo .bar {
2350
2679
  a: b; }
2351
2680
  CSS
@@ -2367,6 +2696,8 @@ SCSS
2367
2696
 
2368
2697
  def test_at_root_with_supports
2369
2698
  assert_equal <<CSS, render(<<SCSS)
2699
+ @media screen {
2700
+ @fblthp {} }
2370
2701
  @supports (foo: bar) {
2371
2702
  .bar {
2372
2703
  a: b; } }
@@ -2389,6 +2720,8 @@ SCSS
2389
2720
 
2390
2721
  def test_at_root_with_unknown_directive
2391
2722
  assert_equal <<CSS, render(<<SCSS)
2723
+ @media screen {
2724
+ @fblthp {} }
2392
2725
  @fblthp {
2393
2726
  .bar {
2394
2727
  a: b; } }
@@ -2412,6 +2745,7 @@ SCSS
2412
2745
  def test_at_root_with_multiple
2413
2746
  assert_equal <<CSS, render(<<SCSS)
2414
2747
  @media screen {
2748
+ @fblthp {}
2415
2749
  .foo .bar {
2416
2750
  a: b; } }
2417
2751
  CSS
@@ -2514,185 +2848,6 @@ CSS
2514
2848
  SCSS
2515
2849
  end
2516
2850
 
2517
- ## Selector Script
2518
-
2519
- def test_selector_script
2520
- assert_equal(<<CSS, render(<<SCSS))
2521
- .foo .bar {
2522
- content: ".foo .bar"; }
2523
- CSS
2524
- .foo .bar {
2525
- content: "\#{&}";
2526
- }
2527
- SCSS
2528
- end
2529
-
2530
- def test_nested_selector_script
2531
- assert_equal(<<CSS, render(<<SCSS))
2532
- .foo .bar {
2533
- content: ".foo .bar"; }
2534
- CSS
2535
- .foo {
2536
- .bar {
2537
- content: "\#{&}";
2538
- }
2539
- }
2540
- SCSS
2541
- end
2542
-
2543
- def test_nested_selector_script_with_outer_comma_selector
2544
- assert_equal(<<CSS, render(<<SCSS))
2545
- .foo .baz, .bar .baz {
2546
- content: ".foo .baz, .bar .baz"; }
2547
- CSS
2548
- .foo, .bar {
2549
- .baz {
2550
- content: "\#{&}";
2551
- }
2552
- }
2553
- SCSS
2554
- end
2555
-
2556
- def test_nested_selector_script_with_inner_comma_selector
2557
- assert_equal(<<CSS, render(<<SCSS))
2558
- .foo .bar, .foo .baz {
2559
- content: ".foo .bar, .foo .baz"; }
2560
- CSS
2561
- .foo {
2562
- .bar, .baz {
2563
- content: "\#{&}";
2564
- }
2565
- }
2566
- SCSS
2567
- end
2568
-
2569
- def test_selector_script_through_mixin
2570
- assert_equal(<<CSS, render(<<SCSS))
2571
- .foo {
2572
- content: ".foo"; }
2573
- CSS
2574
- @mixin mixin {
2575
- content: "\#{&}";
2576
- }
2577
-
2578
- .foo {
2579
- @include mixin;
2580
- }
2581
- SCSS
2582
- end
2583
-
2584
- def test_selector_script_through_content
2585
- assert_equal(<<CSS, render(<<SCSS))
2586
- .foo {
2587
- content: ".foo"; }
2588
- CSS
2589
- @mixin mixin {
2590
- @content;
2591
- }
2592
-
2593
- .foo {
2594
- @include mixin {
2595
- content: "\#{&}";
2596
- }
2597
- }
2598
- SCSS
2599
- end
2600
-
2601
- def test_selector_script_through_function
2602
- assert_equal(<<CSS, render(<<SCSS))
2603
- .foo {
2604
- content: ".foo"; }
2605
- CSS
2606
- @function fn() {
2607
- @return "\#{&}";
2608
- }
2609
-
2610
- .foo {
2611
- content: fn();
2612
- }
2613
- SCSS
2614
- end
2615
-
2616
- def test_selector_script_through_media
2617
- assert_equal(<<CSS, render(<<SCSS))
2618
- .foo {
2619
- content: "outer"; }
2620
- @media screen {
2621
- .foo .bar {
2622
- content: ".foo .bar"; } }
2623
- CSS
2624
- .foo {
2625
- content: "outer";
2626
- @media screen {
2627
- .bar {
2628
- content: "\#{&}";
2629
- }
2630
- }
2631
- }
2632
- SCSS
2633
- end
2634
-
2635
- def test_selector_script_save_and_reuse
2636
- assert_equal(<<CSS, render(<<SCSS))
2637
- .bar {
2638
- content: ".foo"; }
2639
- CSS
2640
- $var: null;
2641
- .foo {
2642
- $var: & !global;
2643
- }
2644
-
2645
- .bar {
2646
- content: "\#{$var}";
2647
- }
2648
- SCSS
2649
- end
2650
-
2651
- def test_selector_script_with_at_root
2652
- assert_equal(<<CSS, render(<<SCSS))
2653
- .foo-bar {
2654
- a: b; }
2655
- CSS
2656
- .foo {
2657
- @at-root \#{&}-bar {
2658
- a: b;
2659
- }
2660
- }
2661
- SCSS
2662
- end
2663
-
2664
- def test_multi_level_at_root_with_inner_selector_script
2665
- assert_equal <<CSS, render(<<SCSS)
2666
- .bar {
2667
- a: b; }
2668
- CSS
2669
- .foo {
2670
- @at-root .bar {
2671
- @at-root \#{&} {
2672
- a: b;
2673
- }
2674
- }
2675
- }
2676
- SCSS
2677
- end
2678
-
2679
- def test_at_root_with_at_root_through_mixin
2680
- assert_equal(<<CSS, render(<<SCSS))
2681
- .bar-baz {
2682
- a: b; }
2683
- CSS
2684
- @mixin foo {
2685
- .bar {
2686
- @at-root \#{&}-baz {
2687
- a: b;
2688
- }
2689
- }
2690
- }
2691
-
2692
- @include foo;
2693
- SCSS
2694
- end
2695
-
2696
2851
  ## Errors
2697
2852
 
2698
2853
  def test_nested_mixin_def_is_scoped
@@ -2901,6 +3056,48 @@ MESSAGE
2901
3056
  SCSS
2902
3057
  end
2903
3058
 
3059
+ def test_failed_parent_selector_with_suffix
3060
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3061
+ Invalid parent selector for "&-bar": "*"
3062
+ MESSAGE
3063
+ * {
3064
+ &-bar {a: b}
3065
+ }
3066
+ SCSS
3067
+
3068
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3069
+ Invalid parent selector for "&-bar": "[foo=bar]"
3070
+ MESSAGE
3071
+ [foo=bar] {
3072
+ &-bar {a: b}
3073
+ }
3074
+ SCSS
3075
+
3076
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3077
+ Invalid parent selector for "&-bar": "::nth-child(2n+1)"
3078
+ MESSAGE
3079
+ ::nth-child(2n+1) {
3080
+ &-bar {a: b}
3081
+ }
3082
+ SCSS
3083
+
3084
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3085
+ Invalid parent selector for "&-bar": ":not(.foo)"
3086
+ MESSAGE
3087
+ :not(.foo) {
3088
+ &-bar {a: b}
3089
+ }
3090
+ SCSS
3091
+
3092
+ assert_raise_message(Sass::SyntaxError, <<MESSAGE.rstrip) {render(<<SCSS)}
3093
+ Invalid parent selector for "&-bar": ".foo +"
3094
+ MESSAGE
3095
+ .foo + {
3096
+ &-bar {a: b}
3097
+ }
3098
+ SCSS
3099
+ end
3100
+
2904
3101
  # Regression
2905
3102
 
2906
3103
  def test_loud_comment_in_compressed_mode