sassc 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/ext/libsass/.gitignore +13 -6
  4. data/ext/libsass/Makefile +42 -26
  5. data/ext/libsass/Makefile.am +43 -30
  6. data/ext/libsass/Readme.md +4 -2
  7. data/ext/libsass/appveyor.yml +10 -14
  8. data/ext/libsass/ast.cpp +54 -44
  9. data/ext/libsass/ast.hpp +404 -236
  10. data/ext/libsass/ast_def_macros.hpp +5 -0
  11. data/ext/libsass/ast_factory.hpp +6 -3
  12. data/ext/libsass/ast_fwd_decl.hpp +12 -0
  13. data/ext/libsass/b64/encode.h +2 -2
  14. data/ext/libsass/backtrace.hpp +13 -17
  15. data/ext/libsass/base64vlq.hpp +4 -1
  16. data/ext/libsass/bind.cpp +12 -15
  17. data/ext/libsass/bind.hpp +6 -6
  18. data/ext/libsass/color_names.hpp +4 -1
  19. data/ext/libsass/configure.ac +7 -21
  20. data/ext/libsass/constants.cpp +6 -4
  21. data/ext/libsass/constants.hpp +10 -4
  22. data/ext/libsass/context.cpp +89 -58
  23. data/ext/libsass/context.hpp +28 -35
  24. data/ext/libsass/contextualize.cpp +20 -10
  25. data/ext/libsass/contextualize.hpp +8 -23
  26. data/ext/libsass/contrib/libsass.spec +66 -0
  27. data/ext/libsass/cssize.cpp +547 -0
  28. data/ext/libsass/cssize.hpp +82 -0
  29. data/ext/libsass/debug.hpp +3 -3
  30. data/ext/libsass/debugger.hpp +358 -0
  31. data/ext/libsass/emitter.cpp +255 -0
  32. data/ext/libsass/emitter.hpp +83 -0
  33. data/ext/libsass/environment.hpp +7 -3
  34. data/ext/libsass/error_handling.cpp +11 -14
  35. data/ext/libsass/error_handling.hpp +9 -7
  36. data/ext/libsass/eval.cpp +253 -161
  37. data/ext/libsass/eval.hpp +13 -13
  38. data/ext/libsass/expand.cpp +135 -64
  39. data/ext/libsass/expand.hpp +11 -13
  40. data/ext/libsass/extend.cpp +66 -20
  41. data/ext/libsass/extend.hpp +6 -11
  42. data/ext/libsass/file.cpp +31 -26
  43. data/ext/libsass/file.hpp +6 -1
  44. data/ext/libsass/functions.cpp +270 -287
  45. data/ext/libsass/functions.hpp +8 -11
  46. data/ext/libsass/inspect.cpp +385 -255
  47. data/ext/libsass/inspect.hpp +15 -26
  48. data/ext/libsass/kwd_arg_macros.hpp +5 -0
  49. data/ext/libsass/mapping.hpp +4 -3
  50. data/ext/libsass/memory_manager.hpp +5 -2
  51. data/ext/libsass/node.cpp +50 -50
  52. data/ext/libsass/node.hpp +26 -27
  53. data/ext/libsass/operation.hpp +15 -4
  54. data/ext/libsass/output.cpp +401 -0
  55. data/ext/libsass/output.hpp +56 -0
  56. data/ext/libsass/parser.cpp +573 -399
  57. data/ext/libsass/parser.hpp +122 -88
  58. data/ext/libsass/paths.hpp +7 -2
  59. data/ext/libsass/plugins.cpp +155 -0
  60. data/ext/libsass/plugins.hpp +56 -0
  61. data/ext/libsass/position.cpp +128 -0
  62. data/ext/libsass/position.hpp +108 -11
  63. data/ext/libsass/prelexer.cpp +184 -110
  64. data/ext/libsass/prelexer.hpp +131 -24
  65. data/ext/libsass/remove_placeholders.cpp +1 -1
  66. data/ext/libsass/remove_placeholders.hpp +6 -6
  67. data/ext/libsass/sass.cpp +3 -3
  68. data/ext/libsass/sass.h +12 -4
  69. data/ext/libsass/sass2scss.cpp +3 -2
  70. data/ext/libsass/sass2scss.h +5 -0
  71. data/ext/libsass/sass_context.cpp +136 -37
  72. data/ext/libsass/sass_context.h +19 -10
  73. data/ext/libsass/sass_functions.cpp +29 -2
  74. data/ext/libsass/sass_functions.h +8 -2
  75. data/ext/libsass/sass_interface.cpp +32 -23
  76. data/ext/libsass/sass_interface.h +9 -4
  77. data/ext/libsass/sass_util.cpp +19 -23
  78. data/ext/libsass/sass_util.hpp +28 -27
  79. data/ext/libsass/sass_values.cpp +6 -4
  80. data/ext/libsass/sass_values.h +3 -3
  81. data/ext/libsass/script/ci-build-libsass +13 -1
  82. data/ext/libsass/script/ci-report-coverage +2 -1
  83. data/ext/libsass/source_map.cpp +79 -28
  84. data/ext/libsass/source_map.hpp +35 -16
  85. data/ext/libsass/subset_map.hpp +6 -4
  86. data/ext/libsass/to_c.hpp +4 -4
  87. data/ext/libsass/to_string.cpp +13 -8
  88. data/ext/libsass/to_string.hpp +6 -4
  89. data/ext/libsass/units.cpp +2 -1
  90. data/ext/libsass/units.hpp +6 -1
  91. data/ext/libsass/utf8_string.cpp +0 -5
  92. data/ext/libsass/utf8_string.hpp +3 -2
  93. data/ext/libsass/util.cpp +461 -49
  94. data/ext/libsass/util.hpp +34 -13
  95. data/ext/libsass/version.sh +10 -0
  96. data/ext/libsass/win/libsass.filters +20 -11
  97. data/ext/libsass/win/libsass.vcxproj +11 -8
  98. data/lib/sassc/importer.rb +1 -8
  99. data/lib/sassc/native.rb +7 -0
  100. data/lib/sassc/native/native_context_api.rb +5 -5
  101. data/lib/sassc/version.rb +1 -1
  102. data/test/native_test.rb +1 -1
  103. metadata +14 -10
  104. data/ext/libsass/copy_c_str.cpp +0 -13
  105. data/ext/libsass/copy_c_str.hpp +0 -5
  106. data/ext/libsass/output_compressed.cpp +0 -401
  107. data/ext/libsass/output_compressed.hpp +0 -95
  108. data/ext/libsass/output_nested.cpp +0 -364
  109. data/ext/libsass/output_nested.hpp +0 -108
  110. data/ext/libsass/test-driver +0 -127
  111. data/ext/libsass/token.hpp +0 -32
@@ -1,8 +1,9 @@
1
- #define SASS_SUBSET_MAP
1
+ #ifndef SASS_SUBSET_MAP_H
2
+ #define SASS_SUBSET_MAP_H
2
3
 
3
- #include <vector>
4
4
  #include <map>
5
5
  #include <set>
6
+ #include <vector>
6
7
  #include <algorithm>
7
8
  #include <iterator>
8
9
  #include <iostream>
@@ -81,6 +82,7 @@ namespace Sass {
81
82
  vector<V> get_v(const vector<K>& s);
82
83
  bool empty() { return values_.empty(); }
83
84
  void clear() { values_.clear(); hash_.clear(); }
85
+ const vector<V> values(void) { return values_; }
84
86
  };
85
87
 
86
88
  template<typename K, typename V>
@@ -106,9 +108,7 @@ namespace Sass {
106
108
  sort(sorted.begin(), sorted.end());
107
109
  vector<pair<size_t, vector<K> > > indices;
108
110
  for (size_t i = 0, S = s.size(); i < S; ++i) {
109
- // cerr << "looking for " << s[i] << endl;
110
111
  if (!hash_.count(s[i])) {
111
- // cerr << "didn't find " << s[i] << endl;
112
112
  continue;
113
113
  }
114
114
  vector<triple<vector<K>, set<K>, size_t> > subsets = hash_[s[i]];
@@ -143,3 +143,5 @@ namespace Sass {
143
143
  }
144
144
 
145
145
  }
146
+
147
+ #endif
@@ -1,9 +1,7 @@
1
- #define SASS_TO_C
1
+ #ifndef SASS_TO_C_H
2
+ #define SASS_TO_C_H
2
3
 
3
- #ifndef SASS_OPERATION
4
4
  #include "operation.hpp"
5
- #endif
6
-
7
5
  #include "sass_values.h"
8
6
 
9
7
  namespace Sass {
@@ -42,3 +40,5 @@ namespace Sass {
42
40
  };
43
41
 
44
42
  }
43
+
44
+ #endif
@@ -1,29 +1,34 @@
1
1
  #include <cmath>
2
2
  #include <sstream>
3
3
  #include <iomanip>
4
+ #include <iostream>
4
5
 
5
- #ifndef SASS_TO_STRING
6
- #include "to_string.hpp"
7
- #endif
8
-
9
- #include "inspect.hpp"
10
6
  #include "ast.hpp"
7
+ #include "inspect.hpp"
11
8
  #include "context.hpp"
12
- #include <iostream>
9
+ #include "to_string.hpp"
13
10
 
14
11
  namespace Sass {
15
12
  using namespace std;
16
13
 
17
- To_String::To_String(Context* ctx) : ctx(ctx) { }
14
+ To_String::To_String(Context* ctx)
15
+ : ctx(ctx) { }
18
16
  To_String::~To_String() { }
19
17
 
20
18
  inline string To_String::fallback_impl(AST_Node* n)
21
19
  {
22
- Inspect i(ctx);
20
+ Emitter emitter(ctx);
21
+ Inspect i(emitter);
22
+ i.in_declaration_list = true;
23
23
  n->perform(&i);
24
24
  return i.get_buffer();
25
25
  }
26
26
 
27
+ inline string To_String::operator()(String_Constant* s)
28
+ {
29
+ return s->value();
30
+ }
31
+
27
32
  inline string To_String::operator()(Null* n)
28
33
  { return ""; }
29
34
  }
@@ -1,15 +1,14 @@
1
- #define SASS_TO_STRING
1
+ #ifndef SASS_TO_STRING_H
2
+ #define SASS_TO_STRING_H
2
3
 
3
4
  #include <string>
4
5
 
5
- #ifndef SASS_OPERATION
6
6
  #include "operation.hpp"
7
- #endif
8
7
 
9
8
  namespace Sass {
10
9
  using namespace std;
11
10
 
12
- struct Context;
11
+ class Context;
13
12
  class Null;
14
13
 
15
14
  class To_String : public Operation_CRTP<string, To_String> {
@@ -25,8 +24,11 @@ namespace Sass {
25
24
  virtual ~To_String();
26
25
 
27
26
  string operator()(Null* n);
27
+ string operator()(String_Constant*);
28
28
 
29
29
  template <typename U>
30
30
  string fallback(U n) { return fallback_impl(n); }
31
31
  };
32
32
  }
33
+
34
+ #endif
@@ -45,10 +45,11 @@ namespace Sass {
45
45
  return factor;
46
46
  }
47
47
 
48
+ /* not used anymore - remove?
48
49
  double convert(double n, const string& from, const string& to)
49
50
  {
50
51
  double factor = conversion_factor(from, to);
51
52
  return factor ? factor * n : n;
52
- }
53
+ } */
53
54
 
54
55
  }
@@ -1,3 +1,6 @@
1
+ #ifndef SASS_UNITS_H
2
+ #define SASS_UNITS_H
3
+
1
4
  #include <string>
2
5
 
3
6
  namespace Sass {
@@ -6,5 +9,7 @@ namespace Sass {
6
9
  extern double conversion_factors[10][10];
7
10
  Unit string_to_unit(const string&);
8
11
  double conversion_factor(const string&, const string&);
9
- double convert(double, const string&, const string&);
12
+ // double convert(double, const string&, const string&);
10
13
  }
14
+
15
+ #endif
@@ -1,6 +1,3 @@
1
- #ifndef SASS_UTF8_STRING
2
- #define SASS_UTF8_STRING
3
-
4
1
  #include <string>
5
2
  #include <vector>
6
3
  #include <cstdlib>
@@ -98,5 +95,3 @@ namespace Sass {
98
95
 
99
96
  }
100
97
  }
101
-
102
- #endif
@@ -1,7 +1,8 @@
1
- #ifndef SASS_UTF8_STRING
2
- #define SASS_UTF8_STRING
1
+ #ifndef SASS_UTF8_STRING_H
2
+ #define SASS_UTF8_STRING_H
3
3
 
4
4
  #include <string>
5
+ #include "utf8.h"
5
6
 
6
7
  namespace Sass {
7
8
  namespace UTF_8 {
@@ -1,6 +1,391 @@
1
+ #include<stdint.h>
2
+ #include "ast.hpp"
1
3
  #include "util.hpp"
4
+ #include "prelexer.hpp"
5
+ #include "utf8/checked.h"
2
6
 
3
7
  namespace Sass {
8
+
9
+ #define out_of_memory() do { \
10
+ fprintf(stderr, "Out of memory.\n"); \
11
+ exit(EXIT_FAILURE); \
12
+ } while (0)
13
+
14
+ /* Sadly, sass_strdup is not portable. */
15
+ char *sass_strdup(const char *str)
16
+ {
17
+ char *ret = (char*) malloc(strlen(str) + 1);
18
+ if (ret == NULL)
19
+ out_of_memory();
20
+ strcpy(ret, str);
21
+ return ret;
22
+ }
23
+
24
+ /* Locale unspecific atof function. */
25
+ double sass_atof(const char *str)
26
+ {
27
+ char separator = *(localeconv()->decimal_point);
28
+ if(separator != '.'){
29
+ // The current locale specifies another
30
+ // separator. convert the separator to the
31
+ // one understood by the locale if needed
32
+ const char *found = strchr(str, '.');
33
+ if(found != NULL){
34
+ // substitution is required. perform the substitution on a copy
35
+ // of the string. This is slower but it is thread safe.
36
+ char *copy = sass_strdup(str);
37
+ *(copy + (found - str)) = separator;
38
+ double res = atof(copy);
39
+ free(copy);
40
+ return res;
41
+ }
42
+ }
43
+
44
+ return atof(str);
45
+ }
46
+
47
+ // double escape every escape sequences
48
+ // escape unescaped quotes and backslashes
49
+ string string_escape(const string& str)
50
+ {
51
+ string out("");
52
+ for (auto i : str) {
53
+ // escape some characters
54
+ if (i == '"') out += '\\';
55
+ if (i == '\'') out += '\\';
56
+ if (i == '\\') out += '\\';
57
+ out += i;
58
+ }
59
+ return out;
60
+ }
61
+
62
+ // unescape every escape sequence
63
+ // only removes unescaped backslashes
64
+ string string_unescape(const string& str)
65
+ {
66
+ string out("");
67
+ bool esc = false;
68
+ for (auto i : str) {
69
+ if (esc || i != '\\') {
70
+ esc = false;
71
+ out += i;
72
+ } else {
73
+ esc = true;
74
+ }
75
+ }
76
+ // open escape sequence at end
77
+ // maybe it should thow an error
78
+ if (esc) { out += '\\'; }
79
+ return out;
80
+ }
81
+
82
+ // evacuate unescaped quoted
83
+ // leave everything else untouched
84
+ string evacuate_quotes(const string& str)
85
+ {
86
+ string out("");
87
+ bool esc = false;
88
+ for (auto i : str) {
89
+ if (!esc) {
90
+ // ignore next character
91
+ if (i == '\\') esc = true;
92
+ // evacuate unescaped quotes
93
+ else if (i == '"') out += '\\';
94
+ else if (i == '\'') out += '\\';
95
+ }
96
+ // get escaped char now
97
+ else { esc = false; }
98
+ // remove nothing
99
+ out += i;
100
+ }
101
+ return out;
102
+ }
103
+
104
+ // double escape all escape sequences
105
+ // keep unescaped quotes and backslashes
106
+ string evacuate_escapes(const string& str)
107
+ {
108
+ string out("");
109
+ bool esc = false;
110
+ for (auto i : str) {
111
+ if (i == '\\' && !esc) {
112
+ out += '\\';
113
+ out += '\\';
114
+ esc = true;
115
+ } else if (esc && i == '"') {
116
+ out += '\\';
117
+ out += i;
118
+ esc = false;
119
+ } else if (esc && i == '\'') {
120
+ out += '\\';
121
+ out += i;
122
+ esc = false;
123
+ } else if (esc && i == '\\') {
124
+ out += '\\';
125
+ out += i;
126
+ esc = false;
127
+ } else {
128
+ esc = false;
129
+ out += i;
130
+ }
131
+ }
132
+ // happens when parsing does not correctly skip
133
+ // over escaped sequences for ie. interpolations
134
+ // one example: foo\#{interpolate}
135
+ // if (esc) out += '\\';
136
+ return out;
137
+ }
138
+
139
+ // bell character is replaces with space
140
+ string string_to_output(const string& str)
141
+ {
142
+ string out("");
143
+ for (auto i : str) {
144
+ if (i == 10) {
145
+ out += ' ';
146
+ } else {
147
+ out += i;
148
+ }
149
+ }
150
+ return out;
151
+ }
152
+
153
+ string comment_to_string(const string& text)
154
+ {
155
+ string str = "";
156
+ size_t has = 0;
157
+ bool clean = false;
158
+ for (auto i : text) {
159
+ if (clean) {
160
+ if (i == '\n') { has = 0; }
161
+ else if (i == '\r') { has = 0; }
162
+ else if (i == '\t') { ++ has; }
163
+ else if (i == ' ') { ++ has; }
164
+ else if (i == '*') {}
165
+ else {
166
+ clean = false;
167
+ str += ' ';
168
+ str += i;
169
+ }
170
+ } else if (i == '\n') {
171
+ clean = true;
172
+ } else if (i == '\r') {
173
+ clean = true;
174
+ } else {
175
+ str += i;
176
+ }
177
+ }
178
+ if (has) return str;
179
+ else return text;
180
+ }
181
+
182
+ string normalize_wspace(const string& str)
183
+ {
184
+ bool ws = false;
185
+ bool esc = false;
186
+ char inside_str = 0;
187
+ string text = "";
188
+ for(auto i : str) {
189
+ if (!esc && i == '\\') {
190
+ esc = true;
191
+ text += i;
192
+ } else if (esc) {
193
+ esc = false;
194
+ text += i;
195
+ } else if (!inside_str && (i == '"' || i == '\'')) {
196
+ inside_str = i;
197
+ text += i;
198
+ } else if (inside_str) {
199
+ if (i == inside_str)
200
+ inside_str = false;
201
+ text += i;
202
+ } else if (
203
+ i == ' ' ||
204
+ i == '\r' ||
205
+ i == '\n' ||
206
+ i == ' '
207
+ ) {
208
+ // only add one space
209
+ if (!ws) text += ' ';
210
+ ws = true;
211
+ } else {
212
+ ws = false;
213
+ text += i;
214
+ }
215
+ }
216
+ if (esc) text += '\\';
217
+ return text;
218
+ }
219
+
220
+ // find best quote_mark by detecting if the string contains any single
221
+ // or double quotes. When a single quote is found, we not we want a double
222
+ // quote as quote_mark. Otherwise we check if the string cotains any double
223
+ // quotes, which will trigger the use of single quotes as best quote_mark.
224
+ char detect_best_quotemark(const char* s, char qm)
225
+ {
226
+ // ensure valid fallback quote_mark
227
+ char quote_mark = qm && qm != '*' ? qm : '"';
228
+ while (*s) {
229
+ // force double quotes as soon
230
+ // as one single quote is found
231
+ if (*s == '\'') { return '"'; }
232
+ // a single does not force quote_mark
233
+ // maybe we see a double quote later
234
+ else if (*s == '"') { quote_mark = '\''; }
235
+ ++ s;
236
+ }
237
+ return quote_mark;
238
+ }
239
+
240
+ string unquote(const string& s, char* qd)
241
+ {
242
+
243
+ // not enough room for quotes
244
+ // no possibility to unquote
245
+ if (s.length() < 2) return s;
246
+
247
+ char q;
248
+ bool skipped = false;
249
+
250
+ // this is no guarantee that the unquoting will work
251
+ // what about whitespace before/after the quote_mark?
252
+ if (*s.begin() == '"' && *s.rbegin() == '"') q = '"';
253
+ else if (*s.begin() == '\'' && *s.rbegin() == '\'') q = '\'';
254
+ else return s;
255
+
256
+ string unq;
257
+ unq.reserve(s.length()-2);
258
+
259
+ for (size_t i = 1, L = s.length() - 1; i < L; ++i) {
260
+
261
+ // implement the same strange ruby sass behavior
262
+ // an escape sequence can also mean a unicode char
263
+ if (s[i] == '\\' && !skipped) {
264
+ // remember
265
+ skipped = true;
266
+
267
+ // skip it
268
+ // ++ i;
269
+
270
+ // if (i == L) break;
271
+
272
+ // escape length
273
+ size_t len = 1;
274
+
275
+ // parse as many sequence chars as possible
276
+ // ToDo: Check if ruby aborts after possible max
277
+ while (i + len < L && s[i + len] && isxdigit(s[i + len])) ++ len;
278
+
279
+ // hex string?
280
+ if (len > 1) {
281
+
282
+ // convert the extracted hex string to code point value
283
+ // ToDo: Maybe we could do this without creating a substring
284
+ uint32_t cp = strtol(s.substr (i + 1, len - 1).c_str(), nullptr, 16);
285
+
286
+ // assert invalid code points
287
+ if (cp == 0) cp = 0xFFFD;
288
+ // replace bell character
289
+ // if (cp == 10) cp = 32;
290
+
291
+ // use a very simple approach to convert via utf8 lib
292
+ // maybe there is a more elegant way; maybe we shoud
293
+ // convert the whole output from string to a stream!?
294
+ // allocate memory for utf8 char and convert to utf8
295
+ unsigned char u[5] = {0,0,0,0,0}; utf8::append(cp, u);
296
+ for(size_t m = 0; u[m] && m < 5; m++) unq.push_back(u[m]);
297
+
298
+ // skip some more chars?
299
+ i += len - 1; skipped = false;
300
+
301
+ }
302
+
303
+
304
+ }
305
+ // check for unexpected delimiter
306
+ // be strict and throw error back
307
+ else if (!skipped && q == s[i]) {
308
+ // don't be that strict
309
+ return s;
310
+ // this basically always means an internal error and not users fault
311
+ error("Unescaped delimiter in string to unquote found. [" + s + "]", ParserState("[UNQUOTE]", -1));
312
+ }
313
+ else {
314
+ skipped = false;
315
+ unq.push_back(s[i]);
316
+ }
317
+
318
+ }
319
+ if (skipped) { return s; }
320
+ if (qd) *qd = q;
321
+ return unq;
322
+
323
+ }
324
+
325
+ string quote(const string& s, char q)
326
+ {
327
+
328
+ // return an empty quoted string
329
+ if (s.empty()) return string(2, q ? q : '"');
330
+
331
+ // autodetect with fallback to given quote
332
+ q = detect_best_quotemark(s.c_str(), q);
333
+
334
+ string quoted;
335
+ quoted.reserve(s.length()+2);
336
+ quoted.push_back(q);
337
+
338
+ const char* it = s.c_str();
339
+ const char* end = it + strlen(it) + 1;
340
+ while (*it && it < end) {
341
+ const char* now = it;
342
+
343
+ if (*it == q) {
344
+ quoted.push_back('\\');
345
+ } else if (*it == '\\') {
346
+ quoted.push_back('\\');
347
+ }
348
+
349
+ int cp = utf8::next(it, end);
350
+
351
+ if (cp == 10) {
352
+ quoted.push_back('\\');
353
+ quoted.push_back('a');
354
+ } else if (cp < 127) {
355
+ quoted.push_back((char) cp);
356
+ } else {
357
+ while (now < it) {
358
+ quoted.push_back(*now);
359
+ ++ now;
360
+ }
361
+ }
362
+ }
363
+
364
+ quoted.push_back(q);
365
+ return quoted;
366
+ }
367
+
368
+ bool is_hex_doublet(double n)
369
+ {
370
+ return n == 0x00 || n == 0x11 || n == 0x22 || n == 0x33 ||
371
+ n == 0x44 || n == 0x55 || n == 0x66 || n == 0x77 ||
372
+ n == 0x88 || n == 0x99 || n == 0xAA || n == 0xBB ||
373
+ n == 0xCC || n == 0xDD || n == 0xEE || n == 0xFF ;
374
+ }
375
+
376
+ bool is_color_doublet(double r, double g, double b)
377
+ {
378
+ return is_hex_doublet(r) && is_hex_doublet(g) && is_hex_doublet(b);
379
+ }
380
+
381
+ bool peek_linefeed(const char* start)
382
+ {
383
+ if(*start == '\n' || *start == '\r') return true;;
384
+ const char* linefeed = Prelexer::wspaces(start);
385
+ if (linefeed == 0) return false;
386
+ return *linefeed == '\n' || *linefeed == '\r';
387
+ }
388
+
4
389
  namespace Util {
5
390
  using std::string;
6
391
 
@@ -37,7 +422,7 @@ namespace Sass {
37
422
  }
38
423
  }
39
424
 
40
- bool isPrintable(Ruleset* r) {
425
+ bool isPrintable(Ruleset* r, Output_Style style) {
41
426
  if (r == NULL) {
42
427
  return false;
43
428
  }
@@ -47,7 +432,7 @@ namespace Sass {
47
432
  bool hasSelectors = static_cast<Selector_List*>(r->selector())->length() > 0;
48
433
 
49
434
  if (!hasSelectors) {
50
- return false;
435
+ return false;
51
436
  }
52
437
 
53
438
  bool hasDeclarations = false;
@@ -55,23 +440,29 @@ namespace Sass {
55
440
  for (size_t i = 0, L = b->length(); i < L; ++i) {
56
441
  Statement* stm = (*b)[i];
57
442
  if (dynamic_cast<Has_Block*>(stm)) {
58
- Block* pChildBlock = ((Has_Block*)stm)->block();
59
- if (isPrintable(pChildBlock)) {
443
+ Block* pChildBlock = ((Has_Block*)stm)->block();
444
+ if (isPrintable(pChildBlock, style)) {
60
445
  hasPrintableChildBlocks = true;
61
446
  }
447
+ } else if (Comment* c = dynamic_cast<Comment*>(stm)) {
448
+ if (style == COMPRESSED) {
449
+ hasDeclarations = c->is_important();
450
+ } else {
451
+ hasDeclarations = true;
452
+ }
62
453
  } else {
63
- hasDeclarations = true;
454
+ hasDeclarations = true;
64
455
  }
65
456
 
66
457
  if (hasDeclarations || hasPrintableChildBlocks) {
67
- return true;
458
+ return true;
68
459
  }
69
460
  }
70
461
 
71
462
  return false;
72
463
  }
73
464
 
74
- bool isPrintable(Feature_Block* f) {
465
+ bool isPrintable(Feature_Block* f, Output_Style style) {
75
466
  if (f == NULL) {
76
467
  return false;
77
468
  }
@@ -95,7 +486,7 @@ namespace Sass {
95
486
  }
96
487
  else if (dynamic_cast<Has_Block*>(stm)) {
97
488
  Block* pChildBlock = ((Has_Block*)stm)->block();
98
- if (isPrintable(pChildBlock)) {
489
+ if (isPrintable(pChildBlock, style)) {
99
490
  hasPrintableChildBlocks = true;
100
491
  }
101
492
  }
@@ -108,7 +499,7 @@ namespace Sass {
108
499
  return false;
109
500
  }
110
501
 
111
- bool isPrintable(Media_Block* m) {
502
+ bool isPrintable(Media_Block* m, Output_Style style) {
112
503
  if (m == NULL) {
113
504
  return false;
114
505
  }
@@ -122,7 +513,7 @@ namespace Sass {
122
513
  for (size_t i = 0, L = b->length(); i < L; ++i) {
123
514
  Statement* stm = (*b)[i];
124
515
  if (!stm->is_hoistable() && m->selector() != NULL && !hasSelectors) {
125
- // If a statement isn't hoistable, the selectors apply to it. If there are no selectors (a selector list of length 0),
516
+ // If a statement isn't hoistable, the selectors apply to it. If there are no selectors (a selector list of length 0),
126
517
  // then those statements aren't considered printable. That means there was a placeholder that was removed. If the selector
127
518
  // is NULL, then that means there was never a wrapping selector and it is printable (think of a top level media block with
128
519
  // a declaration in it).
@@ -131,55 +522,76 @@ namespace Sass {
131
522
  hasDeclarations = true;
132
523
  }
133
524
  else if (dynamic_cast<Has_Block*>(stm)) {
134
- Block* pChildBlock = ((Has_Block*)stm)->block();
135
- if (isPrintable(pChildBlock)) {
525
+ Block* pChildBlock = ((Has_Block*)stm)->block();
526
+ if (isPrintable(pChildBlock, style)) {
136
527
  hasPrintableChildBlocks = true;
137
528
  }
138
529
  }
139
530
 
140
- if (hasDeclarations || hasPrintableChildBlocks) {
141
- return true;
531
+ if (hasDeclarations || hasPrintableChildBlocks) {
532
+ return true;
142
533
  }
143
534
  }
144
535
 
145
536
  return false;
146
537
  }
147
538
 
148
- bool isPrintable(Block* b) {
149
- if (b == NULL) {
150
- return false;
151
- }
152
-
153
- for (size_t i = 0, L = b->length(); i < L; ++i) {
154
- Statement* stm = (*b)[i];
155
- if (typeid(*stm) == typeid(Declaration) || typeid(*stm) == typeid(At_Rule)) {
156
- return true;
157
- }
158
- else if (typeid(*stm) == typeid(Ruleset)) {
159
- Ruleset* r = (Ruleset*) stm;
160
- if (isPrintable(r)) {
161
- return true;
162
- }
163
- }
164
- else if (typeid(*stm) == typeid(Feature_Block)) {
165
- Feature_Block* f = (Feature_Block*) stm;
166
- if (isPrintable(f)) {
167
- return true;
168
- }
169
- }
170
- else if (typeid(*stm) == typeid(Media_Block)) {
171
- Media_Block* m = (Media_Block*) stm;
172
- if (isPrintable(m)) {
173
- return true;
174
- }
175
- }
176
- else if (dynamic_cast<Has_Block*>(stm) && isPrintable(((Has_Block*)stm)->block())) {
177
- return true;
178
- }
179
- }
180
-
181
- return false;
182
- }
539
+ bool isPrintable(Block* b, Output_Style style) {
540
+ if (b == NULL) {
541
+ return false;
542
+ }
543
+
544
+ for (size_t i = 0, L = b->length(); i < L; ++i) {
545
+ Statement* stm = (*b)[i];
546
+ if (typeid(*stm) == typeid(Declaration) || typeid(*stm) == typeid(At_Rule)) {
547
+ return true;
548
+ }
549
+ else if (typeid(*stm) == typeid(Comment)) {
550
+
551
+ }
552
+ else if (typeid(*stm) == typeid(Ruleset)) {
553
+ Ruleset* r = (Ruleset*) stm;
554
+ if (isPrintable(r, style)) {
555
+ return true;
556
+ }
557
+ }
558
+ else if (typeid(*stm) == typeid(Feature_Block)) {
559
+ Feature_Block* f = (Feature_Block*) stm;
560
+ if (isPrintable(f, style)) {
561
+ return true;
562
+ }
563
+ }
564
+ else if (typeid(*stm) == typeid(Media_Block)) {
565
+ Media_Block* m = (Media_Block*) stm;
566
+ if (isPrintable(m, style)) {
567
+ return true;
568
+ }
569
+ }
570
+ else if (dynamic_cast<Has_Block*>(stm) && isPrintable(((Has_Block*)stm)->block(), style)) {
571
+ return true;
572
+ }
573
+ }
574
+
575
+ return false;
576
+ }
577
+
578
+ string vecJoin(const vector<string>& vec, const string& sep)
579
+ {
580
+ switch (vec.size())
581
+ {
582
+ case 0:
583
+ return string("");
584
+ case 1:
585
+ return vec[0];
586
+ default:
587
+ std::ostringstream os;
588
+ os << vec[0];
589
+ for (size_t i = 1; i < vec.size(); i++) {
590
+ os << sep << vec[i];
591
+ }
592
+ return os.str();
593
+ }
594
+ }
183
595
 
184
596
  bool isAscii(int ch) {
185
597
  return ch >= 0 && ch < 128;