sass 3.2.0.alpha.60 → 3.2.0.alpha.61

Sign up to get free protection for your applications and to get access to all the features.
@@ -247,6 +247,8 @@ END
247
247
  # Runs SassScript interpolation in the selector,
248
248
  # and then parses the result into a {Sass::Selector::CommaSequence}.
249
249
  def visit_rule(node)
250
+ rule = node.rule
251
+ rule = rule.map {|e| e.is_a?(String) && e != ' ' ? e.strip : e} if node.style == :compressed
250
252
  parser = Sass::SCSS::StaticParser.new(run_interp(node.rule), node.filename, node.line)
251
253
  node.parsed_rules ||= parser.parse_selector
252
254
  if node.options[:trace_selectors]
@@ -295,6 +297,7 @@ END
295
297
  end
296
298
 
297
299
  def visit_media(node)
300
+ node.query = node.query.deep_copy
298
301
  node.query.perform {|interp| run_interp(interp)}
299
302
  yield
300
303
  end
@@ -94,4 +94,14 @@ class Sass::Tree::Visitors::SetOptions < Sass::Tree::Visitors::Base
94
94
  node.expr.options = @options
95
95
  yield
96
96
  end
97
+
98
+ def visit_directive(node)
99
+ node.value.each {|c| c.options = @options if c.is_a?(Sass::Script::Node)}
100
+ yield
101
+ end
102
+
103
+ def visit_media(node)
104
+ node.query.options = @options
105
+ yield
106
+ end
97
107
  end
@@ -67,8 +67,10 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
67
67
  end
68
68
 
69
69
  def visit_directive(node)
70
+ was_in_directive = @in_directive
70
71
  return node.resolved_value + ";" unless node.has_children
71
72
  return node.resolved_value + " {}" if node.children.empty?
73
+ @in_directive = @in_directive || !node.is_a?(Sass::Tree::MediaNode)
72
74
  result = if node.style == :compressed
73
75
  "#{node.resolved_value}{"
74
76
  else
@@ -101,6 +103,8 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
101
103
  else
102
104
  (node.style == :expanded ? "\n" : " ") + "}\n"
103
105
  end
106
+ ensure
107
+ @in_directive = was_in_directive
104
108
  end
105
109
 
106
110
  def visit_media(node)
@@ -133,7 +137,11 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
133
137
  joined_rules = node.resolved_rules.members.map do |seq|
134
138
  next if seq.has_placeholder?
135
139
  rule_part = seq.to_a.join
136
- rule_part.gsub!(/\s*([^,])\s*\n\s*/m, '\1 ') if node.style == :compressed
140
+ if node.style == :compressed
141
+ rule_part.gsub!(/([^,])\s*\n\s*/m, '\1 ')
142
+ rule_part.gsub!(/\s*([,+>])\s*/m, '\1')
143
+ rule_part.strip!
144
+ end
137
145
  rule_part
138
146
  end.compact.join(rule_separator)
139
147
 
@@ -145,7 +153,7 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
145
153
  old_spaces = ' ' * @tabs
146
154
  spaces = ' ' * (@tabs + 1)
147
155
  if node.style != :compressed
148
- if node.options[:debug_info]
156
+ if node.options[:debug_info] && !@in_directive
149
157
  to_return << visit(debug_info_rule(node.debug_info, node.options)) << "\n"
150
158
  elsif node.options[:trace_selectors]
151
159
  to_return << "#{old_spaces}/* "
@@ -191,7 +199,7 @@ class Sass::Tree::Visitors::ToCss < Sass::Tree::Visitors::Base
191
199
 
192
200
  def debug_info_rule(debug_info, options)
193
201
  node = Sass::Tree::DirectiveNode.resolved("@media -sass-debug-info")
194
- debug_info.map {|k, v| [k.to_s, v.to_s]}.sort.each do |k, v|
202
+ Sass::Util.hash_to_a(debug_info.map {|k, v| [k.to_s, v.to_s]}).each do |k, v|
195
203
  rule = Sass::Tree::RuleNode.new([""])
196
204
  rule.resolved_rules = Sass::Selector::CommaSequence.new(
197
205
  [Sass::Selector::Sequence.new(
data/lib/sass/util.rb CHANGED
@@ -218,6 +218,20 @@ module Sass
218
218
  lcs_backtrace(lcs_table(x, y, &block), x, y, x.size-1, y.size-1, &block)
219
219
  end
220
220
 
221
+ # Converts a Hash to an Array. This is usually identical to `Hash#to_a`,
222
+ # with the following exceptions:
223
+ #
224
+ # * In Ruby 1.8, `Hash#to_a` is not deterministically ordered, but this is.
225
+ # * In Ruby 1.9 when running tests, this is ordered in the same way it would
226
+ # be under Ruby 1.8 (sorted key order rather than insertion order).
227
+ #
228
+ # @param hash [Hash]
229
+ # @return [Array]
230
+ def hash_to_a(hash)
231
+ return has.to_a unless ruby1_8? || defined?(Test::Unit)
232
+ return hash.sort_by {|k, v| k}
233
+ end
234
+
221
235
  # Returns information about the caller of the previous method.
222
236
  #
223
237
  # @param entry [String] An entry in the `#caller` list, or a similarly formatted string
@@ -561,6 +575,24 @@ MSG
561
575
  ruby1_8? ? enum.enum_slice(n) : enum.each_slice(n)
562
576
  end
563
577
 
578
+ # Destructively removes all elements from an array that match a block, and
579
+ # returns the removed elements.
580
+ #
581
+ # @param array [Array] The array from which to remove elements.
582
+ # @yield [el] Called for each element.
583
+ # @yieldparam el [*] The element to test.
584
+ # @yieldreturn [Boolean] Whether or not to extract the element.
585
+ # @return [Array] The extracted elements.
586
+ def extract!(array)
587
+ out = []
588
+ array.reject! do |e|
589
+ next false unless yield e
590
+ out << e
591
+ true
592
+ end
593
+ out
594
+ end
595
+
564
596
  # Returns the ASCII code of the given character.
565
597
  #
566
598
  # @param c [String] All characters but the first are ignored.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- coding: utf-8 -*-
3
- require 'test_helper'
4
- require 'sass/test_helper'
3
+ require File.dirname(__FILE__) + '/../test_helper'
4
+ require File.dirname(__FILE__) + '/test_helper'
5
5
  require 'sass/engine'
6
6
  require 'stringio'
7
7
  require 'mock_importer'
@@ -1028,6 +1028,23 @@ foo
1028
1028
  SASS
1029
1029
  end
1030
1030
 
1031
+ def test_debug_info_in_keyframes
1032
+ assert_equal(<<CSS, render(<<SASS, :debug_info => true))
1033
+ @-webkit-keyframes warm {
1034
+ from {
1035
+ color: black; }
1036
+
1037
+ to {
1038
+ color: red; } }
1039
+ CSS
1040
+ @-webkit-keyframes warm
1041
+ from
1042
+ color: black
1043
+ to
1044
+ color: red
1045
+ SASS
1046
+ end
1047
+
1031
1048
  def test_empty_first_line
1032
1049
  assert_equal("#a {\n b: c; }\n", render("#a\n\n b: c"))
1033
1050
  end
@@ -2212,6 +2229,27 @@ SASS
2212
2229
 
2213
2230
  # Regression tests
2214
2231
 
2232
+ def test_variable_in_media_in_mixin
2233
+ assert_equal <<CSS, render(<<SASS)
2234
+ @media screen and (min-width: 10px) {
2235
+ body {
2236
+ background: red; } }
2237
+ @media screen and (min-width: 20px) {
2238
+ body {
2239
+ background: blue; } }
2240
+ CSS
2241
+ @mixin respond-to($width)
2242
+ @media screen and (min-width: $width)
2243
+ @content
2244
+
2245
+ body
2246
+ @include respond-to(10px)
2247
+ background: red
2248
+ @include respond-to(20px)
2249
+ background: blue
2250
+ SASS
2251
+ end
2252
+
2215
2253
  def test_tricky_mixin_loop_exception
2216
2254
  render <<SASS
2217
2255
  @mixin foo($a)
@@ -2541,6 +2579,15 @@ CSS
2541
2579
  SASS
2542
2580
  end
2543
2581
 
2582
+ def test_selector_compression
2583
+ assert_equal <<CSS, render(<<SASS, :style => :compressed)
2584
+ a>b,c+d,:-moz-any(e,f,g){h:i}
2585
+ CSS
2586
+ a > b, c + d, :-moz-any(e, f, g)
2587
+ h: i
2588
+ SASS
2589
+ end
2590
+
2544
2591
  # Encodings
2545
2592
 
2546
2593
  unless Sass::Util.ruby1_8?
@@ -1165,6 +1165,70 @@ SCSS
1165
1165
  CSS
1166
1166
  .baz.foo {a: b}
1167
1167
  foo > bar {@extend .foo}
1168
+ SCSS
1169
+
1170
+ assert_equal <<CSS, render(<<SCSS)
1171
+ .baz > .foo, .baz > .bar {
1172
+ a: b; }
1173
+ CSS
1174
+ .baz > {
1175
+ .foo {a: b}
1176
+ .bar {@extend .foo}
1177
+ }
1178
+ SCSS
1179
+
1180
+ assert_equal <<CSS, render(<<SCSS)
1181
+ .foo .bar, .foo > .baz {
1182
+ a: b; }
1183
+ CSS
1184
+ .foo {
1185
+ .bar {a: b}
1186
+ > .baz {@extend .bar}
1187
+ }
1188
+ SCSS
1189
+
1190
+ assert_equal <<CSS, render(<<SCSS)
1191
+ .foo .bar, .foo .bip > .baz {
1192
+ a: b; }
1193
+ CSS
1194
+ .foo {
1195
+ .bar {a: b}
1196
+ .bip > .baz {@extend .bar}
1197
+ }
1198
+ SCSS
1199
+
1200
+ assert_equal <<CSS, render(<<SCSS)
1201
+ .foo .bip .bar, .foo .bip .foo > .baz {
1202
+ a: b; }
1203
+ CSS
1204
+ .foo {
1205
+ .bip .bar {a: b}
1206
+ > .baz {@extend .bar}
1207
+ }
1208
+ SCSS
1209
+
1210
+ assert_equal <<CSS, render(<<SCSS)
1211
+ .foo > .bar, .foo > .bip + .baz {
1212
+ a: b; }
1213
+ CSS
1214
+ .foo > .bar {a: b}
1215
+ .bip + .baz {@extend .bar}
1216
+ SCSS
1217
+
1218
+ assert_equal <<CSS, render(<<SCSS)
1219
+ .foo + .bar, .bip > .foo + .baz {
1220
+ a: b; }
1221
+ CSS
1222
+ .foo + .bar {a: b}
1223
+ .bip > .baz {@extend .bar}
1224
+ SCSS
1225
+
1226
+ assert_equal <<CSS, render(<<SCSS)
1227
+ .foo > .bar, .bip.foo > .baz {
1228
+ a: b; }
1229
+ CSS
1230
+ .foo > .bar {a: b}
1231
+ .bip > .baz {@extend .bar}
1168
1232
  SCSS
1169
1233
  end
1170
1234
 
@@ -1186,7 +1250,7 @@ SCSS
1186
1250
 
1187
1251
  def test_nested_extender_with_hacky_selector
1188
1252
  assert_equal <<CSS, render(<<SCSS)
1189
- .baz .foo, .baz foo + > > + bar {
1253
+ .baz .foo, .baz foo + > > + bar, foo .baz + > > + bar {
1190
1254
  a: b; }
1191
1255
  CSS
1192
1256
  .baz .foo {a: b}
@@ -1194,7 +1258,7 @@ foo + > > + bar {@extend .foo}
1194
1258
  SCSS
1195
1259
 
1196
1260
  assert_equal <<CSS, render(<<SCSS)
1197
- .baz .foo, .baz > > bar {
1261
+ .baz .foo, > > .baz bar {
1198
1262
  a: b; }
1199
1263
  CSS
1200
1264
  .baz .foo {a: b}
@@ -1223,6 +1287,402 @@ CSS
1223
1287
  SCSS
1224
1288
  end
1225
1289
 
1290
+ # Combinator Unification
1291
+
1292
+ def test_combinator_unification_for_hacky_combinators
1293
+ assert_equal <<CSS, render(<<SCSS)
1294
+ .a > + x, .a .b > + y, .b .a > + y {
1295
+ a: b; }
1296
+ CSS
1297
+ .a > + x {a: b}
1298
+ .b y {@extend x}
1299
+ SCSS
1300
+
1301
+ assert_equal <<CSS, render(<<SCSS)
1302
+ .a x, .a .b > + y, .b .a > + y {
1303
+ a: b; }
1304
+ CSS
1305
+ .a x {a: b}
1306
+ .b > + y {@extend x}
1307
+ SCSS
1308
+
1309
+ assert_equal <<CSS, render(<<SCSS)
1310
+ .a > + x, .a .b > + y, .b .a > + y {
1311
+ a: b; }
1312
+ CSS
1313
+ .a > + x {a: b}
1314
+ .b > + y {@extend x}
1315
+ SCSS
1316
+
1317
+ assert_equal <<CSS, render(<<SCSS)
1318
+ .a ~ > + x, .a .b ~ > + y, .b .a ~ > + y {
1319
+ a: b; }
1320
+ CSS
1321
+ .a ~ > + x {a: b}
1322
+ .b > + y {@extend x}
1323
+ SCSS
1324
+
1325
+ assert_equal <<CSS, render(<<SCSS)
1326
+ .a + > x {
1327
+ a: b; }
1328
+ CSS
1329
+ .a + > x {a: b}
1330
+ .b > + y {@extend x}
1331
+ SCSS
1332
+
1333
+ assert_equal <<CSS, render(<<SCSS)
1334
+ .a + > x {
1335
+ a: b; }
1336
+ CSS
1337
+ .a + > x {a: b}
1338
+ .b > + y {@extend x}
1339
+ SCSS
1340
+
1341
+ assert_equal <<CSS, render(<<SCSS)
1342
+ .a ~ > + .b > x, .a .c ~ > + .d.b > y, .c .a ~ > + .d.b > y {
1343
+ a: b; }
1344
+ CSS
1345
+ .a ~ > + .b > x {a: b}
1346
+ .c > + .d > y {@extend x}
1347
+ SCSS
1348
+ end
1349
+
1350
+ def test_combinator_unification_double_tilde
1351
+ assert_equal <<CSS, render(<<SCSS)
1352
+ .a.b ~ x, .a.b ~ y {
1353
+ a: b; }
1354
+ CSS
1355
+ .a.b ~ x {a: b}
1356
+ .a ~ y {@extend x}
1357
+ SCSS
1358
+
1359
+ assert_equal <<CSS, render(<<SCSS)
1360
+ .a ~ x, .a.b ~ y {
1361
+ a: b; }
1362
+ CSS
1363
+ .a ~ x {a: b}
1364
+ .a.b ~ y {@extend x}
1365
+ SCSS
1366
+
1367
+ assert_equal <<CSS, render(<<SCSS)
1368
+ .a ~ x, .a ~ .b ~ y, .b ~ .a ~ y, .b.a ~ y {
1369
+ a: b; }
1370
+ CSS
1371
+ .a ~ x {a: b}
1372
+ .b ~ y {@extend x}
1373
+ SCSS
1374
+
1375
+ assert_equal <<CSS, render(<<SCSS)
1376
+ a.a ~ x, a.a ~ b.b ~ y, b.b ~ a.a ~ y {
1377
+ a: b; }
1378
+ CSS
1379
+ a.a ~ x {a: b}
1380
+ b.b ~ y {@extend x}
1381
+ SCSS
1382
+ end
1383
+
1384
+ def test_combinator_unification_tilde_plus
1385
+ assert_equal <<CSS, render(<<SCSS)
1386
+ .a.b + x, .a.b + y {
1387
+ a: b; }
1388
+ CSS
1389
+ .a.b + x {a: b}
1390
+ .a ~ y {@extend x}
1391
+ SCSS
1392
+
1393
+ assert_equal <<CSS, render(<<SCSS)
1394
+ .a + x, .a.b ~ .a + y, .a.b + y {
1395
+ a: b; }
1396
+ CSS
1397
+ .a + x {a: b}
1398
+ .a.b ~ y {@extend x}
1399
+ SCSS
1400
+
1401
+ assert_equal <<CSS, render(<<SCSS)
1402
+ .a + x, .b ~ .a + y, .b.a + y {
1403
+ a: b; }
1404
+ CSS
1405
+ .a + x {a: b}
1406
+ .b ~ y {@extend x}
1407
+ SCSS
1408
+
1409
+ assert_equal <<CSS, render(<<SCSS)
1410
+ a.a + x, b.b ~ a.a + y {
1411
+ a: b; }
1412
+ CSS
1413
+ a.a + x {a: b}
1414
+ b.b ~ y {@extend x}
1415
+ SCSS
1416
+
1417
+ assert_equal <<CSS, render(<<SCSS)
1418
+ .a.b ~ x, .a.b ~ .a + y, .a.b + y {
1419
+ a: b; }
1420
+ CSS
1421
+ .a.b ~ x {a: b}
1422
+ .a + y {@extend x}
1423
+ SCSS
1424
+
1425
+ assert_equal <<CSS, render(<<SCSS)
1426
+ .a ~ x, .a.b + y {
1427
+ a: b; }
1428
+ CSS
1429
+ .a ~ x {a: b}
1430
+ .a.b + y {@extend x}
1431
+ SCSS
1432
+
1433
+ assert_equal <<CSS, render(<<SCSS)
1434
+ .a ~ x, .a ~ .b + y, .a.b + y {
1435
+ a: b; }
1436
+ CSS
1437
+ .a ~ x {a: b}
1438
+ .b + y {@extend x}
1439
+ SCSS
1440
+
1441
+ assert_equal <<CSS, render(<<SCSS)
1442
+ a.a ~ x, a.a ~ b.b + y {
1443
+ a: b; }
1444
+ CSS
1445
+ a.a ~ x {a: b}
1446
+ b.b + y {@extend x}
1447
+ SCSS
1448
+ end
1449
+
1450
+ def test_combinator_unification_angle_sibling
1451
+ assert_equal <<CSS, render(<<SCSS)
1452
+ .a > x, .a > .b ~ y {
1453
+ a: b; }
1454
+ CSS
1455
+ .a > x {a: b}
1456
+ .b ~ y {@extend x}
1457
+ SCSS
1458
+
1459
+ assert_equal <<CSS, render(<<SCSS)
1460
+ .a > x, .a > .b + y {
1461
+ a: b; }
1462
+ CSS
1463
+ .a > x {a: b}
1464
+ .b + y {@extend x}
1465
+ SCSS
1466
+
1467
+ assert_equal <<CSS, render(<<SCSS)
1468
+ .a ~ x, .b > .a ~ y {
1469
+ a: b; }
1470
+ CSS
1471
+ .a ~ x {a: b}
1472
+ .b > y {@extend x}
1473
+ SCSS
1474
+
1475
+ assert_equal <<CSS, render(<<SCSS)
1476
+ .a + x, .b > .a + y {
1477
+ a: b; }
1478
+ CSS
1479
+ .a + x {a: b}
1480
+ .b > y {@extend x}
1481
+ SCSS
1482
+ end
1483
+
1484
+ def test_combinator_unification_double_angle
1485
+ assert_equal <<CSS, render(<<SCSS)
1486
+ .a.b > x, .b.a > y {
1487
+ a: b; }
1488
+ CSS
1489
+ .a.b > x {a: b}
1490
+ .b > y {@extend x}
1491
+ SCSS
1492
+
1493
+ assert_equal <<CSS, render(<<SCSS)
1494
+ .a > x, .a.b > y {
1495
+ a: b; }
1496
+ CSS
1497
+ .a > x {a: b}
1498
+ .a.b > y {@extend x}
1499
+ SCSS
1500
+
1501
+ assert_equal <<CSS, render(<<SCSS)
1502
+ .a > x, .b.a > y {
1503
+ a: b; }
1504
+ CSS
1505
+ .a > x {a: b}
1506
+ .b > y {@extend x}
1507
+ SCSS
1508
+
1509
+ assert_equal <<CSS, render(<<SCSS)
1510
+ a.a > x {
1511
+ a: b; }
1512
+ CSS
1513
+ a.a > x {a: b}
1514
+ b.b > y {@extend x}
1515
+ SCSS
1516
+ end
1517
+
1518
+ def test_combinator_unification_double_plus
1519
+ assert_equal <<CSS, render(<<SCSS)
1520
+ .a.b + x, .b.a + y {
1521
+ a: b; }
1522
+ CSS
1523
+ .a.b + x {a: b}
1524
+ .b + y {@extend x}
1525
+ SCSS
1526
+
1527
+ assert_equal <<CSS, render(<<SCSS)
1528
+ .a + x, .a.b + y {
1529
+ a: b; }
1530
+ CSS
1531
+ .a + x {a: b}
1532
+ .a.b + y {@extend x}
1533
+ SCSS
1534
+
1535
+ assert_equal <<CSS, render(<<SCSS)
1536
+ .a + x, .b.a + y {
1537
+ a: b; }
1538
+ CSS
1539
+ .a + x {a: b}
1540
+ .b + y {@extend x}
1541
+ SCSS
1542
+
1543
+ assert_equal <<CSS, render(<<SCSS)
1544
+ a.a + x {
1545
+ a: b; }
1546
+ CSS
1547
+ a.a + x {a: b}
1548
+ b.b + y {@extend x}
1549
+ SCSS
1550
+ end
1551
+
1552
+ def test_combinator_unification_angle_space
1553
+ assert_equal <<CSS, render(<<SCSS)
1554
+ .a.b > x, .a.b > y {
1555
+ a: b; }
1556
+ CSS
1557
+ .a.b > x {a: b}
1558
+ .a y {@extend x}
1559
+ SCSS
1560
+
1561
+ assert_equal <<CSS, render(<<SCSS)
1562
+ .a > x, .a.b .a > y {
1563
+ a: b; }
1564
+ CSS
1565
+ .a > x {a: b}
1566
+ .a.b y {@extend x}
1567
+ SCSS
1568
+
1569
+ assert_equal <<CSS, render(<<SCSS)
1570
+ .a > x, .b .a > y {
1571
+ a: b; }
1572
+ CSS
1573
+ .a > x {a: b}
1574
+ .b y {@extend x}
1575
+ SCSS
1576
+
1577
+ assert_equal <<CSS, render(<<SCSS)
1578
+ .a.b x, .a.b .a > y {
1579
+ a: b; }
1580
+ CSS
1581
+ .a.b x {a: b}
1582
+ .a > y {@extend x}
1583
+ SCSS
1584
+
1585
+ assert_equal <<CSS, render(<<SCSS)
1586
+ .a x, .a.b > y {
1587
+ a: b; }
1588
+ CSS
1589
+ .a x {a: b}
1590
+ .a.b > y {@extend x}
1591
+ SCSS
1592
+
1593
+ assert_equal <<CSS, render(<<SCSS)
1594
+ .a x, .a .b > y {
1595
+ a: b; }
1596
+ CSS
1597
+ .a x {a: b}
1598
+ .b > y {@extend x}
1599
+ SCSS
1600
+ end
1601
+
1602
+ def test_combinator_unification_plus_space
1603
+ assert_equal <<CSS, render(<<SCSS)
1604
+ .a.b + x, .a .a.b + y {
1605
+ a: b; }
1606
+ CSS
1607
+ .a.b + x {a: b}
1608
+ .a y {@extend x}
1609
+ SCSS
1610
+
1611
+ assert_equal <<CSS, render(<<SCSS)
1612
+ .a + x, .a.b .a + y {
1613
+ a: b; }
1614
+ CSS
1615
+ .a + x {a: b}
1616
+ .a.b y {@extend x}
1617
+ SCSS
1618
+
1619
+ assert_equal <<CSS, render(<<SCSS)
1620
+ .a + x, .b .a + y {
1621
+ a: b; }
1622
+ CSS
1623
+ .a + x {a: b}
1624
+ .b y {@extend x}
1625
+ SCSS
1626
+
1627
+ assert_equal <<CSS, render(<<SCSS)
1628
+ .a.b x, .a.b .a + y {
1629
+ a: b; }
1630
+ CSS
1631
+ .a.b x {a: b}
1632
+ .a + y {@extend x}
1633
+ SCSS
1634
+
1635
+ assert_equal <<CSS, render(<<SCSS)
1636
+ .a x, .a .a.b + y {
1637
+ a: b; }
1638
+ CSS
1639
+ .a x {a: b}
1640
+ .a.b + y {@extend x}
1641
+ SCSS
1642
+
1643
+ assert_equal <<CSS, render(<<SCSS)
1644
+ .a x, .a .b + y {
1645
+ a: b; }
1646
+ CSS
1647
+ .a x {a: b}
1648
+ .b + y {@extend x}
1649
+ SCSS
1650
+ end
1651
+
1652
+ def test_combinator_unification_nested
1653
+ assert_equal <<CSS, render(<<SCSS)
1654
+ .a > .b + x, .c.a > .d.b + y {
1655
+ a: b; }
1656
+ CSS
1657
+ .a > .b + x {a: b}
1658
+ .c > .d + y {@extend x}
1659
+ SCSS
1660
+
1661
+ assert_equal <<CSS, render(<<SCSS)
1662
+ .a > .b + x, .c.a > .b + y {
1663
+ a: b; }
1664
+ CSS
1665
+ .a > .b + x {a: b}
1666
+ .c > y {@extend x}
1667
+ SCSS
1668
+ end
1669
+
1670
+ def test_combinator_unification_with_newlines
1671
+ assert_equal <<CSS, render(<<SCSS)
1672
+ .a >
1673
+ .b
1674
+ + x, .c.a > .d.b + y {
1675
+ a: b; }
1676
+ CSS
1677
+ .a >
1678
+ .b
1679
+ + x {a: b}
1680
+ .c
1681
+ > .d +
1682
+ y {@extend x}
1683
+ SCSS
1684
+ end
1685
+
1226
1686
  # Loops
1227
1687
 
1228
1688
  def test_extend_self_loop
@@ -1431,6 +1891,20 @@ SCSS
1431
1891
 
1432
1892
  # Regression Tests
1433
1893
 
1894
+ def test_newline_near_combinator
1895
+ assert_equal <<CSS, render(<<SCSS)
1896
+ .a +
1897
+ .b x, .a +
1898
+ .b .c y, .c .a +
1899
+ .b y {
1900
+ a: b; }
1901
+ CSS
1902
+ .a +
1903
+ .b x {a: b}
1904
+ .c y {@extend x}
1905
+ SCSS
1906
+ end
1907
+
1434
1908
  def test_duplicated_selector_with_newlines
1435
1909
  assert_equal(<<CSS, render(<<SCSS))
1436
1910
  .example-1-1,