sassc 1.8.1 → 1.8.2
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.
- 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);
|