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

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.
@@ -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,