sassc 1.8.3 → 1.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/ext/libsass/.editorconfig +1 -1
  4. data/ext/libsass/.gitignore +1 -0
  5. data/ext/libsass/LICENSE +1 -1
  6. data/ext/libsass/Makefile +20 -14
  7. data/ext/libsass/Makefile.conf +0 -1
  8. data/ext/libsass/Readme.md +3 -1
  9. data/ext/libsass/appveyor.yml +19 -11
  10. data/ext/libsass/docs/api-importer-example.md +2 -1235
  11. data/ext/libsass/docs/build-with-autotools.md +10 -0
  12. data/ext/libsass/docs/build-with-makefiles.md +18 -0
  13. data/ext/libsass/include/sass/base.h +4 -1
  14. data/ext/libsass/include/sass/values.h +2 -1
  15. data/ext/libsass/src/ast.cpp +279 -346
  16. data/ext/libsass/src/ast.hpp +234 -60
  17. data/ext/libsass/src/base64vlq.cpp +1 -0
  18. data/ext/libsass/src/bind.cpp +35 -45
  19. data/ext/libsass/src/bind.hpp +1 -0
  20. data/ext/libsass/src/color_maps.cpp +1 -0
  21. data/ext/libsass/src/constants.cpp +4 -1
  22. data/ext/libsass/src/constants.hpp +2 -1
  23. data/ext/libsass/src/context.cpp +41 -31
  24. data/ext/libsass/src/context.hpp +10 -10
  25. data/ext/libsass/src/cssize.cpp +7 -4
  26. data/ext/libsass/src/cssize.hpp +1 -3
  27. data/ext/libsass/src/debugger.hpp +73 -14
  28. data/ext/libsass/src/emitter.cpp +37 -25
  29. data/ext/libsass/src/emitter.hpp +10 -9
  30. data/ext/libsass/src/environment.cpp +16 -5
  31. data/ext/libsass/src/environment.hpp +5 -3
  32. data/ext/libsass/src/error_handling.cpp +91 -14
  33. data/ext/libsass/src/error_handling.hpp +105 -4
  34. data/ext/libsass/src/eval.cpp +519 -330
  35. data/ext/libsass/src/eval.hpp +12 -13
  36. data/ext/libsass/src/expand.cpp +92 -56
  37. data/ext/libsass/src/expand.hpp +5 -3
  38. data/ext/libsass/src/extend.cpp +60 -51
  39. data/ext/libsass/src/extend.hpp +1 -3
  40. data/ext/libsass/src/file.cpp +37 -27
  41. data/ext/libsass/src/functions.cpp +78 -62
  42. data/ext/libsass/src/functions.hpp +1 -0
  43. data/ext/libsass/src/inspect.cpp +293 -64
  44. data/ext/libsass/src/inspect.hpp +2 -0
  45. data/ext/libsass/src/lexer.cpp +1 -0
  46. data/ext/libsass/src/listize.cpp +14 -15
  47. data/ext/libsass/src/listize.hpp +3 -5
  48. data/ext/libsass/src/memory_manager.cpp +1 -0
  49. data/ext/libsass/src/node.cpp +2 -3
  50. data/ext/libsass/src/operation.hpp +70 -71
  51. data/ext/libsass/src/output.cpp +28 -32
  52. data/ext/libsass/src/output.hpp +1 -2
  53. data/ext/libsass/src/parser.cpp +402 -183
  54. data/ext/libsass/src/parser.hpp +19 -9
  55. data/ext/libsass/src/plugins.cpp +1 -0
  56. data/ext/libsass/src/position.cpp +1 -0
  57. data/ext/libsass/src/prelexer.cpp +134 -56
  58. data/ext/libsass/src/prelexer.hpp +51 -3
  59. data/ext/libsass/src/remove_placeholders.cpp +35 -9
  60. data/ext/libsass/src/remove_placeholders.hpp +4 -3
  61. data/ext/libsass/src/sass.cpp +1 -0
  62. data/ext/libsass/src/sass.hpp +129 -0
  63. data/ext/libsass/src/sass_context.cpp +31 -14
  64. data/ext/libsass/src/sass_context.hpp +2 -31
  65. data/ext/libsass/src/sass_functions.cpp +1 -0
  66. data/ext/libsass/src/sass_interface.cpp +5 -6
  67. data/ext/libsass/src/sass_util.cpp +1 -2
  68. data/ext/libsass/src/sass_util.hpp +5 -5
  69. data/ext/libsass/src/sass_values.cpp +13 -10
  70. data/ext/libsass/src/source_map.cpp +4 -3
  71. data/ext/libsass/src/source_map.hpp +2 -2
  72. data/ext/libsass/src/subset_map.hpp +0 -1
  73. data/ext/libsass/src/to_c.cpp +1 -0
  74. data/ext/libsass/src/to_c.hpp +1 -3
  75. data/ext/libsass/src/to_value.cpp +3 -5
  76. data/ext/libsass/src/to_value.hpp +1 -1
  77. data/ext/libsass/src/units.cpp +96 -59
  78. data/ext/libsass/src/units.hpp +10 -8
  79. data/ext/libsass/src/utf8_string.cpp +5 -0
  80. data/ext/libsass/src/util.cpp +23 -156
  81. data/ext/libsass/src/util.hpp +10 -14
  82. data/ext/libsass/src/values.cpp +1 -0
  83. data/ext/libsass/test/test_node.cpp +2 -6
  84. data/ext/libsass/test/test_selector_difference.cpp +1 -3
  85. data/ext/libsass/test/test_specificity.cpp +0 -2
  86. data/ext/libsass/test/test_superselector.cpp +0 -2
  87. data/ext/libsass/test/test_unification.cpp +1 -3
  88. data/ext/libsass/win/libsass.targets +18 -5
  89. data/ext/libsass/win/libsass.vcxproj +9 -7
  90. data/ext/libsass/win/libsass.vcxproj.filters +148 -106
  91. data/lib/sassc/version.rb +1 -1
  92. data/test/engine_test.rb +12 -0
  93. data/test/native_test.rb +1 -1
  94. metadata +3 -4
  95. data/ext/libsass/src/to_string.cpp +0 -48
  96. data/ext/libsass/src/to_string.hpp +0 -38
@@ -1,6 +1,7 @@
1
1
  #ifndef SASS_FUNCTIONS_H
2
2
  #define SASS_FUNCTIONS_H
3
3
 
4
+ #include "listize.hpp"
4
5
  #include "position.hpp"
5
6
  #include "environment.hpp"
6
7
  #include "sass/functions.h"
@@ -1,3 +1,4 @@
1
+ #include "sass.hpp"
1
2
  #include <cmath>
2
3
  #include <string>
3
4
  #include <iostream>
@@ -26,11 +27,11 @@ namespace Sass {
26
27
  add_open_mapping(block);
27
28
  append_scope_opener();
28
29
  }
29
- if (output_style() == SASS_STYLE_NESTED) indentation += block->tabs();
30
+ if (output_style() == NESTED) indentation += block->tabs();
30
31
  for (size_t i = 0, L = block->length(); i < L; ++i) {
31
32
  (*block)[i]->perform(this);
32
33
  }
33
- if (output_style() == SASS_STYLE_NESTED) indentation -= block->tabs();
34
+ if (output_style() == NESTED) indentation -= block->tabs();
34
35
  if (!block->is_root()) {
35
36
  append_scope_closer();
36
37
  add_close_mapping(block);
@@ -123,14 +124,15 @@ namespace Sass {
123
124
  if (dec->value()->concrete_type() == Expression::NULL_VAL) return;
124
125
  bool was_decl = in_declaration;
125
126
  in_declaration = true;
126
- if (output_style() == SASS_STYLE_NESTED)
127
+ if (output_style() == NESTED)
127
128
  indentation += dec->tabs();
128
129
  append_indentation();
129
130
  dec->property()->perform(this);
130
131
  append_colon_separator();
131
132
 
132
133
  if (dec->value()->concrete_type() == Expression::SELECTOR) {
133
- Listize listize(*ctx);
134
+ Memory_Manager mem;
135
+ Listize listize(mem);
134
136
  dec->value()->perform(&listize)->perform(this);
135
137
  } else {
136
138
  dec->value()->perform(this);
@@ -141,7 +143,7 @@ namespace Sass {
141
143
  append_string("!important");
142
144
  }
143
145
  append_delimiter();
144
- if (output_style() == SASS_STYLE_NESTED)
146
+ if (output_style() == NESTED)
145
147
  indentation -= dec->tabs();
146
148
  in_declaration = was_decl;
147
149
  }
@@ -169,9 +171,11 @@ namespace Sass {
169
171
  }
170
172
 
171
173
  import->urls().front()->perform(this);
172
- if (import->media_queries()) {
173
- append_mandatory_space();
174
- import->media_queries()->perform(this);
174
+ if (import->urls().size() == 1) {
175
+ if (import->media_queries()) {
176
+ append_mandatory_space();
177
+ import->media_queries()->perform(this);
178
+ }
175
179
  }
176
180
  append_delimiter();
177
181
  for (size_t i = 1, S = import->urls().size(); i < S; ++i) {
@@ -184,9 +188,11 @@ namespace Sass {
184
188
  }
185
189
 
186
190
  import->urls()[i]->perform(this);
187
- if (import->media_queries()) {
188
- append_mandatory_space();
189
- import->media_queries()->perform(this);
191
+ if (import->urls().size() - 1 == i) {
192
+ if (import->media_queries()) {
193
+ append_mandatory_space();
194
+ import->media_queries()->perform(this);
195
+ }
190
196
  }
191
197
  append_delimiter();
192
198
  }
@@ -346,6 +352,10 @@ namespace Sass {
346
352
 
347
353
  void Inspect::operator()(Map* map)
348
354
  {
355
+ if (output_style() == TO_SASS && map->empty()) {
356
+ append_string("()");
357
+ return;
358
+ }
349
359
  if (map->empty()) return;
350
360
  if (map->is_invisible()) return;
351
361
  bool items_output = false;
@@ -362,15 +372,25 @@ namespace Sass {
362
372
 
363
373
  void Inspect::operator()(List* list)
364
374
  {
375
+ if (output_style() == TO_SASS && list->empty()) {
376
+ append_string("()");
377
+ return;
378
+ }
365
379
  std::string sep(list->separator() == SASS_SPACE ? " " : ",");
366
- if ((output_style() != SASS_STYLE_COMPRESSED || in_debug) && sep == ",") sep += " ";
380
+ if ((output_style() != COMPRESSED) && sep == ",") sep += " ";
367
381
  else if (in_media_block && sep != " ") sep += " "; // verified
368
382
  if (list->empty()) return;
369
383
  bool items_output = false;
370
384
 
371
385
  bool was_space_array = in_space_array;
372
386
  bool was_comma_array = in_comma_array;
373
- if (!in_declaration && (
387
+ // probably ruby sass eqivalent of element_needs_parens
388
+ if (output_style() == TO_SASS && list->length() == 1 &&
389
+ (!dynamic_cast<List*>((*list)[0]) &&
390
+ !dynamic_cast<Selector_List*>((*list)[0]))) {
391
+ append_string("(");
392
+ }
393
+ else if (!in_declaration && (list->separator() == SASS_HASH ||
374
394
  (list->separator() == SASS_SPACE && in_space_array) ||
375
395
  (list->separator() == SASS_COMMA && in_comma_array)
376
396
  )) {
@@ -381,9 +401,13 @@ namespace Sass {
381
401
  else if (list->separator() == SASS_COMMA) in_comma_array = true;
382
402
 
383
403
  for (size_t i = 0, L = list->size(); i < L; ++i) {
404
+ if (list->separator() == SASS_HASH)
405
+ { sep[0] = i % 2 ? ':' : ','; }
384
406
  Expression* list_item = (*list)[i];
385
- if (list_item->is_invisible()) {
386
- continue;
407
+ if (output_style() != TO_SASS) {
408
+ if (list_item->is_invisible()) {
409
+ continue;
410
+ }
387
411
  }
388
412
  if (items_output) {
389
413
  append_string(sep);
@@ -396,7 +420,13 @@ namespace Sass {
396
420
 
397
421
  in_comma_array = was_comma_array;
398
422
  in_space_array = was_space_array;
399
- if (!in_declaration && (
423
+ // probably ruby sass eqivalent of element_needs_parens
424
+ if (output_style() == TO_SASS && list->length() == 1 &&
425
+ (!dynamic_cast<List*>((*list)[0]) &&
426
+ !dynamic_cast<Selector_List*>((*list)[0]))) {
427
+ append_string(",)");
428
+ }
429
+ else if (!in_declaration && (list->separator() == SASS_HASH ||
400
430
  (list->separator() == SASS_SPACE && in_space_array) ||
401
431
  (list->separator() == SASS_COMMA && in_comma_array)
402
432
  )) {
@@ -408,22 +438,41 @@ namespace Sass {
408
438
  void Inspect::operator()(Binary_Expression* expr)
409
439
  {
410
440
  expr->left()->perform(this);
441
+ if ( in_media_block ||
442
+ (output_style() == INSPECT) || (
443
+ expr->op().ws_before
444
+ && (!expr->is_interpolant())
445
+ && (!expr->is_delayed() ||
446
+ expr->is_left_interpolant() ||
447
+ expr->is_right_interpolant()
448
+ )
449
+
450
+ )) append_string(" ");
411
451
  switch (expr->type()) {
412
- case Sass_OP::AND: append_string(" and "); break;
413
- case Sass_OP::OR: append_string(" or "); break;
414
- case Sass_OP::EQ: append_string(" == "); break;
415
- case Sass_OP::NEQ: append_string(" != "); break;
416
- case Sass_OP::GT: append_string(" > "); break;
417
- case Sass_OP::GTE: append_string(" >= "); break;
418
- case Sass_OP::LT: append_string(" < "); break;
419
- case Sass_OP::LTE: append_string(" <= "); break;
420
- case Sass_OP::ADD: append_string(" + "); break;
421
- case Sass_OP::SUB: append_string(" - "); break;
422
- case Sass_OP::MUL: append_string(" * "); break;
423
- case Sass_OP::DIV: append_string(in_media_block ? " / " : "/"); break;
424
- case Sass_OP::MOD: append_string(" % "); break;
452
+ case Sass_OP::AND: append_string("&&"); break;
453
+ case Sass_OP::OR: append_string("||"); break;
454
+ case Sass_OP::EQ: append_string("=="); break;
455
+ case Sass_OP::NEQ: append_string("!="); break;
456
+ case Sass_OP::GT: append_string(">"); break;
457
+ case Sass_OP::GTE: append_string(">="); break;
458
+ case Sass_OP::LT: append_string("<"); break;
459
+ case Sass_OP::LTE: append_string("<="); break;
460
+ case Sass_OP::ADD: append_string("+"); break;
461
+ case Sass_OP::SUB: append_string("-"); break;
462
+ case Sass_OP::MUL: append_string("*"); break;
463
+ case Sass_OP::DIV: append_string("/"); break;
464
+ case Sass_OP::MOD: append_string("%"); break;
425
465
  default: break; // shouldn't get here
426
466
  }
467
+ if ( in_media_block ||
468
+ (output_style() == INSPECT) || (
469
+ expr->op().ws_after
470
+ && (!expr->is_interpolant())
471
+ && (!expr->is_delayed()
472
+ || expr->is_left_interpolant()
473
+ || expr->is_right_interpolant()
474
+ )
475
+ )) append_string(" ");
427
476
  expr->right()->perform(this);
428
477
  }
429
478
 
@@ -458,29 +507,187 @@ namespace Sass {
458
507
 
459
508
  void Inspect::operator()(Number* n)
460
509
  {
461
- // use values to_string facility
462
- bool compressed = ctx->output_style() == SASS_STYLE_COMPRESSED;
463
- std::string res(n->to_string(compressed, (int)ctx->c_options->precision));
510
+
511
+ std::string res;
512
+
513
+ // check if the fractional part of the value equals to zero
514
+ // neat trick from http://stackoverflow.com/a/1521682/1550314
515
+ // double int_part; bool is_int = modf(value, &int_part) == 0.0;
516
+
517
+ // this all cannot be done with one run only, since fixed
518
+ // output differs from normal output and regular output
519
+ // can contain scientific notation which we do not want!
520
+
521
+ // first sample
522
+ std::stringstream ss;
523
+ ss.precision(12);
524
+ ss << n->value();
525
+
526
+ // check if we got scientific notation in result
527
+ if (ss.str().find_first_of("e") != std::string::npos) {
528
+ ss.clear(); ss.str(std::string());
529
+ ss.precision(std::max(12, opt.precision));
530
+ ss << std::fixed << n->value();
531
+ }
532
+
533
+ std::string tmp = ss.str();
534
+ size_t pos_point = tmp.find_first_of(".,");
535
+ size_t pos_fract = tmp.find_last_not_of("0");
536
+ bool is_int = pos_point == pos_fract ||
537
+ pos_point == std::string::npos;
538
+
539
+ // reset stream for another run
540
+ ss.clear(); ss.str(std::string());
541
+
542
+ // take a shortcut for integers
543
+ if (is_int)
544
+ {
545
+ ss.precision(0);
546
+ ss << std::fixed << n->value();
547
+ res = std::string(ss.str());
548
+ }
549
+ // process floats
550
+ else
551
+ {
552
+ // do we have have too much precision?
553
+ if (pos_fract < opt.precision + pos_point)
554
+ { ss.precision((int)(pos_fract - pos_point)); }
555
+ else { ss.precision(opt.precision); }
556
+ // round value again
557
+ ss << std::fixed << n->value();
558
+ res = std::string(ss.str());
559
+ // maybe we truncated up to decimal point
560
+ size_t pos = res.find_last_not_of("0");
561
+ // handle case where we have a "0"
562
+ if (pos == std::string::npos) {
563
+ res = "0.0";
564
+ } else {
565
+ bool at_dec_point = res[pos] == '.' ||
566
+ res[pos] == ',';
567
+ // don't leave a blank point
568
+ if (at_dec_point) ++ pos;
569
+ res.resize (pos + 1);
570
+ }
571
+ }
572
+
573
+ // some final cosmetics
574
+ if (res == "0.0") res = "0";
575
+ else if (res == "") res = "0";
576
+ else if (res == "-0") res = "0";
577
+ else if (res == "-0.0") res = "0";
578
+ else if (opt.output_style == COMPRESSED)
579
+ {
580
+ // check if handling negative nr
581
+ size_t off = res[0] == '-' ? 1 : 0;
582
+ // remove leading zero from floating point in compressed mode
583
+ if (n->zero() && res[off] == '0' && res[off+1] == '.') res.erase(off, 1);
584
+ }
585
+
586
+ // add unit now
587
+ res += n->unit();
588
+
464
589
  // output the final token
465
590
  append_token(res, n);
466
591
  }
467
592
 
593
+ // helper function for serializing colors
594
+ template <size_t range>
595
+ static double cap_channel(double c) {
596
+ if (c > range) return range;
597
+ else if (c < 0) return 0;
598
+ else return c;
599
+ }
600
+
468
601
  void Inspect::operator()(Color* c)
469
602
  {
470
- // use values to_string facility
471
- bool compressed = ctx->output_style() == SASS_STYLE_COMPRESSED;
472
- std::string res(c->to_string(compressed, (int)ctx->c_options->precision));
473
603
  // output the final token
474
- append_token(res, c);
604
+ std::stringstream ss;
605
+
606
+ // original color name
607
+ // maybe an unknown token
608
+ std::string name = c->disp();
609
+
610
+ // resolved color
611
+ std::string res_name = name;
612
+
613
+ double r = Sass::round(cap_channel<0xff>(c->r()), opt.precision);
614
+ double g = Sass::round(cap_channel<0xff>(c->g()), opt.precision);
615
+ double b = Sass::round(cap_channel<0xff>(c->b()), opt.precision);
616
+ double a = cap_channel<1> (c->a());
617
+
618
+ // get color from given name (if one was given at all)
619
+ if (name != "" && name_to_color(name)) {
620
+ const Color* n = name_to_color(name);
621
+ r = Sass::round(cap_channel<0xff>(n->r()), opt.precision);
622
+ g = Sass::round(cap_channel<0xff>(n->g()), opt.precision);
623
+ b = Sass::round(cap_channel<0xff>(n->b()), opt.precision);
624
+ a = cap_channel<1> (n->a());
625
+ }
626
+ // otherwise get the possible resolved color name
627
+ else {
628
+ double numval = r * 0x10000 + g * 0x100 + b;
629
+ if (color_to_name(numval))
630
+ res_name = color_to_name(numval);
631
+ }
632
+
633
+ std::stringstream hexlet;
634
+ bool compressed = opt.output_style == COMPRESSED;
635
+ hexlet << '#' << std::setw(1) << std::setfill('0');
636
+ // create a short color hexlet if there is any need for it
637
+ if (compressed && is_color_doublet(r, g, b) && a == 1) {
638
+ hexlet << std::hex << std::setw(1) << (static_cast<unsigned long>(r) >> 4);
639
+ hexlet << std::hex << std::setw(1) << (static_cast<unsigned long>(g) >> 4);
640
+ hexlet << std::hex << std::setw(1) << (static_cast<unsigned long>(b) >> 4);
641
+ } else {
642
+ hexlet << std::hex << std::setw(2) << static_cast<unsigned long>(r);
643
+ hexlet << std::hex << std::setw(2) << static_cast<unsigned long>(g);
644
+ hexlet << std::hex << std::setw(2) << static_cast<unsigned long>(b);
645
+ }
646
+
647
+ if (compressed && !c->is_delayed()) name = "";
648
+ if (opt.output_style == INSPECT && a >= 1) {
649
+ append_token(hexlet.str(), c);
650
+ return;
651
+ }
652
+
653
+ // retain the originally specified color definition if unchanged
654
+ if (name != "") {
655
+ ss << name;
656
+ }
657
+ else if (r == 0 && g == 0 && b == 0 && a == 0) {
658
+ ss << "transparent";
659
+ }
660
+ else if (a >= 1) {
661
+ if (res_name != "") {
662
+ if (compressed && hexlet.str().size() < res_name.size()) {
663
+ ss << hexlet.str();
664
+ } else {
665
+ ss << res_name;
666
+ }
667
+ }
668
+ else {
669
+ ss << hexlet.str();
670
+ }
671
+ }
672
+ else {
673
+ ss << "rgba(";
674
+ ss << static_cast<unsigned long>(r) << ",";
675
+ if (!compressed) ss << " ";
676
+ ss << static_cast<unsigned long>(g) << ",";
677
+ if (!compressed) ss << " ";
678
+ ss << static_cast<unsigned long>(b) << ",";
679
+ if (!compressed) ss << " ";
680
+ ss << a << ')';
681
+ }
682
+
683
+ append_token(ss.str(), c);
684
+
475
685
  }
476
686
 
477
687
  void Inspect::operator()(Boolean* b)
478
688
  {
479
- // use values to_string facility
480
- bool compressed = ctx->output_style() == SASS_STYLE_COMPRESSED;
481
- std::string res(b->to_string(compressed, (int)ctx->c_options->precision));
482
689
  // output the final token
483
- append_token(res, b);
690
+ append_token(b->value() ? "true" : "false", b);
484
691
  }
485
692
 
486
693
  void Inspect::operator()(String_Schema* ss)
@@ -496,25 +703,28 @@ namespace Sass {
496
703
 
497
704
  void Inspect::operator()(String_Constant* s)
498
705
  {
499
- // get options from optional? context
500
- int precision = ctx ? (int)ctx->c_options->precision : 5;
501
- bool compressed = ctx ? ctx->output_style() == SASS_STYLE_COMPRESSED : false;
502
- // use values to_string facility
503
- std::string res(s->to_string(compressed, precision));
504
- // output the final token
505
- append_token(res, s);
706
+ append_token(s->value(), s);
506
707
  }
507
708
 
508
709
  void Inspect::operator()(String_Quoted* s)
509
710
  {
510
- // get options from optional? context
511
- int precision = ctx ? (int)ctx->c_options->precision : 5;
512
- bool compressed = ctx ? ctx->output_style() == SASS_STYLE_COMPRESSED : false;
513
- // use values to_string facility
514
- std::string res(s->to_string(compressed, precision));
515
- // output the final token
516
- append_token(res, s);
711
+ if (const char q = s->quote_mark()) {
712
+ append_token(quote(s->value(), q), s);
713
+ } else {
714
+ append_token(s->value(), s);
715
+ }
716
+ }
717
+
718
+ void Inspect::operator()(Custom_Error* e)
719
+ {
720
+ append_token(e->message(), e);
517
721
  }
722
+
723
+ void Inspect::operator()(Custom_Warning* w)
724
+ {
725
+ append_token(w->message(), w);
726
+ }
727
+
518
728
  void Inspect::operator()(Supports_Operator* so)
519
729
  {
520
730
 
@@ -611,11 +821,8 @@ namespace Sass {
611
821
 
612
822
  void Inspect::operator()(Null* n)
613
823
  {
614
- // use values to_string facility
615
- bool compressed = output_style() == SASS_STYLE_COMPRESSED;
616
- std::string res(n->to_string(compressed, (int)ctx->c_options->precision));
617
824
  // output the final token
618
- append_token(res, n);
825
+ append_token("null", n);
619
826
  }
620
827
 
621
828
  // parameters and arguments
@@ -752,7 +959,7 @@ namespace Sass {
752
959
  (*s)[i]->perform(this);
753
960
  }
754
961
  if (s->has_line_break()) {
755
- if (output_style() != SASS_STYLE_COMPACT) {
962
+ if (output_style() != COMPACT) {
756
963
  append_optional_linefeed();
757
964
  }
758
965
  }
@@ -774,7 +981,7 @@ namespace Sass {
774
981
  if (head && head->length() != 0) head->perform(this);
775
982
  bool is_empty = !head || head->length() == 0 || head->is_empty_reference();
776
983
  bool is_tail = head && !head->is_empty_reference() && tail;
777
- if (output_style() == SASS_STYLE_COMPRESSED && comb != Complex_Selector::ANCESTOR_OF) scheduled_space = 0;
984
+ if (output_style() == COMPRESSED && comb != Complex_Selector::ANCESTOR_OF) scheduled_space = 0;
778
985
 
779
986
  switch (comb) {
780
987
  case Complex_Selector::ANCESTOR_OF:
@@ -810,7 +1017,7 @@ namespace Sass {
810
1017
  }
811
1018
  if (tail) tail->perform(this);
812
1019
  if (!tail && c->has_line_break()) {
813
- if (output_style() == SASS_STYLE_COMPACT) {
1020
+ if (output_style() == COMPACT) {
814
1021
  append_mandatory_space();
815
1022
  }
816
1023
  }
@@ -818,10 +1025,23 @@ namespace Sass {
818
1025
 
819
1026
  void Inspect::operator()(Selector_List* g)
820
1027
  {
821
- if (g->empty()) return;
1028
+
1029
+ if (g->empty()) {
1030
+ if (output_style() == TO_SASS) {
1031
+ append_token("()", g);
1032
+ }
1033
+ return;
1034
+ }
1035
+
822
1036
 
823
1037
  bool was_comma_array = in_comma_array;
824
- if (!in_declaration && in_comma_array) {
1038
+ // probably ruby sass eqivalent of element_needs_parens
1039
+ if (output_style() == TO_SASS && g->length() == 1 &&
1040
+ (!dynamic_cast<List*>((*g)[0]) &&
1041
+ !dynamic_cast<Selector_List*>((*g)[0]))) {
1042
+ append_string("(");
1043
+ }
1044
+ else if (!in_declaration && in_comma_array) {
825
1045
  append_string("(");
826
1046
  }
827
1047
 
@@ -830,7 +1050,10 @@ namespace Sass {
830
1050
  for (size_t i = 0, L = g->length(); i < L; ++i) {
831
1051
  if (!in_wrapped && i == 0) append_indentation();
832
1052
  if ((*g)[i] == 0) continue;
1053
+ schedule_mapping((*g)[i]->last());
1054
+ // add_open_mapping((*g)[i]->last());
833
1055
  (*g)[i]->perform(this);
1056
+ // add_close_mapping((*g)[i]->last());
834
1057
  if (i < L - 1) {
835
1058
  scheduled_space = 0;
836
1059
  append_comma_separator();
@@ -838,7 +1061,13 @@ namespace Sass {
838
1061
  }
839
1062
 
840
1063
  in_comma_array = was_comma_array;
841
- if (!in_declaration && in_comma_array) {
1064
+ // probably ruby sass eqivalent of element_needs_parens
1065
+ if (output_style() == TO_SASS && g->length() == 1 &&
1066
+ (!dynamic_cast<List*>((*g)[0]) &&
1067
+ !dynamic_cast<Selector_List*>((*g)[0]))) {
1068
+ append_string(",)");
1069
+ }
1070
+ else if (!in_declaration && in_comma_array) {
842
1071
  append_string(")");
843
1072
  }
844
1073