sassc 1.8.3 → 1.8.4

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 (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