sassc 1.10.1 → 1.11.0

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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -2
  3. data/ext/libsass/.github/CONTRIBUTING.md +65 -0
  4. data/ext/libsass/.github/ISSUE_TEMPLATE.md +29 -0
  5. data/ext/libsass/Makefile +8 -3
  6. data/ext/libsass/Makefile.conf +28 -22
  7. data/ext/libsass/Readme.md +14 -7
  8. data/ext/libsass/configure.ac +5 -8
  9. data/ext/libsass/docs/api-context-internal.md +3 -0
  10. data/ext/libsass/docs/api-context.md +7 -0
  11. data/ext/libsass/docs/api-doc.md +4 -0
  12. data/ext/libsass/docs/api-importer.md +2 -0
  13. data/ext/libsass/docs/api-value-example.md +55 -0
  14. data/ext/libsass/docs/api-value.md +49 -22
  15. data/ext/libsass/docs/implementations.md +4 -0
  16. data/ext/libsass/include/sass/base.h +5 -4
  17. data/ext/libsass/include/sass/context.h +3 -0
  18. data/ext/libsass/include/sass/values.h +28 -27
  19. data/ext/libsass/include/sass/version.h +1 -1
  20. data/ext/libsass/include/sass2scss.h +1 -1
  21. data/ext/libsass/script/ci-build-libsass +3 -3
  22. data/ext/libsass/script/ci-install-deps +12 -3
  23. data/ext/libsass/src/ast.cpp +321 -212
  24. data/ext/libsass/src/ast.hpp +273 -165
  25. data/ext/libsass/src/ast_factory.hpp +4 -5
  26. data/ext/libsass/src/ast_fwd_decl.hpp +8 -7
  27. data/ext/libsass/src/bind.cpp +2 -7
  28. data/ext/libsass/src/bind.hpp +0 -1
  29. data/ext/libsass/src/check_nesting.cpp +379 -0
  30. data/ext/libsass/src/check_nesting.hpp +60 -0
  31. data/ext/libsass/src/constants.cpp +7 -6
  32. data/ext/libsass/src/constants.hpp +2 -1
  33. data/ext/libsass/src/context.cpp +7 -1
  34. data/ext/libsass/src/context.hpp +1 -1
  35. data/ext/libsass/src/cssize.cpp +76 -32
  36. data/ext/libsass/src/cssize.hpp +7 -8
  37. data/ext/libsass/src/debugger.hpp +70 -40
  38. data/ext/libsass/src/error_handling.cpp +15 -2
  39. data/ext/libsass/src/error_handling.hpp +19 -0
  40. data/ext/libsass/src/eval.cpp +107 -161
  41. data/ext/libsass/src/eval.hpp +12 -8
  42. data/ext/libsass/src/expand.cpp +81 -74
  43. data/ext/libsass/src/expand.hpp +13 -12
  44. data/ext/libsass/src/extend.cpp +149 -142
  45. data/ext/libsass/src/extend.hpp +10 -3
  46. data/ext/libsass/src/file.cpp +2 -1
  47. data/ext/libsass/src/functions.cpp +96 -59
  48. data/ext/libsass/src/functions.hpp +2 -2
  49. data/ext/libsass/src/inspect.cpp +33 -45
  50. data/ext/libsass/src/inspect.hpp +7 -7
  51. data/ext/libsass/src/json.cpp +17 -5
  52. data/ext/libsass/src/lexer.cpp +3 -3
  53. data/ext/libsass/src/listize.cpp +10 -10
  54. data/ext/libsass/src/listize.hpp +3 -3
  55. data/ext/libsass/src/node.cpp +30 -30
  56. data/ext/libsass/src/node.hpp +13 -13
  57. data/ext/libsass/src/operation.hpp +21 -19
  58. data/ext/libsass/src/output.cpp +48 -103
  59. data/ext/libsass/src/output.hpp +0 -1
  60. data/ext/libsass/src/parser.cpp +161 -133
  61. data/ext/libsass/src/parser.hpp +10 -7
  62. data/ext/libsass/src/remove_placeholders.cpp +6 -6
  63. data/ext/libsass/src/remove_placeholders.hpp +1 -1
  64. data/ext/libsass/src/sass.cpp +21 -0
  65. data/ext/libsass/src/sass.hpp +8 -1
  66. data/ext/libsass/src/sass2scss.cpp +14 -3
  67. data/ext/libsass/src/sass_context.cpp +69 -24
  68. data/ext/libsass/src/sass_context.hpp +3 -0
  69. data/ext/libsass/src/source_map.cpp +22 -10
  70. data/ext/libsass/src/to_value.cpp +2 -2
  71. data/ext/libsass/src/to_value.hpp +1 -1
  72. data/ext/libsass/src/units.hpp +3 -1
  73. data/ext/libsass/src/util.cpp +20 -16
  74. data/ext/libsass/src/util.hpp +2 -1
  75. data/ext/libsass/win/libsass.targets +2 -0
  76. data/ext/libsass/win/libsass.vcxproj.filters +6 -0
  77. data/lib/sassc/engine.rb +5 -0
  78. data/lib/sassc/native/native_functions_api.rb +13 -1
  79. data/lib/sassc/script/value_conversion.rb +11 -1
  80. data/lib/sassc/script/value_conversion/list.rb +23 -0
  81. data/lib/sassc/version.rb +1 -1
  82. data/test/engine_test.rb +18 -2
  83. data/test/functions_test.rb +30 -0
  84. data/test/native_test.rb +1 -1
  85. metadata +8 -3
@@ -51,7 +51,7 @@ namespace Sass {
51
51
  static Parser from_c_str(const char* beg, const char* end, Context& ctx, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0);
52
52
  static Parser from_token(Token t, Context& ctx, ParserState pstate = ParserState("[TOKEN]"), const char* source = 0);
53
53
  // special static parsers to convert strings into certain selectors
54
- static Selector_List* parse_selector(const char* src, Context& ctx, ParserState pstate = ParserState("[SELECTOR]"), const char* source = 0);
54
+ static CommaSequence_Selector* parse_selector(const char* src, Context& ctx, ParserState pstate = ParserState("[SELECTOR]"), const char* source = 0);
55
55
 
56
56
  #ifdef __clang__
57
57
 
@@ -66,6 +66,10 @@ namespace Sass {
66
66
  #endif
67
67
 
68
68
 
69
+ // skip current token and next whitespace
70
+ // moves ParserState right before next token
71
+ void advanceToNextToken();
72
+
69
73
  bool peek_newline(const char* start = 0);
70
74
 
71
75
  // skip over spaces, tabs and line comments
@@ -236,12 +240,11 @@ namespace Sass {
236
240
  Arguments* parse_arguments();
237
241
  Argument* parse_argument();
238
242
  Assignment* parse_assignment();
239
- // Propset* parse_propset();
240
243
  Ruleset* parse_ruleset(Lookahead lookahead, bool is_root = false);
241
244
  Selector_Schema* parse_selector_schema(const char* end_of_selector);
242
- Selector_List* parse_selector_list(bool at_root = false);
243
- Complex_Selector* parse_complex_selector(bool in_root = true);
244
- Compound_Selector* parse_compound_selector();
245
+ CommaSequence_Selector* parse_selector_list(bool at_root = false);
246
+ Sequence_Selector* parse_complex_selector(bool in_root = true);
247
+ SimpleSequence_Selector* parse_compound_selector();
245
248
  Simple_Selector* parse_simple_selector();
246
249
  Wrapped_Selector* parse_negated_selector();
247
250
  Simple_Selector* parse_pseudo_selector();
@@ -255,8 +258,8 @@ namespace Sass {
255
258
  Declaration* parse_declaration();
256
259
  Expression* parse_map_value();
257
260
  Expression* parse_map();
258
- Expression* parse_list();
259
- Expression* parse_comma_list();
261
+ Expression* parse_list(bool delayed = false);
262
+ Expression* parse_comma_list(bool delayed = false);
260
263
  Expression* parse_space_list();
261
264
  Expression* parse_disjunction();
262
265
  Expression* parse_conjunction();
@@ -16,9 +16,9 @@ namespace Sass {
16
16
  }
17
17
  }
18
18
 
19
- Selector_List* Remove_Placeholders::remove_placeholders(Selector_List* sl)
19
+ CommaSequence_Selector* Remove_Placeholders::remove_placeholders(CommaSequence_Selector* sl)
20
20
  {
21
- Selector_List* new_sl = SASS_MEMORY_NEW(ctx.mem, Selector_List, sl->pstate());
21
+ CommaSequence_Selector* new_sl = SASS_MEMORY_NEW(ctx.mem, CommaSequence_Selector, sl->pstate());
22
22
 
23
23
  for (size_t i = 0, L = sl->length(); i < L; ++i) {
24
24
  if (!(*sl)[i]->contains_placeholder()) {
@@ -33,19 +33,19 @@ namespace Sass {
33
33
 
34
34
  void Remove_Placeholders::operator()(Ruleset* r) {
35
35
  // Create a new selector group without placeholders
36
- Selector_List* sl = static_cast<Selector_List*>(r->selector());
36
+ CommaSequence_Selector* sl = static_cast<CommaSequence_Selector*>(r->selector());
37
37
 
38
38
  if (sl) {
39
39
  // Set the new placeholder selector list
40
40
  r->selector(remove_placeholders(sl));
41
41
  // Remove placeholders in wrapped selectors
42
- for (Complex_Selector* cs : *sl) {
42
+ for (Sequence_Selector* cs : *sl) {
43
43
  while (cs) {
44
44
  if (cs->head()) {
45
45
  for (Simple_Selector* ss : *cs->head()) {
46
46
  if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(ss)) {
47
- if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
48
- Selector_List* clean = remove_placeholders(sl);
47
+ if (CommaSequence_Selector* sl = dynamic_cast<CommaSequence_Selector*>(ws->selector())) {
48
+ CommaSequence_Selector* clean = remove_placeholders(sl);
49
49
  // also clean superflous parent selectors
50
50
  // probably not really the correct place
51
51
  clean->remove_parent_selectors();
@@ -18,7 +18,7 @@ namespace Sass {
18
18
  void fallback_impl(AST_Node* n) {}
19
19
 
20
20
  public:
21
- Selector_List* remove_placeholders(Selector_List*);
21
+ CommaSequence_Selector* remove_placeholders(CommaSequence_Selector*);
22
22
 
23
23
  public:
24
24
  Remove_Placeholders(Context&);
@@ -70,3 +70,24 @@ extern "C" {
70
70
  }
71
71
 
72
72
  }
73
+
74
+ namespace Sass {
75
+
76
+ // helper to aid dreaded MSVC debug mode
77
+ char* sass_copy_string(std::string str)
78
+ {
79
+ // In MSVC the following can lead to segfault:
80
+ // sass_copy_c_string(stream.str().c_str());
81
+ // Reason is that the string returned by str() is disposed before
82
+ // sass_copy_c_string is invoked. The string is actually a stack
83
+ // object, so indeed nobody is holding on to it. So it seems
84
+ // perfectly fair to release it right away. So the const char*
85
+ // by c_str will point to invalid memory. I'm not sure if this is
86
+ // the behavior for all compiler, but I'm pretty sure we would
87
+ // have gotten more issues reported if that would be the case.
88
+ // Wrapping it in a functions seems the cleanest approach as the
89
+ // function must hold on to the stack variable until it's done.
90
+ return sass_copy_c_string(str.c_str());
91
+ }
92
+
93
+ }
@@ -45,6 +45,9 @@
45
45
  // include C-API header
46
46
  #include "sass/base.h"
47
47
 
48
+ // For C++ helper
49
+ #include <string>
50
+
48
51
  // output behaviours
49
52
  namespace Sass {
50
53
 
@@ -57,7 +60,11 @@ namespace Sass {
57
60
  const static Sass_Output_Style INSPECT = SASS_STYLE_INSPECT;
58
61
  const static Sass_Output_Style TO_SASS = SASS_STYLE_TO_SASS;
59
62
 
60
- };
63
+ // helper to aid dreaded MSVC debug mode
64
+ // see implementation for more details
65
+ char* sass_copy_string(std::string str);
66
+
67
+ }
61
68
 
62
69
  // input behaviours
63
70
  enum Sass_Input_Style {
@@ -574,6 +574,12 @@ namespace Sass
574
574
  }
575
575
  }
576
576
 
577
+ // check if we have a BEM property (one colon and no selector)
578
+ if (sass.substr(pos_left, 1) == ":" && converter.selector == true) {
579
+ size_t pos_wspace = sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left);
580
+ sass = indent + sass.substr(pos_left + 1, pos_wspace) + ":";
581
+ }
582
+
577
583
  }
578
584
 
579
585
  // terminate some statements immediately
@@ -584,10 +590,15 @@ namespace Sass
584
590
  sass.substr(pos_left, 8) == "@charset"
585
591
  ) { sass = indent + sass.substr(pos_left); }
586
592
  // replace some specific sass shorthand directives (if not fallowed by a white space character)
587
- else if (sass.substr(pos_left, 1) == "=" && sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left) != pos_left + 1)
593
+ else if (sass.substr(pos_left, 1) == "=")
588
594
  { sass = indent + "@mixin " + sass.substr(pos_left + 1); }
589
- else if (sass.substr(pos_left, 1) == "+" && sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left) != pos_left + 1)
590
- { sass = indent + "@include " + sass.substr(pos_left + 1); }
595
+ else if (sass.substr(pos_left, 1) == "+")
596
+ {
597
+ // must be followed by a mixin call (no whitespace afterwards or at ending directly)
598
+ if (sass[pos_left+1] != 0 && sass[pos_left+1] != ' ' && sass[pos_left+1] != '\t') {
599
+ sass = indent + "@include " + sass.substr(pos_left + 1);
600
+ }
601
+ }
591
602
 
592
603
  // add quotes for import if needed
593
604
  else if (sass.substr(pos_left, 7) == "@import")
@@ -17,10 +17,30 @@
17
17
 
18
18
  #define LFEED "\n"
19
19
 
20
+ // C++ helper
21
+ namespace Sass {
22
+ // see sass_copy_c_string(std::string str)
23
+ static inline JsonNode* json_mkstream(const std::stringstream& stream)
24
+ {
25
+ // hold on to string on stack!
26
+ std::string str(stream.str());
27
+ return json_mkstring(str.c_str());
28
+ }
29
+ }
30
+
20
31
  extern "C" {
21
32
  using namespace Sass;
22
33
 
23
- static void copy_options(struct Sass_Options* to, struct Sass_Options* from) { *to = *from; }
34
+ static void sass_clear_options (struct Sass_Options* options);
35
+ static void sass_reset_options (struct Sass_Options* options);
36
+ static void copy_options(struct Sass_Options* to, struct Sass_Options* from) {
37
+ // free assigned memory
38
+ sass_clear_options(to);
39
+ // move memory
40
+ *to = *from;
41
+ // Reset pointers on source
42
+ sass_reset_options(from);
43
+ }
24
44
 
25
45
  #define IMPLEMENT_SASS_OPTION_ACCESSOR(type, option) \
26
46
  type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return options->option; } \
@@ -103,10 +123,9 @@ extern "C" {
103
123
  json_append_member(json_err, "line", json_mknumber((double)(e.pstate.line+1)));
104
124
  json_append_member(json_err, "column", json_mknumber((double)(e.pstate.column+1)));
105
125
  json_append_member(json_err, "message", json_mkstring(e.what()));
106
- json_append_member(json_err, "formatted", json_mkstring(msg_stream.str().c_str()));
107
-
126
+ json_append_member(json_err, "formatted", json_mkstream(msg_stream));
108
127
  try { c_ctx->error_json = json_stringify(json_err, " "); } catch(...) {}
109
- c_ctx->error_message = sass_copy_c_string(msg_stream.str().c_str());
128
+ c_ctx->error_message = sass_copy_string(msg_stream.str());
110
129
  c_ctx->error_text = sass_copy_c_string(e.what());
111
130
  c_ctx->error_status = 1;
112
131
  c_ctx->error_file = sass_copy_c_string(e.pstate.path);
@@ -123,9 +142,9 @@ extern "C" {
123
142
  msg_stream << "Unable to allocate memory: " << ba.what() << std::endl;
124
143
  json_append_member(json_err, "status", json_mknumber(2));
125
144
  json_append_member(json_err, "message", json_mkstring(ba.what()));
126
- json_append_member(json_err, "formatted", json_mkstring(msg_stream.str().c_str()));
145
+ json_append_member(json_err, "formatted", json_mkstream(msg_stream));
127
146
  try { c_ctx->error_json = json_stringify(json_err, " "); } catch(...) {}
128
- c_ctx->error_message = sass_copy_c_string(msg_stream.str().c_str());
147
+ c_ctx->error_message = sass_copy_string(msg_stream.str());
129
148
  c_ctx->error_text = sass_copy_c_string(ba.what());
130
149
  c_ctx->error_status = 2;
131
150
  c_ctx->output_string = 0;
@@ -138,9 +157,9 @@ extern "C" {
138
157
  msg_stream << "Internal Error: " << e.what() << std::endl;
139
158
  json_append_member(json_err, "status", json_mknumber(3));
140
159
  json_append_member(json_err, "message", json_mkstring(e.what()));
141
- json_append_member(json_err, "formatted", json_mkstring(msg_stream.str().c_str()));
160
+ json_append_member(json_err, "formatted", json_mkstream(msg_stream));
142
161
  try { c_ctx->error_json = json_stringify(json_err, " "); } catch(...) {}
143
- c_ctx->error_message = sass_copy_c_string(msg_stream.str().c_str());
162
+ c_ctx->error_message = sass_copy_string(msg_stream.str());
144
163
  c_ctx->error_text = sass_copy_c_string(e.what());
145
164
  c_ctx->error_status = 3;
146
165
  c_ctx->output_string = 0;
@@ -153,9 +172,9 @@ extern "C" {
153
172
  msg_stream << "Internal Error: " << e << std::endl;
154
173
  json_append_member(json_err, "status", json_mknumber(4));
155
174
  json_append_member(json_err, "message", json_mkstring(e.c_str()));
156
- json_append_member(json_err, "formatted", json_mkstring(msg_stream.str().c_str()));
175
+ json_append_member(json_err, "formatted", json_mkstream(msg_stream));
157
176
  try { c_ctx->error_json = json_stringify(json_err, " "); } catch(...) {}
158
- c_ctx->error_message = sass_copy_c_string(msg_stream.str().c_str());
177
+ c_ctx->error_message = sass_copy_string(msg_stream.str());
159
178
  c_ctx->error_text = sass_copy_c_string(e.c_str());
160
179
  c_ctx->error_status = 4;
161
180
  c_ctx->output_string = 0;
@@ -168,9 +187,9 @@ extern "C" {
168
187
  msg_stream << "Internal Error: " << e << std::endl;
169
188
  json_append_member(json_err, "status", json_mknumber(4));
170
189
  json_append_member(json_err, "message", json_mkstring(e));
171
- json_append_member(json_err, "formatted", json_mkstring(msg_stream.str().c_str()));
190
+ json_append_member(json_err, "formatted", json_mkstream(msg_stream));
172
191
  try { c_ctx->error_json = json_stringify(json_err, " "); } catch(...) {}
173
- c_ctx->error_message = sass_copy_c_string(msg_stream.str().c_str());
192
+ c_ctx->error_message = sass_copy_string(msg_stream.str());
174
193
  c_ctx->error_text = sass_copy_c_string(e);
175
194
  c_ctx->error_status = 4;
176
195
  c_ctx->output_string = 0;
@@ -184,7 +203,7 @@ extern "C" {
184
203
  json_append_member(json_err, "status", json_mknumber(5));
185
204
  json_append_member(json_err, "message", json_mkstring("unknown"));
186
205
  try { c_ctx->error_json = json_stringify(json_err, " "); } catch(...) {}
187
- c_ctx->error_message = sass_copy_c_string(msg_stream.str().c_str());
206
+ c_ctx->error_message = sass_copy_string(msg_stream.str());
188
207
  c_ctx->error_text = sass_copy_c_string("unknown");
189
208
  c_ctx->error_status = 5;
190
209
  c_ctx->output_string = 0;
@@ -465,6 +484,24 @@ extern "C" {
465
484
  return 0;
466
485
  }
467
486
 
487
+ // helper function, not exported, only accessible locally
488
+ static void sass_reset_options (struct Sass_Options* options)
489
+ {
490
+ // free pointer before
491
+ // or copy/move them
492
+ options->input_path = 0;
493
+ options->output_path = 0;
494
+ options->plugin_path = 0;
495
+ options->include_path = 0;
496
+ options->source_map_file = 0;
497
+ options->source_map_root = 0;
498
+ options->c_functions = 0;
499
+ options->c_importers = 0;
500
+ options->c_headers = 0;
501
+ options->plugin_paths = 0;
502
+ options->include_paths = 0;
503
+ }
504
+
468
505
  // helper function, not exported, only accessible locally
469
506
  static void sass_clear_options (struct Sass_Options* options)
470
507
  {
@@ -517,12 +554,25 @@ extern "C" {
517
554
  cur = next;
518
555
  }
519
556
  }
557
+ // Free options strings
558
+ free(options->input_path);
559
+ free(options->output_path);
560
+ free(options->plugin_path);
561
+ free(options->include_path);
562
+ free(options->source_map_file);
563
+ free(options->source_map_root);
520
564
  // Free custom functions
521
565
  free(options->c_functions);
522
566
  // Free custom importers
523
567
  free(options->c_importers);
524
568
  free(options->c_headers);
525
569
  // Reset our pointers
570
+ options->input_path = 0;
571
+ options->output_path = 0;
572
+ options->plugin_path = 0;
573
+ options->include_path = 0;
574
+ options->source_map_file = 0;
575
+ options->source_map_root = 0;
526
576
  options->c_functions = 0;
527
577
  options->c_importers = 0;
528
578
  options->c_headers = 0;
@@ -542,12 +592,6 @@ extern "C" {
542
592
  if (ctx->error_text) free(ctx->error_text);
543
593
  if (ctx->error_json) free(ctx->error_json);
544
594
  if (ctx->error_file) free(ctx->error_file);
545
- if (ctx->input_path) free(ctx->input_path);
546
- if (ctx->output_path) free(ctx->output_path);
547
- if (ctx->plugin_path) free(ctx->plugin_path);
548
- if (ctx->include_path) free(ctx->include_path);
549
- if (ctx->source_map_file) free(ctx->source_map_file);
550
- if (ctx->source_map_root) free(ctx->source_map_root);
551
595
  free_string_array(ctx->included_files);
552
596
  // play safe and reset properties
553
597
  ctx->output_string = 0;
@@ -556,11 +600,6 @@ extern "C" {
556
600
  ctx->error_text = 0;
557
601
  ctx->error_json = 0;
558
602
  ctx->error_file = 0;
559
- ctx->input_path = 0;
560
- ctx->output_path = 0;
561
- ctx->include_path = 0;
562
- ctx->source_map_file = 0;
563
- ctx->source_map_root = 0;
564
603
  ctx->included_files = 0;
565
604
  // now clear the options
566
605
  sass_clear_options(ctx);
@@ -577,6 +616,11 @@ extern "C" {
577
616
  free(compiler);
578
617
  }
579
618
 
619
+ void ADDCALL sass_delete_options (struct Sass_Options* options)
620
+ {
621
+ sass_clear_options(options); free(options);
622
+ }
623
+
580
624
  // Deallocate all associated memory with file context
581
625
  void ADDCALL sass_delete_file_context (struct Sass_File_Context* ctx)
582
626
  {
@@ -623,6 +667,7 @@ extern "C" {
623
667
  IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_comments);
624
668
  IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_embed);
625
669
  IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_contents);
670
+ IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_file_urls);
626
671
  IMPLEMENT_SASS_OPTION_ACCESSOR(bool, omit_source_map_url);
627
672
  IMPLEMENT_SASS_OPTION_ACCESSOR(bool, is_indented_syntax_src);
628
673
  IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Function_List, c_functions);
@@ -15,6 +15,9 @@ struct Sass_Options : Sass_Output_Options {
15
15
  // embed include contents in maps
16
16
  bool source_map_contents;
17
17
 
18
+ // create file urls for sources
19
+ bool source_map_file_urls;
20
+
18
21
  // Disable sourceMappingUrl in css output
19
22
  bool omit_source_map_url;
20
23
 
@@ -25,20 +25,32 @@ namespace Sass {
25
25
 
26
26
  json_append_member(json_srcmap, "version", json_mknumber(3));
27
27
 
28
+ const char *include = file.c_str();
29
+ JsonNode *json_include = json_mkstring(include);
30
+ json_append_member(json_srcmap, "file", json_include);
31
+
28
32
  // pass-through sourceRoot option
29
33
  if (!ctx.source_map_root.empty()) {
30
34
  JsonNode* root = json_mkstring(ctx.source_map_root.c_str());
31
35
  json_append_member(json_srcmap, "sourceRoot", root);
32
36
  }
33
37
 
34
- const char *include = file.c_str();
35
- JsonNode *json_include = json_mkstring(include);
36
- json_append_member(json_srcmap, "file", json_include);
37
-
38
38
  JsonNode *json_includes = json_mkarray();
39
39
  for (size_t i = 0; i < source_index.size(); ++i) {
40
- const char *include = links[source_index[i]].c_str();
41
- JsonNode *json_include = json_mkstring(include);
40
+ std::string include(links[source_index[i]]);
41
+ if (ctx.c_options.source_map_file_urls) {
42
+ include = File::rel2abs(include);
43
+ // check for windows abs path
44
+ if (include[0] == '/') {
45
+ // ends up with three slashes
46
+ include = "file://" + include;
47
+ } else {
48
+ // needs an additional slash
49
+ include = "file:///" + include;
50
+ }
51
+ }
52
+ const char* inc = include.c_str();
53
+ JsonNode *json_include = json_mkstring(inc);
42
54
  json_append_element(json_includes, json_include);
43
55
  }
44
56
  json_append_member(json_srcmap, "sources", json_includes);
@@ -54,15 +66,15 @@ namespace Sass {
54
66
  json_append_member(json_srcmap, "sourcesContent", json_contents);
55
67
  }
56
68
 
57
- std::string mappings = serialize_mappings();
58
- JsonNode *json_mappings = json_mkstring(mappings.c_str());
59
- json_append_member(json_srcmap, "mappings", json_mappings);
60
-
61
69
  JsonNode *json_names = json_mkarray();
62
70
  // so far we have no implementation for names
63
71
  // no problem as we do not alter any identifiers
64
72
  json_append_member(json_srcmap, "names", json_names);
65
73
 
74
+ std::string mappings = serialize_mappings();
75
+ JsonNode *json_mappings = json_mkstring(mappings.c_str());
76
+ json_append_member(json_srcmap, "mappings", json_mappings);
77
+
66
78
  char *str = json_stringify(json_srcmap, "\t");
67
79
  std::string result = std::string(str);
68
80
  free(str);
@@ -88,8 +88,8 @@ namespace Sass {
88
88
  return arg->value()->perform(this);
89
89
  }
90
90
 
91
- // Selector_List is converted to a string
92
- Value* To_Value::operator()(Selector_List* s)
91
+ // CommaSequence_Selector is converted to a string
92
+ Value* To_Value::operator()(CommaSequence_Selector* s)
93
93
  {
94
94
  return SASS_MEMORY_NEW(mem, String_Quoted,
95
95
  s->pstate(),
@@ -37,7 +37,7 @@ namespace Sass {
37
37
  Value* operator()(Null*);
38
38
 
39
39
  // convert to string via `To_String`
40
- Value* operator()(Selector_List*);
40
+ Value* operator()(CommaSequence_Selector*);
41
41
  Value* operator()(Binary_Expression*);
42
42
 
43
43
  // fallback throws error