sassc 1.8.1 → 1.8.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/ext/libsass/Makefile +10 -6
- data/ext/libsass/Readme.md +4 -4
- data/ext/libsass/appveyor.yml +16 -1
- data/ext/libsass/docs/README.md +1 -1
- data/ext/libsass/docs/api-context-example.md +1 -1
- data/ext/libsass/docs/api-context.md +1 -1
- data/ext/libsass/docs/api-doc.md +1 -1
- data/ext/libsass/docs/api-function-example.md +12 -3
- data/ext/libsass/docs/api-function-internal.md +4 -4
- data/ext/libsass/docs/api-function.md +15 -13
- data/ext/libsass/docs/api-importer-internal.md +9 -4
- data/ext/libsass/docs/api-value.md +1 -1
- data/ext/libsass/docs/build-shared-library.md +3 -3
- data/ext/libsass/docs/custom-functions-internal.md +1 -1
- data/ext/libsass/docs/{plugins.go → plugins.md} +0 -0
- data/ext/libsass/script/ci-build-libsass +25 -36
- data/ext/libsass/script/ci-install-deps +3 -8
- data/ext/libsass/script/ci-report-coverage +17 -13
- data/ext/libsass/src/ast.cpp +102 -7
- data/ext/libsass/src/ast.hpp +53 -27
- data/ext/libsass/src/ast_def_macros.hpp +8 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +3 -2
- data/ext/libsass/src/backtrace.hpp +1 -1
- data/ext/libsass/src/bind.cpp +28 -17
- data/ext/libsass/src/bind.hpp +1 -1
- data/ext/libsass/src/context.cpp +441 -184
- data/ext/libsass/src/context.hpp +79 -82
- data/ext/libsass/src/debugger.hpp +3 -1
- data/ext/libsass/src/emitter.cpp +18 -17
- data/ext/libsass/src/emitter.hpp +5 -2
- data/ext/libsass/src/error_handling.cpp +78 -7
- data/ext/libsass/src/error_handling.hpp +50 -9
- data/ext/libsass/src/eval.cpp +100 -36
- data/ext/libsass/src/eval.hpp +5 -5
- data/ext/libsass/src/expand.cpp +32 -3
- data/ext/libsass/src/extend.cpp +1 -1
- data/ext/libsass/src/file.cpp +39 -27
- data/ext/libsass/src/file.hpp +67 -13
- data/ext/libsass/src/functions.cpp +39 -32
- data/ext/libsass/src/inspect.cpp +21 -21
- data/ext/libsass/src/json.cpp +1 -1
- data/ext/libsass/src/lexer.hpp +33 -4
- data/ext/libsass/src/output.cpp +11 -11
- data/ext/libsass/src/parser.cpp +28 -130
- data/ext/libsass/src/parser.hpp +0 -4
- data/ext/libsass/src/prelexer.cpp +8 -5
- data/ext/libsass/src/prelexer.hpp +1 -3
- data/ext/libsass/src/sass_context.cpp +52 -241
- data/ext/libsass/src/sass_context.hpp +156 -0
- data/ext/libsass/src/sass_functions.cpp +1 -26
- data/ext/libsass/src/sass_functions.hpp +32 -0
- data/ext/libsass/src/sass_interface.cpp +14 -48
- data/ext/libsass/src/sass_values.cpp +3 -77
- data/ext/libsass/src/sass_values.hpp +81 -0
- data/ext/libsass/src/source_map.cpp +7 -7
- data/ext/libsass/src/source_map.hpp +1 -4
- data/ext/libsass/src/to_string.cpp +4 -3
- data/ext/libsass/src/to_string.hpp +2 -1
- data/ext/libsass/src/util.cpp +34 -16
- data/ext/libsass/src/util.hpp +10 -8
- data/lib/sassc/version.rb +1 -1
- data/lib/tasks/libsass.rb +1 -1
- data/test/custom_importer_test.rb +6 -4
- data/test/engine_test.rb +5 -3
- data/test/functions_test.rb +1 -0
- data/test/native_test.rb +1 -1
- metadata +6 -4
- data/ext/libsass/script/coveralls-debug +0 -32
data/ext/libsass/src/json.cpp
CHANGED
data/ext/libsass/src/lexer.hpp
CHANGED
@@ -84,14 +84,14 @@ namespace Sass {
|
|
84
84
|
//####################################
|
85
85
|
|
86
86
|
// Match a single character literal.
|
87
|
-
// Regex equivalent: /(?:
|
87
|
+
// Regex equivalent: /(?:x)/
|
88
88
|
template <char chr>
|
89
89
|
const char* exactly(const char* src) {
|
90
90
|
return *src == chr ? src + 1 : 0;
|
91
91
|
}
|
92
92
|
|
93
|
-
// Match
|
94
|
-
// Regex equivalent: /
|
93
|
+
// Match the full string literal.
|
94
|
+
// Regex equivalent: /(?:literal)/
|
95
95
|
template <const char* str>
|
96
96
|
const char* exactly(const char* src) {
|
97
97
|
if (str == 0) return 0;
|
@@ -102,7 +102,26 @@ namespace Sass {
|
|
102
102
|
while (*pre && *src == *pre) {
|
103
103
|
++src, ++pre;
|
104
104
|
}
|
105
|
-
|
105
|
+
// did the matcher finish?
|
106
|
+
return *pre == 0 ? src : 0;
|
107
|
+
}
|
108
|
+
|
109
|
+
|
110
|
+
// Match the full string literal.
|
111
|
+
// Regex equivalent: /(?:literal)/i
|
112
|
+
// only define lower case alpha chars
|
113
|
+
template <const char* str>
|
114
|
+
const char* insensitive(const char* src) {
|
115
|
+
if (str == 0) return 0;
|
116
|
+
const char* pre = str;
|
117
|
+
if (src == 0) return 0;
|
118
|
+
// there is a small chance that the search string
|
119
|
+
// is longer than the rest of the string to look at
|
120
|
+
while (*pre && (*src == *pre || *src+32 == *pre)) {
|
121
|
+
++src, ++pre;
|
122
|
+
}
|
123
|
+
// did the matcher finish?
|
124
|
+
return *pre == 0 ? src : 0;
|
106
125
|
}
|
107
126
|
|
108
127
|
// Match for members of char class.
|
@@ -225,6 +244,16 @@ namespace Sass {
|
|
225
244
|
// ADVANCED "REGEX" CONSTRUCTORS
|
226
245
|
//####################################
|
227
246
|
|
247
|
+
// Match with word boundary rule.
|
248
|
+
// Regex equivalent: /(?:$mx)\b/i
|
249
|
+
template <const char* str>
|
250
|
+
const char* keyword(const char* src) {
|
251
|
+
return sequence <
|
252
|
+
insensitive < str >,
|
253
|
+
word_boundary
|
254
|
+
>(src);
|
255
|
+
}
|
256
|
+
|
228
257
|
// Match with word boundary rule.
|
229
258
|
// Regex equivalent: /(?:$mx)\b/
|
230
259
|
template <const char* str>
|
data/ext/libsass/src/output.cpp
CHANGED
@@ -74,7 +74,7 @@ namespace Sass {
|
|
74
74
|
// skip all ascii chars
|
75
75
|
if (chr >= 0) continue;
|
76
76
|
// declare the charset
|
77
|
-
if (output_style() !=
|
77
|
+
if (output_style() != SASS_STYLE_COMPRESSED)
|
78
78
|
charset = "@charset \"UTF-8\";"
|
79
79
|
+ ctx->linefeed;
|
80
80
|
else charset = "\xEF\xBB\xBF";
|
@@ -95,7 +95,7 @@ namespace Sass {
|
|
95
95
|
std::string txt = c->text()->perform(&to_string);
|
96
96
|
// if (indentation && txt == "/**/") return;
|
97
97
|
bool important = c->is_important();
|
98
|
-
if (output_style() !=
|
98
|
+
if (output_style() != SASS_STYLE_COMPRESSED || important) {
|
99
99
|
if (buffer().size() == 0) {
|
100
100
|
top_nodes.push_back(c);
|
101
101
|
} else {
|
@@ -131,11 +131,11 @@ namespace Sass {
|
|
131
131
|
|
132
132
|
if (b->has_non_hoistable()) {
|
133
133
|
decls = true;
|
134
|
-
if (output_style() ==
|
135
|
-
if (ctx && ctx->source_comments) {
|
134
|
+
if (output_style() == SASS_STYLE_NESTED) indentation += r->tabs();
|
135
|
+
if (ctx && ctx->c_options->source_comments) {
|
136
136
|
std::stringstream ss;
|
137
137
|
append_indentation();
|
138
|
-
ss << "/* line " << r->pstate().line+1 << ", " << r->pstate().path << " */";
|
138
|
+
ss << "/* line " << r->pstate().line + 1 << ", " << r->pstate().path << " */";
|
139
139
|
append_string(ss.str());
|
140
140
|
append_optional_linefeed();
|
141
141
|
}
|
@@ -171,7 +171,7 @@ namespace Sass {
|
|
171
171
|
stm->perform(this);
|
172
172
|
}
|
173
173
|
}
|
174
|
-
if (output_style() ==
|
174
|
+
if (output_style() == SASS_STYLE_NESTED) indentation -= r->tabs();
|
175
175
|
append_scope_closer(b);
|
176
176
|
}
|
177
177
|
|
@@ -238,7 +238,7 @@ namespace Sass {
|
|
238
238
|
return;
|
239
239
|
}
|
240
240
|
|
241
|
-
if (output_style() ==
|
241
|
+
if (output_style() == SASS_STYLE_NESTED) indentation += f->tabs();
|
242
242
|
append_indentation();
|
243
243
|
append_token("@supports", f);
|
244
244
|
append_mandatory_space();
|
@@ -274,7 +274,7 @@ namespace Sass {
|
|
274
274
|
}
|
275
275
|
}
|
276
276
|
|
277
|
-
if (output_style() ==
|
277
|
+
if (output_style() == SASS_STYLE_NESTED) indentation -= f->tabs();
|
278
278
|
|
279
279
|
append_scope_closer();
|
280
280
|
|
@@ -297,7 +297,7 @@ namespace Sass {
|
|
297
297
|
}
|
298
298
|
return;
|
299
299
|
}
|
300
|
-
if (output_style() ==
|
300
|
+
if (output_style() == SASS_STYLE_NESTED) indentation += m->tabs();
|
301
301
|
append_indentation();
|
302
302
|
append_token("@media", m);
|
303
303
|
append_mandatory_space();
|
@@ -311,7 +311,7 @@ namespace Sass {
|
|
311
311
|
if (i < L - 1) append_special_linefeed();
|
312
312
|
}
|
313
313
|
|
314
|
-
if (output_style() ==
|
314
|
+
if (output_style() == SASS_STYLE_NESTED) indentation -= m->tabs();
|
315
315
|
append_scope_closer();
|
316
316
|
}
|
317
317
|
|
@@ -380,7 +380,7 @@ namespace Sass {
|
|
380
380
|
void Output::operator()(String_Constant* s)
|
381
381
|
{
|
382
382
|
std::string value(s->value());
|
383
|
-
if (s->can_compress_whitespace() && output_style() ==
|
383
|
+
if (s->can_compress_whitespace() && output_style() == SASS_STYLE_COMPRESSED) {
|
384
384
|
value.erase(std::remove_if(value.begin(), value.end(), ::isspace), value.end());
|
385
385
|
}
|
386
386
|
if (!in_comment) {
|
data/ext/libsass/src/parser.cpp
CHANGED
@@ -76,18 +76,10 @@ namespace Sass {
|
|
76
76
|
Block* root = SASS_MEMORY_NEW(ctx.mem, Block, pstate, 0, true);
|
77
77
|
read_bom();
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
do_import(load_path, pre, ctx.c_headers, false);
|
84
|
-
ctx.head_imports = ctx.queue.size() - 1;
|
85
|
-
if (!pre->urls().empty()) (*root) << pre;
|
86
|
-
if (!pre->files().empty()) {
|
87
|
-
for (size_t i = 0, S = pre->files().size(); i < S; ++i) {
|
88
|
-
(*root) << SASS_MEMORY_NEW(ctx.mem, Import_Stub, pstate, pre->files()[i]);
|
89
|
-
}
|
90
|
-
}
|
79
|
+
// custom headers
|
80
|
+
if (ctx.resources.size() == 1) {
|
81
|
+
is_root = true;
|
82
|
+
ctx.apply_custom_headers(root, path, pstate);
|
91
83
|
}
|
92
84
|
|
93
85
|
block_stack.push_back(root);
|
@@ -113,6 +105,7 @@ namespace Sass {
|
|
113
105
|
|
114
106
|
// parse comments before block
|
115
107
|
// lex < optional_css_comments >();
|
108
|
+
|
116
109
|
// lex mandatory opener or error out
|
117
110
|
if (!lex_css < exactly<'{'> >()) {
|
118
111
|
css_error("Invalid CSS", " after ", ": expected \"{\", was ");
|
@@ -130,7 +123,7 @@ namespace Sass {
|
|
130
123
|
// update for end position
|
131
124
|
block->update_pstate(pstate);
|
132
125
|
|
133
|
-
// parse comments
|
126
|
+
// parse comments after block
|
134
127
|
// lex < optional_css_comments >();
|
135
128
|
|
136
129
|
block_stack.pop_back();
|
@@ -222,11 +215,9 @@ namespace Sass {
|
|
222
215
|
Import* imp = parse_import();
|
223
216
|
// if it is a url, we only add the statement
|
224
217
|
if (!imp->urls().empty()) (*block) << imp;
|
225
|
-
//
|
226
|
-
|
227
|
-
|
228
|
-
(*block) << SASS_MEMORY_NEW(ctx.mem, Import_Stub, pstate, imp->files()[i]);
|
229
|
-
}
|
218
|
+
// process all resources now (add Import_Stub nodes)
|
219
|
+
for (size_t i = 0, S = imp->incs().size(); i < S; ++i) {
|
220
|
+
(*block) << SASS_MEMORY_NEW(ctx.mem, Import_Stub, pstate, imp->incs()[i]);
|
230
221
|
}
|
231
222
|
}
|
232
223
|
|
@@ -288,105 +279,7 @@ namespace Sass {
|
|
288
279
|
}
|
289
280
|
// EO parse_block_nodes
|
290
281
|
|
291
|
-
|
292
|
-
|
293
|
-
std::string extension;
|
294
|
-
std::string unquoted(unquote(import_path));
|
295
|
-
if (unquoted.length() > 4) { // 2 quote marks + the 4 chars in .css
|
296
|
-
// a string constant is guaranteed to end with a quote mark, so make sure to skip it when indexing from the end
|
297
|
-
extension = unquoted.substr(unquoted.length() - 4, 4);
|
298
|
-
}
|
299
|
-
|
300
|
-
if (extension == ".css") {
|
301
|
-
String_Constant* loc = SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, unquote(import_path));
|
302
|
-
Argument* loc_arg = SASS_MEMORY_NEW(ctx.mem, Argument, pstate, loc);
|
303
|
-
Arguments* loc_args = SASS_MEMORY_NEW(ctx.mem, Arguments, pstate);
|
304
|
-
(*loc_args) << loc_arg;
|
305
|
-
Function_Call* new_url = SASS_MEMORY_NEW(ctx.mem, Function_Call, pstate, "url", loc_args);
|
306
|
-
imp->urls().push_back(new_url);
|
307
|
-
}
|
308
|
-
else {
|
309
|
-
std::string current_dir = File::dir_name(path);
|
310
|
-
std::string resolved(ctx.add_file(current_dir, unquoted, *this));
|
311
|
-
if (resolved.empty()) error("file to import not found or unreadable: " + unquoted + "\nCurrent dir: " + current_dir, pstate);
|
312
|
-
imp->files().push_back(resolved);
|
313
|
-
}
|
314
|
-
|
315
|
-
}
|
316
|
-
|
317
|
-
void Parser::import_single_file (Import* imp, std::string import_path) {
|
318
|
-
|
319
|
-
if (imp->media_queries() ||
|
320
|
-
!unquote(import_path).substr(0, 7).compare("http://") ||
|
321
|
-
!unquote(import_path).substr(0, 8).compare("https://") ||
|
322
|
-
!unquote(import_path).substr(0, 2).compare("//"))
|
323
|
-
{
|
324
|
-
imp->urls().push_back(SASS_MEMORY_NEW(ctx.mem, String_Quoted, pstate, import_path));
|
325
|
-
}
|
326
|
-
else {
|
327
|
-
add_single_file(imp, import_path);
|
328
|
-
}
|
329
|
-
|
330
|
-
}
|
331
|
-
|
332
|
-
bool Parser::do_import(const std::string& import_path, Import* imp, std::vector<Sass_Importer_Entry> importers, bool only_one)
|
333
|
-
{
|
334
|
-
size_t i = 0;
|
335
|
-
bool has_import = false;
|
336
|
-
std::string load_path = unquote(import_path);
|
337
|
-
// std::cerr << "-- " << load_path << "\n";
|
338
|
-
for (Sass_Importer_Entry& importer : importers) {
|
339
|
-
// int priority = sass_importer_get_priority(importer);
|
340
|
-
Sass_Importer_Fn fn = sass_importer_get_function(importer);
|
341
|
-
if (Sass_Import_List includes =
|
342
|
-
fn(load_path.c_str(), importer, ctx.c_compiler)
|
343
|
-
) {
|
344
|
-
Sass_Import_List list = includes;
|
345
|
-
while (*includes) { ++i;
|
346
|
-
std::string uniq_path = load_path;
|
347
|
-
if (!only_one && i) {
|
348
|
-
std::stringstream pathstrm;
|
349
|
-
pathstrm << uniq_path << ":" << i;
|
350
|
-
uniq_path = pathstrm.str();
|
351
|
-
}
|
352
|
-
Sass_Import_Entry include = *includes;
|
353
|
-
const char *abs_path = sass_import_get_abs_path(include);
|
354
|
-
char* source = sass_import_take_source(include);
|
355
|
-
size_t line = sass_import_get_error_line(include);
|
356
|
-
size_t column = sass_import_get_error_column(include);
|
357
|
-
const char* message = sass_import_get_error_message(include);
|
358
|
-
if (message) {
|
359
|
-
if (line == std::string::npos && column == std::string::npos) error(message, pstate);
|
360
|
-
else error(message, ParserState(message, source, Position(line, column)));
|
361
|
-
} else if (source) {
|
362
|
-
if (abs_path) {
|
363
|
-
ctx.add_source(uniq_path, abs_path, source);
|
364
|
-
imp->files().push_back(uniq_path);
|
365
|
-
size_t i = ctx.queue.size() - 1;
|
366
|
-
ctx.process_queue_entry(ctx.queue[i], i);
|
367
|
-
} else {
|
368
|
-
ctx.add_source(uniq_path, uniq_path, source);
|
369
|
-
imp->files().push_back(uniq_path);
|
370
|
-
size_t i = ctx.queue.size() - 1;
|
371
|
-
ctx.process_queue_entry(ctx.queue[i], i);
|
372
|
-
}
|
373
|
-
} else if(abs_path) {
|
374
|
-
import_single_file(imp, abs_path);
|
375
|
-
}
|
376
|
-
++includes;
|
377
|
-
}
|
378
|
-
// deallocate returned memory
|
379
|
-
sass_delete_import_list(list);
|
380
|
-
// set success flag
|
381
|
-
has_import = true;
|
382
|
-
// break import chain
|
383
|
-
if (only_one) return true;
|
384
|
-
}
|
385
|
-
}
|
386
|
-
// return result
|
387
|
-
return has_import;
|
388
|
-
}
|
389
|
-
|
282
|
+
// parse imports inside the
|
390
283
|
Import* Parser::parse_import()
|
391
284
|
{
|
392
285
|
Import* imp = SASS_MEMORY_NEW(ctx.mem, Import, pstate);
|
@@ -395,7 +288,7 @@ namespace Sass {
|
|
395
288
|
do {
|
396
289
|
while (lex< block_comment >());
|
397
290
|
if (lex< quoted_string >()) {
|
398
|
-
if (!
|
291
|
+
if (!ctx.call_importers(unquote(std::string(lexed)), path, pstate, imp))
|
399
292
|
{
|
400
293
|
// push single file import
|
401
294
|
// import_single_file(imp, lexed);
|
@@ -421,8 +314,7 @@ namespace Sass {
|
|
421
314
|
error("malformed URL", pstate);
|
422
315
|
}
|
423
316
|
if (!lex< exactly<')'> >()) error("URI is missing ')'", pstate);
|
424
|
-
|
425
|
-
to_import.push_back(std::pair<std::string,Function_Call*>("", result));
|
317
|
+
to_import.push_back(std::pair<std::string, Function_Call*>("", result));
|
426
318
|
}
|
427
319
|
else {
|
428
320
|
if (first) error("@import directive requires a url or quoted path", pstate);
|
@@ -440,7 +332,7 @@ namespace Sass {
|
|
440
332
|
if (location.second) {
|
441
333
|
imp->urls().push_back(location.second);
|
442
334
|
} else {
|
443
|
-
|
335
|
+
ctx.import_url(imp, location.first, path);
|
444
336
|
}
|
445
337
|
}
|
446
338
|
|
@@ -1849,11 +1741,13 @@ namespace Sass {
|
|
1849
1741
|
Block* block = parse_block();
|
1850
1742
|
Block* alternative = 0;
|
1851
1743
|
|
1852
|
-
if
|
1744
|
+
// only throw away comment if we parse a case
|
1745
|
+
// we want all other comments to be parsed
|
1746
|
+
if (lex_css< elseif_directive >()) {
|
1853
1747
|
alternative = SASS_MEMORY_NEW(ctx.mem, Block, pstate);
|
1854
1748
|
(*alternative) << parse_if_directive(true);
|
1855
1749
|
}
|
1856
|
-
else if (
|
1750
|
+
else if (lex_css< kwd_else_directive >()) {
|
1857
1751
|
alternative = parse_block();
|
1858
1752
|
}
|
1859
1753
|
return SASS_MEMORY_NEW(ctx.mem, If, if_source_position, predicate, block, alternative);
|
@@ -1969,15 +1863,15 @@ namespace Sass {
|
|
1969
1863
|
Media_Query* media_query = SASS_MEMORY_NEW(ctx.mem, Media_Query, pstate);
|
1970
1864
|
|
1971
1865
|
lex < css_comments >(false);
|
1972
|
-
if (lex <
|
1973
|
-
else if (lex <
|
1866
|
+
if (lex < kwd_not >()) media_query->is_negated(true);
|
1867
|
+
else if (lex < kwd_only >()) media_query->is_restricted(true);
|
1974
1868
|
|
1975
1869
|
lex < css_comments >(false);
|
1976
1870
|
if (lex < identifier_schema >()) media_query->media_type(parse_identifier_schema());
|
1977
1871
|
else if (lex < identifier >()) media_query->media_type(parse_interpolated_chunk(lexed));
|
1978
1872
|
else (*media_query) << parse_media_expression();
|
1979
1873
|
|
1980
|
-
while (lex_css <
|
1874
|
+
while (lex_css < kwd_and >()) (*media_query) << parse_media_expression();
|
1981
1875
|
if (lex < identifier_schema >()) {
|
1982
1876
|
String_Schema* schema = SASS_MEMORY_NEW(ctx.mem, String_Schema, pstate);
|
1983
1877
|
*schema << media_query->media_type();
|
@@ -1985,7 +1879,7 @@ namespace Sass {
|
|
1985
1879
|
*schema << parse_identifier_schema();
|
1986
1880
|
media_query->media_type(schema);
|
1987
1881
|
}
|
1988
|
-
while (lex_css <
|
1882
|
+
while (lex_css < kwd_and >()) (*media_query) << parse_media_expression();
|
1989
1883
|
return media_query;
|
1990
1884
|
}
|
1991
1885
|
|
@@ -2051,9 +1945,10 @@ namespace Sass {
|
|
2051
1945
|
Supports_Condition* cond = parse_supports_condition_in_parens();
|
2052
1946
|
if (!cond) return 0;
|
2053
1947
|
|
2054
|
-
while (
|
1948
|
+
while (true) {
|
2055
1949
|
Supports_Operator::Operand op = Supports_Operator::OR;
|
2056
|
-
if (
|
1950
|
+
if (lex < kwd_and >()) { op = Supports_Operator::AND; }
|
1951
|
+
else if(!lex < kwd_or >()) { break; }
|
2057
1952
|
|
2058
1953
|
lex < css_whitespace >();
|
2059
1954
|
Supports_Condition* right = parse_supports_condition_in_parens();
|
@@ -2159,6 +2054,9 @@ namespace Sass {
|
|
2159
2054
|
At_Rule* Parser::parse_at_rule()
|
2160
2055
|
{
|
2161
2056
|
std::string kwd(lexed);
|
2057
|
+
|
2058
|
+
if (lexed == "@else") error("Invalid CSS: @else must come after @if", pstate);
|
2059
|
+
|
2162
2060
|
At_Rule* at_rule = SASS_MEMORY_NEW(ctx.mem, At_Rule, pstate, kwd);
|
2163
2061
|
Lookahead lookahead = lookahead_for_include(position);
|
2164
2062
|
if (lookahead.found && !lookahead.has_interpolants) {
|
@@ -2482,7 +2380,7 @@ namespace Sass {
|
|
2482
2380
|
|
2483
2381
|
void Parser::error(std::string msg, Position pos)
|
2484
2382
|
{
|
2485
|
-
throw
|
2383
|
+
throw Exception::InvalidSass(ParserState(path, source, pos.line ? pos : before_token, Offset(0, 0)), msg);
|
2486
2384
|
}
|
2487
2385
|
|
2488
2386
|
// print a css parsing error with actual context information from parsed source
|
data/ext/libsass/src/parser.hpp
CHANGED
@@ -21,13 +21,9 @@ struct Lookahead {
|
|
21
21
|
namespace Sass {
|
22
22
|
|
23
23
|
class Parser : public ParserState {
|
24
|
-
private:
|
25
|
-
void add_single_file (Import* imp, std::string import_path);
|
26
|
-
void import_single_file (Import* imp, std::string import_path);
|
27
24
|
public:
|
28
25
|
|
29
26
|
enum Syntactic_Context { nothing, mixin_def, function_def };
|
30
|
-
bool do_import(const std::string& import_path, Import* imp, std::vector<Sass_Importer_Entry> importers, bool only_one = true);
|
31
27
|
|
32
28
|
Context& ctx;
|
33
29
|
std::vector<Block*> block_stack;
|
@@ -398,7 +398,7 @@ namespace Sass {
|
|
398
398
|
}
|
399
399
|
const char* elseif_directive(const char* src) {
|
400
400
|
return sequence< exactly< else_kwd >,
|
401
|
-
|
401
|
+
optional_css_comments,
|
402
402
|
word< if_after_else_kwd > >(src);
|
403
403
|
}
|
404
404
|
|
@@ -759,14 +759,17 @@ namespace Sass {
|
|
759
759
|
const char* kwd_false(const char* src) {
|
760
760
|
return word<false_kwd>(src);
|
761
761
|
}
|
762
|
+
const char* kwd_only(const char* src) {
|
763
|
+
return keyword < only_kwd >(src);
|
764
|
+
}
|
762
765
|
const char* kwd_and(const char* src) {
|
763
|
-
return
|
766
|
+
return keyword < and_kwd >(src);
|
764
767
|
}
|
765
768
|
const char* kwd_or(const char* src) {
|
766
|
-
return
|
769
|
+
return keyword < or_kwd >(src);
|
767
770
|
}
|
768
771
|
const char* kwd_not(const char* src) {
|
769
|
-
return
|
772
|
+
return keyword < not_kwd >(src);
|
770
773
|
}
|
771
774
|
const char* kwd_eq(const char* src) {
|
772
775
|
return exactly<eq>(src);
|
@@ -1016,7 +1019,7 @@ namespace Sass {
|
|
1016
1019
|
hex,
|
1017
1020
|
exactly<'|'>,
|
1018
1021
|
// exactly<'+'>,
|
1019
|
-
sequence < number,
|
1022
|
+
sequence < number, unit_identifier >,
|
1020
1023
|
number,
|
1021
1024
|
sequence< exactly<'!'>, word<important_kwd> >
|
1022
1025
|
>(src);
|