sassc 1.8.3 → 1.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/ext/libsass/.editorconfig +1 -1
- data/ext/libsass/.gitignore +1 -0
- data/ext/libsass/LICENSE +1 -1
- data/ext/libsass/Makefile +20 -14
- data/ext/libsass/Makefile.conf +0 -1
- data/ext/libsass/Readme.md +3 -1
- data/ext/libsass/appveyor.yml +19 -11
- data/ext/libsass/docs/api-importer-example.md +2 -1235
- data/ext/libsass/docs/build-with-autotools.md +10 -0
- data/ext/libsass/docs/build-with-makefiles.md +18 -0
- data/ext/libsass/include/sass/base.h +4 -1
- data/ext/libsass/include/sass/values.h +2 -1
- data/ext/libsass/src/ast.cpp +279 -346
- data/ext/libsass/src/ast.hpp +234 -60
- data/ext/libsass/src/base64vlq.cpp +1 -0
- data/ext/libsass/src/bind.cpp +35 -45
- data/ext/libsass/src/bind.hpp +1 -0
- data/ext/libsass/src/color_maps.cpp +1 -0
- data/ext/libsass/src/constants.cpp +4 -1
- data/ext/libsass/src/constants.hpp +2 -1
- data/ext/libsass/src/context.cpp +41 -31
- data/ext/libsass/src/context.hpp +10 -10
- data/ext/libsass/src/cssize.cpp +7 -4
- data/ext/libsass/src/cssize.hpp +1 -3
- data/ext/libsass/src/debugger.hpp +73 -14
- data/ext/libsass/src/emitter.cpp +37 -25
- data/ext/libsass/src/emitter.hpp +10 -9
- data/ext/libsass/src/environment.cpp +16 -5
- data/ext/libsass/src/environment.hpp +5 -3
- data/ext/libsass/src/error_handling.cpp +91 -14
- data/ext/libsass/src/error_handling.hpp +105 -4
- data/ext/libsass/src/eval.cpp +519 -330
- data/ext/libsass/src/eval.hpp +12 -13
- data/ext/libsass/src/expand.cpp +92 -56
- data/ext/libsass/src/expand.hpp +5 -3
- data/ext/libsass/src/extend.cpp +60 -51
- data/ext/libsass/src/extend.hpp +1 -3
- data/ext/libsass/src/file.cpp +37 -27
- data/ext/libsass/src/functions.cpp +78 -62
- data/ext/libsass/src/functions.hpp +1 -0
- data/ext/libsass/src/inspect.cpp +293 -64
- data/ext/libsass/src/inspect.hpp +2 -0
- data/ext/libsass/src/lexer.cpp +1 -0
- data/ext/libsass/src/listize.cpp +14 -15
- data/ext/libsass/src/listize.hpp +3 -5
- data/ext/libsass/src/memory_manager.cpp +1 -0
- data/ext/libsass/src/node.cpp +2 -3
- data/ext/libsass/src/operation.hpp +70 -71
- data/ext/libsass/src/output.cpp +28 -32
- data/ext/libsass/src/output.hpp +1 -2
- data/ext/libsass/src/parser.cpp +402 -183
- data/ext/libsass/src/parser.hpp +19 -9
- data/ext/libsass/src/plugins.cpp +1 -0
- data/ext/libsass/src/position.cpp +1 -0
- data/ext/libsass/src/prelexer.cpp +134 -56
- data/ext/libsass/src/prelexer.hpp +51 -3
- data/ext/libsass/src/remove_placeholders.cpp +35 -9
- data/ext/libsass/src/remove_placeholders.hpp +4 -3
- data/ext/libsass/src/sass.cpp +1 -0
- data/ext/libsass/src/sass.hpp +129 -0
- data/ext/libsass/src/sass_context.cpp +31 -14
- data/ext/libsass/src/sass_context.hpp +2 -31
- data/ext/libsass/src/sass_functions.cpp +1 -0
- data/ext/libsass/src/sass_interface.cpp +5 -6
- data/ext/libsass/src/sass_util.cpp +1 -2
- data/ext/libsass/src/sass_util.hpp +5 -5
- data/ext/libsass/src/sass_values.cpp +13 -10
- data/ext/libsass/src/source_map.cpp +4 -3
- data/ext/libsass/src/source_map.hpp +2 -2
- data/ext/libsass/src/subset_map.hpp +0 -1
- data/ext/libsass/src/to_c.cpp +1 -0
- data/ext/libsass/src/to_c.hpp +1 -3
- data/ext/libsass/src/to_value.cpp +3 -5
- data/ext/libsass/src/to_value.hpp +1 -1
- data/ext/libsass/src/units.cpp +96 -59
- data/ext/libsass/src/units.hpp +10 -8
- data/ext/libsass/src/utf8_string.cpp +5 -0
- data/ext/libsass/src/util.cpp +23 -156
- data/ext/libsass/src/util.hpp +10 -14
- data/ext/libsass/src/values.cpp +1 -0
- data/ext/libsass/test/test_node.cpp +2 -6
- data/ext/libsass/test/test_selector_difference.cpp +1 -3
- data/ext/libsass/test/test_specificity.cpp +0 -2
- data/ext/libsass/test/test_superselector.cpp +0 -2
- data/ext/libsass/test/test_unification.cpp +1 -3
- data/ext/libsass/win/libsass.targets +18 -5
- data/ext/libsass/win/libsass.vcxproj +9 -7
- data/ext/libsass/win/libsass.vcxproj.filters +148 -106
- data/lib/sassc/version.rb +1 -1
- data/test/engine_test.rb +12 -0
- data/test/native_test.rb +1 -1
- metadata +3 -4
- data/ext/libsass/src/to_string.cpp +0 -48
- data/ext/libsass/src/to_string.hpp +0 -38
data/ext/libsass/src/eval.hpp
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#ifndef SASS_EVAL_H
|
|
2
2
|
#define SASS_EVAL_H
|
|
3
3
|
|
|
4
|
+
#include "ast.hpp"
|
|
4
5
|
#include "context.hpp"
|
|
5
|
-
#include "listize.hpp"
|
|
6
6
|
#include "operation.hpp"
|
|
7
|
+
#include "environment.hpp"
|
|
7
8
|
|
|
8
9
|
namespace Sass {
|
|
9
10
|
|
|
10
11
|
class Expand;
|
|
11
12
|
class Context;
|
|
12
|
-
class Listize;
|
|
13
13
|
|
|
14
14
|
class Eval : public Operation_CRTP<Expression*, Eval> {
|
|
15
15
|
|
|
@@ -19,17 +19,16 @@ namespace Sass {
|
|
|
19
19
|
public:
|
|
20
20
|
Expand& exp;
|
|
21
21
|
Context& ctx;
|
|
22
|
-
Listize listize;
|
|
23
22
|
Eval(Expand& exp);
|
|
24
|
-
|
|
23
|
+
~Eval();
|
|
24
|
+
|
|
25
|
+
bool is_in_comment;
|
|
25
26
|
|
|
26
27
|
Env* environment();
|
|
27
28
|
Context& context();
|
|
28
29
|
Selector_List* selector();
|
|
29
30
|
Backtrace* backtrace();
|
|
30
31
|
|
|
31
|
-
using Operation<Expression*>::operator();
|
|
32
|
-
|
|
33
32
|
// for evaluating function bodies
|
|
34
33
|
Expression* operator()(Block*);
|
|
35
34
|
Expression* operator()(Assignment*);
|
|
@@ -87,16 +86,16 @@ namespace Sass {
|
|
|
87
86
|
|
|
88
87
|
// -- only need to define two comparisons, and the rest can be implemented in terms of them
|
|
89
88
|
static bool eq(Expression*, Expression*);
|
|
90
|
-
static bool lt(Expression*, Expression
|
|
89
|
+
static bool lt(Expression*, Expression*, std::string op);
|
|
91
90
|
// -- arithmetic on the combinations that matter
|
|
92
|
-
static Value* op_numbers(Memory_Manager&, enum Sass_OP, const Number&, const Number&,
|
|
93
|
-
static Value* op_number_color(Memory_Manager&, enum Sass_OP, const Number&, const Color&,
|
|
94
|
-
static Value* op_color_number(Memory_Manager&, enum Sass_OP, const Color&, const Number&,
|
|
95
|
-
static Value* op_colors(Memory_Manager&, enum Sass_OP, const Color&, const Color&,
|
|
96
|
-
static Value* op_strings(Memory_Manager&,
|
|
91
|
+
static Value* op_numbers(Memory_Manager&, enum Sass_OP, const Number&, const Number&, struct Sass_Inspect_Options opt, ParserState* pstate = 0);
|
|
92
|
+
static Value* op_number_color(Memory_Manager&, enum Sass_OP, const Number&, const Color&, struct Sass_Inspect_Options opt, ParserState* pstate = 0);
|
|
93
|
+
static Value* op_color_number(Memory_Manager&, enum Sass_OP, const Color&, const Number&, struct Sass_Inspect_Options opt, ParserState* pstate = 0);
|
|
94
|
+
static Value* op_colors(Memory_Manager&, enum Sass_OP, const Color&, const Color&, struct Sass_Inspect_Options opt, ParserState* pstate = 0);
|
|
95
|
+
static Value* op_strings(Memory_Manager&, Sass::Operand, Value&, Value&, struct Sass_Inspect_Options opt, ParserState* pstate = 0, bool interpolant = false);
|
|
97
96
|
|
|
98
97
|
private:
|
|
99
|
-
std::string
|
|
98
|
+
void interpolation(Context& ctx, std::string& res, Expression* ex, bool into_quotes, bool was_itpl = false);
|
|
100
99
|
|
|
101
100
|
};
|
|
102
101
|
|
data/ext/libsass/src/expand.cpp
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
#
|
|
2
|
-
#pragma warning(disable : 4503)
|
|
3
|
-
#endif
|
|
4
|
-
|
|
1
|
+
#include "sass.hpp"
|
|
5
2
|
#include <iostream>
|
|
6
3
|
#include <typeinfo>
|
|
7
4
|
|
|
8
5
|
#include "expand.hpp"
|
|
9
6
|
#include "bind.hpp"
|
|
10
7
|
#include "eval.hpp"
|
|
11
|
-
#include "to_string.hpp"
|
|
12
8
|
#include "backtrace.hpp"
|
|
13
9
|
#include "context.hpp"
|
|
14
10
|
#include "parser.hpp"
|
|
@@ -20,6 +16,7 @@ namespace Sass {
|
|
|
20
16
|
eval(Eval(*this)),
|
|
21
17
|
env_stack(std::vector<Env*>()),
|
|
22
18
|
block_stack(std::vector<Block*>()),
|
|
19
|
+
call_stack(std::vector<AST_Node*>()),
|
|
23
20
|
property_stack(std::vector<String*>()),
|
|
24
21
|
selector_stack(std::vector<Selector_List*>()),
|
|
25
22
|
backtrace_stack(std::vector<Backtrace*>()),
|
|
@@ -28,6 +25,7 @@ namespace Sass {
|
|
|
28
25
|
env_stack.push_back(0);
|
|
29
26
|
env_stack.push_back(env);
|
|
30
27
|
block_stack.push_back(0);
|
|
28
|
+
call_stack.push_back(0);
|
|
31
29
|
// import_stack.push_back(0);
|
|
32
30
|
property_stack.push_back(0);
|
|
33
31
|
selector_stack.push_back(0);
|
|
@@ -106,7 +104,7 @@ namespace Sass {
|
|
|
106
104
|
while (tail) {
|
|
107
105
|
if (tail->head()) for (Simple_Selector* header : tail->head()->elements()) {
|
|
108
106
|
if (dynamic_cast<Parent_Selector*>(header) == NULL) continue; // skip all others
|
|
109
|
-
|
|
107
|
+
std::string sel_str(complex_selector->to_string(ctx.c_options));
|
|
110
108
|
error("Base-level rules cannot contain the parent-selector-referencing character '&'.", header->pstate(), backtrace());
|
|
111
109
|
}
|
|
112
110
|
tail = tail->tail();
|
|
@@ -120,12 +118,21 @@ namespace Sass {
|
|
|
120
118
|
if (sel == 0) throw std::runtime_error("Expanded null selector");
|
|
121
119
|
|
|
122
120
|
selector_stack.push_back(sel);
|
|
121
|
+
Env* env = 0;
|
|
122
|
+
if (block_stack.back()->is_root()) {
|
|
123
|
+
env = new Env(environment());
|
|
124
|
+
env_stack.push_back(env);
|
|
125
|
+
}
|
|
123
126
|
Block* blk = r->block()->perform(this)->block();
|
|
124
127
|
Ruleset* rr = SASS_MEMORY_NEW(ctx.mem, Ruleset,
|
|
125
128
|
r->pstate(),
|
|
126
129
|
sel,
|
|
127
130
|
blk);
|
|
128
131
|
selector_stack.pop_back();
|
|
132
|
+
if (block_stack.back()->is_root()) {
|
|
133
|
+
env_stack.pop_back();
|
|
134
|
+
delete env;
|
|
135
|
+
}
|
|
129
136
|
rr->tabs(r->tabs());
|
|
130
137
|
|
|
131
138
|
return rr;
|
|
@@ -177,12 +184,15 @@ namespace Sass {
|
|
|
177
184
|
|
|
178
185
|
Statement* Expand::operator()(Media_Block* m)
|
|
179
186
|
{
|
|
180
|
-
To_String to_string(&ctx);
|
|
181
187
|
Expression* mq = m->media_queries()->perform(&eval);
|
|
182
|
-
|
|
188
|
+
std::string str_mq(mq->to_string(ctx.c_options));
|
|
189
|
+
char* str = sass_strdup(str_mq.c_str());
|
|
190
|
+
ctx.strings.push_back(str);
|
|
191
|
+
Parser p(Parser::from_c_str(str, ctx, mq->pstate()));
|
|
192
|
+
mq = p.parse_media_queries();
|
|
183
193
|
Media_Block* mm = SASS_MEMORY_NEW(ctx.mem, Media_Block,
|
|
184
194
|
m->pstate(),
|
|
185
|
-
static_cast<List*>(mq),
|
|
195
|
+
static_cast<List*>(mq->perform(&eval)),
|
|
186
196
|
m->block()->perform(this)->block(),
|
|
187
197
|
0);
|
|
188
198
|
mm->tabs(m->tabs());
|
|
@@ -318,6 +328,11 @@ namespace Sass {
|
|
|
318
328
|
|
|
319
329
|
Statement* Expand::operator()(Import_Stub* i)
|
|
320
330
|
{
|
|
331
|
+
// get parent node from call stack
|
|
332
|
+
AST_Node* parent = call_stack.back();
|
|
333
|
+
if (parent && dynamic_cast<Block*>(parent) == NULL) {
|
|
334
|
+
error("Import directives may not be used within control directives or mixins.", i->pstate());
|
|
335
|
+
}
|
|
321
336
|
// we don't seem to need that actually afterall
|
|
322
337
|
Sass_Import_Entry import = sass_make_import(
|
|
323
338
|
i->imp_path().c_str(),
|
|
@@ -355,12 +370,18 @@ namespace Sass {
|
|
|
355
370
|
|
|
356
371
|
Statement* Expand::operator()(Comment* c)
|
|
357
372
|
{
|
|
373
|
+
eval.is_in_comment = true;
|
|
374
|
+
auto rv = SASS_MEMORY_NEW(ctx.mem, Comment, c->pstate(), static_cast<String*>(c->text()->perform(&eval)), c->is_important());
|
|
375
|
+
eval.is_in_comment = false;
|
|
358
376
|
// TODO: eval the text, once we're parsing/storing it as a String_Schema
|
|
359
|
-
return
|
|
377
|
+
return rv;
|
|
360
378
|
}
|
|
361
379
|
|
|
362
380
|
Statement* Expand::operator()(If* i)
|
|
363
381
|
{
|
|
382
|
+
Env env(environment(), true);
|
|
383
|
+
env_stack.push_back(&env);
|
|
384
|
+
call_stack.push_back(i);
|
|
364
385
|
if (*i->predicate()->perform(&eval)) {
|
|
365
386
|
append_block(i->block());
|
|
366
387
|
}
|
|
@@ -368,6 +389,8 @@ namespace Sass {
|
|
|
368
389
|
Block* alt = i->alternative();
|
|
369
390
|
if (alt) append_block(alt);
|
|
370
391
|
}
|
|
392
|
+
call_stack.pop_back();
|
|
393
|
+
env_stack.pop_back();
|
|
371
394
|
return 0;
|
|
372
395
|
}
|
|
373
396
|
|
|
@@ -378,11 +401,11 @@ namespace Sass {
|
|
|
378
401
|
std::string variable(f->variable());
|
|
379
402
|
Expression* low = f->lower_bound()->perform(&eval);
|
|
380
403
|
if (low->concrete_type() != Expression::NUMBER) {
|
|
381
|
-
|
|
404
|
+
throw Exception::TypeMismatch(*low, "integer");
|
|
382
405
|
}
|
|
383
406
|
Expression* high = f->upper_bound()->perform(&eval);
|
|
384
407
|
if (high->concrete_type() != Expression::NUMBER) {
|
|
385
|
-
|
|
408
|
+
throw Exception::TypeMismatch(*high, "integer");
|
|
386
409
|
}
|
|
387
410
|
Number* sass_start = static_cast<Number*>(low);
|
|
388
411
|
Number* sass_end = static_cast<Number*>(high);
|
|
@@ -396,10 +419,11 @@ namespace Sass {
|
|
|
396
419
|
double start = sass_start->value();
|
|
397
420
|
double end = sass_end->value();
|
|
398
421
|
// only create iterator once in this environment
|
|
399
|
-
Env
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
env->
|
|
422
|
+
Env env(environment(), true);
|
|
423
|
+
env_stack.push_back(&env);
|
|
424
|
+
call_stack.push_back(f);
|
|
425
|
+
Number* it = SASS_MEMORY_NEW(env.mem, Number, low->pstate(), start, sass_end->unit());
|
|
426
|
+
env.set_local(variable, it);
|
|
403
427
|
Block* body = f->block();
|
|
404
428
|
if (start < end) {
|
|
405
429
|
if (f->is_inclusive()) ++end;
|
|
@@ -407,7 +431,7 @@ namespace Sass {
|
|
|
407
431
|
i < end;
|
|
408
432
|
++i) {
|
|
409
433
|
it->value(i);
|
|
410
|
-
env
|
|
434
|
+
env.set_local(variable, it);
|
|
411
435
|
append_block(body);
|
|
412
436
|
}
|
|
413
437
|
} else {
|
|
@@ -416,13 +440,12 @@ namespace Sass {
|
|
|
416
440
|
i > end;
|
|
417
441
|
--i) {
|
|
418
442
|
it->value(i);
|
|
419
|
-
env
|
|
443
|
+
env.set_local(variable, it);
|
|
420
444
|
append_block(body);
|
|
421
445
|
}
|
|
422
446
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
else env->set_local(variable, old_var);
|
|
447
|
+
call_stack.pop_back();
|
|
448
|
+
env_stack.pop_back();
|
|
426
449
|
return 0;
|
|
427
450
|
}
|
|
428
451
|
|
|
@@ -432,11 +455,15 @@ namespace Sass {
|
|
|
432
455
|
{
|
|
433
456
|
std::vector<std::string> variables(e->variables());
|
|
434
457
|
Expression* expr = e->list()->perform(&eval);
|
|
435
|
-
|
|
458
|
+
Vectorized<Expression*>* list = 0;
|
|
436
459
|
Map* map = 0;
|
|
437
460
|
if (expr->concrete_type() == Expression::MAP) {
|
|
438
461
|
map = static_cast<Map*>(expr);
|
|
439
462
|
}
|
|
463
|
+
else if (Selector_List* ls = dynamic_cast<Selector_List*>(expr)) {
|
|
464
|
+
Listize listize(ctx.mem);
|
|
465
|
+
list = dynamic_cast<List*>(ls->perform(&listize));
|
|
466
|
+
}
|
|
440
467
|
else if (expr->concrete_type() != Expression::LIST) {
|
|
441
468
|
list = SASS_MEMORY_NEW(ctx.mem, List, expr->pstate(), 1, SASS_COMMA);
|
|
442
469
|
*list << expr;
|
|
@@ -445,12 +472,9 @@ namespace Sass {
|
|
|
445
472
|
list = static_cast<List*>(expr);
|
|
446
473
|
}
|
|
447
474
|
// remember variables and then reset them
|
|
448
|
-
Env
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
old_vars[i] = env->has_local(variables[i]) ? env->get_local(variables[i]) : 0;
|
|
452
|
-
env->set_local(variables[i], 0);
|
|
453
|
-
}
|
|
475
|
+
Env env(environment(), true);
|
|
476
|
+
env_stack.push_back(&env);
|
|
477
|
+
call_stack.push_back(e);
|
|
454
478
|
Block* body = e->block();
|
|
455
479
|
|
|
456
480
|
if (map) {
|
|
@@ -462,16 +486,19 @@ namespace Sass {
|
|
|
462
486
|
List* variable = SASS_MEMORY_NEW(ctx.mem, List, map->pstate(), 2, SASS_SPACE);
|
|
463
487
|
*variable << k;
|
|
464
488
|
*variable << v;
|
|
465
|
-
env
|
|
489
|
+
env.set_local(variables[0], variable);
|
|
466
490
|
} else {
|
|
467
|
-
env
|
|
468
|
-
env
|
|
491
|
+
env.set_local(variables[0], k);
|
|
492
|
+
env.set_local(variables[1], v);
|
|
469
493
|
}
|
|
470
494
|
append_block(body);
|
|
471
495
|
}
|
|
472
496
|
}
|
|
473
497
|
else {
|
|
474
|
-
bool arglist = list->is_arglist();
|
|
498
|
+
// bool arglist = list->is_arglist();
|
|
499
|
+
if (list->length() == 1 && dynamic_cast<Selector_List*>(list)) {
|
|
500
|
+
list = dynamic_cast<Vectorized<Expression*>*>(list);
|
|
501
|
+
}
|
|
475
502
|
for (size_t i = 0, L = list->length(); i < L; ++i) {
|
|
476
503
|
Expression* e = (*list)[i];
|
|
477
504
|
// unwrap value if the expression is an argument
|
|
@@ -480,33 +507,30 @@ namespace Sass {
|
|
|
480
507
|
if (List* scalars = dynamic_cast<List*>(e)) {
|
|
481
508
|
if (variables.size() == 1) {
|
|
482
509
|
Expression* var = scalars;
|
|
483
|
-
if (arglist) var = (*scalars)[0];
|
|
484
|
-
env
|
|
510
|
+
// if (arglist) var = (*scalars)[0];
|
|
511
|
+
env.set_local(variables[0], var);
|
|
485
512
|
} else {
|
|
486
513
|
for (size_t j = 0, K = variables.size(); j < K; ++j) {
|
|
487
514
|
Expression* res = j >= scalars->length()
|
|
488
515
|
? SASS_MEMORY_NEW(ctx.mem, Null, expr->pstate())
|
|
489
516
|
: (*scalars)[j]->perform(&eval);
|
|
490
|
-
env
|
|
517
|
+
env.set_local(variables[j], res);
|
|
491
518
|
}
|
|
492
519
|
}
|
|
493
520
|
} else {
|
|
494
521
|
if (variables.size() > 0) {
|
|
495
|
-
env
|
|
522
|
+
env.set_local(variables[0], e);
|
|
496
523
|
for (size_t j = 1, K = variables.size(); j < K; ++j) {
|
|
497
524
|
Expression* res = SASS_MEMORY_NEW(ctx.mem, Null, expr->pstate());
|
|
498
|
-
env
|
|
525
|
+
env.set_local(variables[j], res);
|
|
499
526
|
}
|
|
500
527
|
}
|
|
501
528
|
}
|
|
502
529
|
append_block(body);
|
|
503
530
|
}
|
|
504
531
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
if(!old_vars[j]) env->del_local(variables[j]);
|
|
508
|
-
else env->set_local(variables[j], old_vars[j]);
|
|
509
|
-
}
|
|
532
|
+
call_stack.pop_back();
|
|
533
|
+
env_stack.pop_back();
|
|
510
534
|
return 0;
|
|
511
535
|
}
|
|
512
536
|
|
|
@@ -514,9 +538,14 @@ namespace Sass {
|
|
|
514
538
|
{
|
|
515
539
|
Expression* pred = w->predicate();
|
|
516
540
|
Block* body = w->block();
|
|
541
|
+
Env env(environment(), true);
|
|
542
|
+
env_stack.push_back(&env);
|
|
543
|
+
call_stack.push_back(w);
|
|
517
544
|
while (*pred->perform(&eval)) {
|
|
518
545
|
append_block(body);
|
|
519
546
|
}
|
|
547
|
+
call_stack.pop_back();
|
|
548
|
+
env_stack.pop_back();
|
|
520
549
|
return 0;
|
|
521
550
|
}
|
|
522
551
|
|
|
@@ -526,20 +555,16 @@ namespace Sass {
|
|
|
526
555
|
return 0;
|
|
527
556
|
}
|
|
528
557
|
|
|
529
|
-
Statement* Expand::operator()(Extension* e)
|
|
530
|
-
{
|
|
531
|
-
To_String to_string(&ctx);
|
|
532
|
-
Selector_List* extender = dynamic_cast<Selector_List*>(selector());
|
|
533
|
-
if (!extender) return 0;
|
|
534
|
-
selector_stack.push_back(0);
|
|
535
558
|
|
|
536
|
-
|
|
537
|
-
|
|
559
|
+
void Expand::expand_selector_list(Selector* s, Selector_List* extender) {
|
|
560
|
+
|
|
561
|
+
if (Selector_List* sl = dynamic_cast<Selector_List*>(s)) {
|
|
562
|
+
for (Complex_Selector* complex_selector : sl->elements()) {
|
|
538
563
|
Complex_Selector* tail = complex_selector;
|
|
539
564
|
while (tail) {
|
|
540
565
|
if (tail->head()) for (Simple_Selector* header : tail->head()->elements()) {
|
|
541
566
|
if (dynamic_cast<Parent_Selector*>(header) == NULL) continue; // skip all others
|
|
542
|
-
|
|
567
|
+
std::string sel_str(complex_selector->to_string(ctx.c_options));
|
|
543
568
|
error("Can't extend " + sel_str + ": can't extend parent selectors", header->pstate(), backtrace());
|
|
544
569
|
}
|
|
545
570
|
tail = tail->tail();
|
|
@@ -547,16 +572,17 @@ namespace Sass {
|
|
|
547
572
|
}
|
|
548
573
|
}
|
|
549
574
|
|
|
550
|
-
|
|
551
|
-
|
|
575
|
+
|
|
576
|
+
Selector_List* contextualized = dynamic_cast<Selector_List*>(s->perform(&eval));
|
|
577
|
+
if (contextualized == NULL) return;
|
|
552
578
|
for (auto complex_sel : contextualized->elements()) {
|
|
553
579
|
Complex_Selector* c = complex_sel;
|
|
554
580
|
if (!c->head() || c->tail()) {
|
|
555
|
-
|
|
581
|
+
std::string sel_str(contextualized->to_string(ctx.c_options));
|
|
556
582
|
error("Can't extend " + sel_str + ": can't extend nested selectors", c->pstate(), backtrace());
|
|
557
583
|
}
|
|
558
584
|
Compound_Selector* placeholder = c->head();
|
|
559
|
-
placeholder->is_optional(
|
|
585
|
+
placeholder->is_optional(s->is_optional());
|
|
560
586
|
for (size_t i = 0, L = extender->length(); i < L; ++i) {
|
|
561
587
|
Complex_Selector* sel = (*extender)[i];
|
|
562
588
|
if (!(sel->head() && sel->head()->length() > 0 &&
|
|
@@ -579,8 +605,16 @@ namespace Sass {
|
|
|
579
605
|
}
|
|
580
606
|
}
|
|
581
607
|
|
|
582
|
-
|
|
608
|
+
}
|
|
583
609
|
|
|
610
|
+
Statement* Expand::operator()(Extension* e)
|
|
611
|
+
{
|
|
612
|
+
if (Selector_List* extender = dynamic_cast<Selector_List*>(selector())) {
|
|
613
|
+
selector_stack.push_back(0);
|
|
614
|
+
Selector* s = e->selector();
|
|
615
|
+
expand_selector_list(s, extender);
|
|
616
|
+
selector_stack.pop_back();
|
|
617
|
+
}
|
|
584
618
|
return 0;
|
|
585
619
|
}
|
|
586
620
|
|
|
@@ -680,10 +714,12 @@ namespace Sass {
|
|
|
680
714
|
// process and add to last block on stack
|
|
681
715
|
inline void Expand::append_block(Block* b)
|
|
682
716
|
{
|
|
717
|
+
if (b->is_root()) call_stack.push_back(b);
|
|
683
718
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
|
684
719
|
Statement* ith = (*b)[i]->perform(this);
|
|
685
720
|
if (ith) *block_stack.back() << ith;
|
|
686
721
|
}
|
|
722
|
+
if (b->is_root()) call_stack.pop_back();
|
|
687
723
|
}
|
|
688
724
|
|
|
689
725
|
}
|
data/ext/libsass/src/expand.hpp
CHANGED
|
@@ -30,6 +30,7 @@ namespace Sass {
|
|
|
30
30
|
// it's easier to work with vectors
|
|
31
31
|
std::vector<Env*> env_stack;
|
|
32
32
|
std::vector<Block*> block_stack;
|
|
33
|
+
std::vector<AST_Node*> call_stack;
|
|
33
34
|
std::vector<String*> property_stack;
|
|
34
35
|
std::vector<Selector_List*> selector_stack;
|
|
35
36
|
std::vector<Backtrace*>backtrace_stack;
|
|
@@ -37,11 +38,12 @@ namespace Sass {
|
|
|
37
38
|
|
|
38
39
|
Statement* fallback_impl(AST_Node* n);
|
|
39
40
|
|
|
41
|
+
private:
|
|
42
|
+
void expand_selector_list(Selector*, Selector_List* extender);
|
|
43
|
+
|
|
40
44
|
public:
|
|
41
45
|
Expand(Context&, Env*, Backtrace*);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
using Operation<Statement*>::operator();
|
|
46
|
+
~Expand() { }
|
|
45
47
|
|
|
46
48
|
Statement* operator()(Block*);
|
|
47
49
|
Statement* operator()(Ruleset*);
|
data/ext/libsass/src/extend.cpp
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
#
|
|
2
|
-
#pragma warning(disable : 4503)
|
|
3
|
-
#endif
|
|
4
|
-
|
|
1
|
+
#include "sass.hpp"
|
|
5
2
|
#include "extend.hpp"
|
|
6
3
|
#include "context.hpp"
|
|
7
|
-
#include "to_string.hpp"
|
|
8
4
|
#include "backtrace.hpp"
|
|
9
5
|
#include "paths.hpp"
|
|
10
6
|
#include "parser.hpp"
|
|
@@ -85,23 +81,20 @@ namespace Sass {
|
|
|
85
81
|
|
|
86
82
|
|
|
87
83
|
std::ostream& operator<<(std::ostream& os, Compound_Selector& compoundSelector) {
|
|
88
|
-
To_String to_string;
|
|
89
84
|
for (size_t i = 0, L = compoundSelector.length(); i < L; ++i) {
|
|
90
85
|
if (i > 0) os << ", ";
|
|
91
|
-
os << compoundSelector[i]->
|
|
86
|
+
os << compoundSelector[i]->to_string();
|
|
92
87
|
}
|
|
93
88
|
return os;
|
|
94
89
|
}
|
|
95
90
|
|
|
96
91
|
std::ostream& operator<<(std::ostream& os, Simple_Selector& simpleSelector) {
|
|
97
|
-
|
|
98
|
-
os << simpleSelector.perform(&to_string);
|
|
92
|
+
os << simpleSelector.to_string();
|
|
99
93
|
return os;
|
|
100
94
|
}
|
|
101
95
|
|
|
102
96
|
// Print a string representation of a Compound_Selector
|
|
103
97
|
static void printSimpleSelector(Simple_Selector* pSimpleSelector, const char* message=NULL, bool newline=true) {
|
|
104
|
-
To_String to_string;
|
|
105
98
|
|
|
106
99
|
if (message) {
|
|
107
100
|
std::cerr << message;
|
|
@@ -125,7 +118,6 @@ namespace Sass {
|
|
|
125
118
|
|
|
126
119
|
// Print a string representation of a Compound_Selector
|
|
127
120
|
static void printCompoundSelector(Compound_Selector* pCompoundSelector, const char* message=NULL, bool newline=true) {
|
|
128
|
-
To_String to_string;
|
|
129
121
|
|
|
130
122
|
if (message) {
|
|
131
123
|
std::cerr << message;
|
|
@@ -144,7 +136,6 @@ namespace Sass {
|
|
|
144
136
|
|
|
145
137
|
|
|
146
138
|
std::ostream& operator<<(std::ostream& os, Complex_Selector& complexSelector) {
|
|
147
|
-
To_String to_string;
|
|
148
139
|
|
|
149
140
|
os << "[";
|
|
150
141
|
Complex_Selector* pIter = &complexSelector;
|
|
@@ -164,7 +155,7 @@ namespace Sass {
|
|
|
164
155
|
first = false;
|
|
165
156
|
|
|
166
157
|
if (pIter->head()) {
|
|
167
|
-
os << pIter->head()->
|
|
158
|
+
os << pIter->head()->to_string();
|
|
168
159
|
} else {
|
|
169
160
|
os << "NULL_HEAD";
|
|
170
161
|
}
|
|
@@ -179,7 +170,6 @@ namespace Sass {
|
|
|
179
170
|
|
|
180
171
|
// Print a string representation of a Complex_Selector
|
|
181
172
|
static void printComplexSelector(Complex_Selector* pComplexSelector, const char* message=NULL, bool newline=true) {
|
|
182
|
-
To_String to_string;
|
|
183
173
|
|
|
184
174
|
if (message) {
|
|
185
175
|
std::cerr << message;
|
|
@@ -197,7 +187,6 @@ namespace Sass {
|
|
|
197
187
|
}
|
|
198
188
|
|
|
199
189
|
static void printSelsNewSeqPairCollection(SelsNewSeqPairCollection& collection, const char* message=NULL, bool newline=true) {
|
|
200
|
-
To_String to_string;
|
|
201
190
|
|
|
202
191
|
if (message) {
|
|
203
192
|
std::cerr << message;
|
|
@@ -225,7 +214,6 @@ namespace Sass {
|
|
|
225
214
|
|
|
226
215
|
// Print a string representation of a SourcesSet
|
|
227
216
|
static void printSourcesSet(SourcesSet& sources, Context& ctx, const char* message=NULL, bool newline=true) {
|
|
228
|
-
To_String to_string;
|
|
229
217
|
|
|
230
218
|
if (message) {
|
|
231
219
|
std::cerr << message;
|
|
@@ -1558,8 +1546,6 @@ namespace Sass {
|
|
|
1558
1546
|
Node extendedSelectors = Node::createCollection();
|
|
1559
1547
|
// extendedSelectors.got_line_feed = true;
|
|
1560
1548
|
|
|
1561
|
-
To_String to_string;
|
|
1562
|
-
|
|
1563
1549
|
SubsetMapEntries entries = subset_map.get_v(pSelector->to_str_vec());
|
|
1564
1550
|
|
|
1565
1551
|
typedef std::vector<std::pair<Complex_Selector, std::vector<ExtensionPair> > > GroupedByToAResult;
|
|
@@ -1591,6 +1577,7 @@ namespace Sass {
|
|
|
1591
1577
|
for (size_t index = 0; index < pCompound->length(); index++) {
|
|
1592
1578
|
Simple_Selector* pSimpleSelector = (*pCompound)[index];
|
|
1593
1579
|
(*pSels) << pSimpleSelector;
|
|
1580
|
+
pCompound->extended(true);
|
|
1594
1581
|
}
|
|
1595
1582
|
}
|
|
1596
1583
|
|
|
@@ -1732,18 +1719,32 @@ namespace Sass {
|
|
|
1732
1719
|
Compound_Selector* pHead = pIter->head();
|
|
1733
1720
|
|
|
1734
1721
|
if (pHead) {
|
|
1722
|
+
for (Simple_Selector* pSimple : *pHead) {
|
|
1723
|
+
if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(pSimple)) {
|
|
1724
|
+
if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
|
|
1725
|
+
for (Complex_Selector* cs : sl->elements()) {
|
|
1726
|
+
while (cs) {
|
|
1727
|
+
if (complexSelectorHasExtension(cs, ctx, subset_map)) {
|
|
1728
|
+
hasExtension = true;
|
|
1729
|
+
break;
|
|
1730
|
+
}
|
|
1731
|
+
cs = cs->tail();
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1735
1737
|
SubsetMapEntries entries = subset_map.get_v(pHead->to_str_vec());
|
|
1736
1738
|
for (ExtensionPair ext : entries) {
|
|
1737
1739
|
// check if both selectors have the same media block parent
|
|
1738
1740
|
if (ext.first->media_block() == pComplexSelector->media_block()) continue;
|
|
1739
|
-
To_String to_string(&ctx);
|
|
1740
1741
|
if (ext.second->media_block() == 0) continue;
|
|
1741
1742
|
if (pComplexSelector->media_block() &&
|
|
1742
1743
|
ext.second->media_block()->media_queries() &&
|
|
1743
1744
|
pComplexSelector->media_block()->media_queries()
|
|
1744
1745
|
) {
|
|
1745
|
-
std::string query_left(ext.second->media_block()->media_queries()->
|
|
1746
|
-
std::string query_right(pComplexSelector->media_block()->media_queries()->
|
|
1746
|
+
std::string query_left(ext.second->media_block()->media_queries()->to_string(ctx.c_options));
|
|
1747
|
+
std::string query_right(pComplexSelector->media_block()->media_queries()->to_string(ctx.c_options));
|
|
1747
1748
|
if (query_left == query_right) continue;
|
|
1748
1749
|
}
|
|
1749
1750
|
|
|
@@ -1754,7 +1755,7 @@ namespace Sass {
|
|
|
1754
1755
|
std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
|
|
1755
1756
|
err << "You may not @extend an outer selector from within @media.\n";
|
|
1756
1757
|
err << "You may only @extend selectors within the same directive.\n";
|
|
1757
|
-
err << "From \"@extend " << ext.second->
|
|
1758
|
+
err << "From \"@extend " << ext.second->to_string(ctx.c_options) << "\"";
|
|
1758
1759
|
err << " on line " << pstate.line+1 << " of " << rel_path << "\n";
|
|
1759
1760
|
error(err.str(), pComplexSelector->pstate());
|
|
1760
1761
|
}
|
|
@@ -1764,29 +1765,6 @@ namespace Sass {
|
|
|
1764
1765
|
pIter = pIter->tail();
|
|
1765
1766
|
}
|
|
1766
1767
|
|
|
1767
|
-
if (!hasExtension) {
|
|
1768
|
-
/* ToDo: don't break stuff
|
|
1769
|
-
std::stringstream err;
|
|
1770
|
-
To_String to_string(&ctx);
|
|
1771
|
-
std::string cwd(Sass::File::get_cwd());
|
|
1772
|
-
std::string sel1(pComplexSelector->perform(&to_string));
|
|
1773
|
-
Compound_Selector* pExtendSelector = 0;
|
|
1774
|
-
for (auto i : subset_map.values()) {
|
|
1775
|
-
if (i.first == pComplexSelector) {
|
|
1776
|
-
pExtendSelector = i.second;
|
|
1777
|
-
break;
|
|
1778
|
-
}
|
|
1779
|
-
}
|
|
1780
|
-
if (!pExtendSelector || !pExtendSelector->is_optional()) {
|
|
1781
|
-
std::string sel2(pExtendSelector ? pExtendSelector->perform(&to_string) : "[unknown]");
|
|
1782
|
-
err << "\"" << sel1 << "\" failed to @extend \"" << sel2 << "\"\n";
|
|
1783
|
-
err << "The selector \"" << sel2 << "\" was not found.\n";
|
|
1784
|
-
err << "Use \"@extend " << sel2 << " !optional\" if the extend should be able to fail.";
|
|
1785
|
-
error(err.str(), pExtendSelector ? pExtendSelector->pstate() : pComplexSelector->pstate());
|
|
1786
|
-
}
|
|
1787
|
-
*/
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
1768
|
return hasExtension;
|
|
1791
1769
|
}
|
|
1792
1770
|
|
|
@@ -1928,8 +1906,6 @@ namespace Sass {
|
|
|
1928
1906
|
*/
|
|
1929
1907
|
Selector_List* Extend::extendSelectorList(Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subset_map, bool isReplace, bool& extendedSomething) {
|
|
1930
1908
|
|
|
1931
|
-
To_String to_string(&ctx);
|
|
1932
|
-
|
|
1933
1909
|
Selector_List* pNewSelectors = SASS_MEMORY_NEW(ctx.mem, Selector_List, pSelectorList->pstate(), pSelectorList->length());
|
|
1934
1910
|
|
|
1935
1911
|
extendedSomething = false;
|
|
@@ -1967,6 +1943,21 @@ namespace Sass {
|
|
|
1967
1943
|
}
|
|
1968
1944
|
}
|
|
1969
1945
|
|
|
1946
|
+
for (Complex_Selector* cs : *pNewSelectors) {
|
|
1947
|
+
while (cs) {
|
|
1948
|
+
if (cs->head()) {
|
|
1949
|
+
for (Simple_Selector* ss : *cs->head()) {
|
|
1950
|
+
if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(ss)) {
|
|
1951
|
+
if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
|
|
1952
|
+
bool extended = false;
|
|
1953
|
+
ws->selector(extendSelectorList(sl, ctx, subset_map, false, extended));
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
cs = cs->tail();
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1970
1961
|
return pNewSelectors;
|
|
1971
1962
|
|
|
1972
1963
|
}
|
|
@@ -2006,9 +1997,8 @@ namespace Sass {
|
|
|
2006
1997
|
// Extend a ruleset by extending the selectors and updating them on the ruleset. The block's rules don't need to change.
|
|
2007
1998
|
template <typename ObjectType>
|
|
2008
1999
|
static void extendObjectWithSelectorAndBlock(ObjectType* pObject, Context& ctx, ExtensionSubsetMap& subset_map) {
|
|
2009
|
-
To_String to_string(&ctx);
|
|
2010
2000
|
|
|
2011
|
-
DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << static_cast<Selector_List*>(pObject->selector())->
|
|
2001
|
+
DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << static_cast<Selector_List*>(pObject->selector())->to_string(ctx.c_options))
|
|
2012
2002
|
|
|
2013
2003
|
// Ruby sass seems to filter nodes that don't have any content well before we get here. I'm not sure the repercussions
|
|
2014
2004
|
// of doing so, so for now, let's just not extend things that won't be output later.
|
|
@@ -2021,8 +2011,8 @@ namespace Sass {
|
|
|
2021
2011
|
Selector_List* pNewSelectorList = Extend::extendSelectorList(static_cast<Selector_List*>(pObject->selector()), ctx, subset_map, false, extendedSomething);
|
|
2022
2012
|
|
|
2023
2013
|
if (extendedSomething && pNewSelectorList) {
|
|
2024
|
-
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << static_cast<Selector_List*>(pObject->selector())->
|
|
2025
|
-
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND SETTING NEW SELECTORS: " << pNewSelectorList->
|
|
2014
|
+
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << static_cast<Selector_List*>(pObject->selector())->to_string(ctx.c_options))
|
|
2015
|
+
DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND SETTING NEW SELECTORS: " << pNewSelectorList->to_string(ctx.c_options))
|
|
2026
2016
|
pNewSelectorList->remove_parent_selectors();
|
|
2027
2017
|
pObject->selector(pNewSelectorList);
|
|
2028
2018
|
} else {
|
|
@@ -2041,6 +2031,25 @@ namespace Sass {
|
|
|
2041
2031
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
|
2042
2032
|
(*b)[i]->perform(this);
|
|
2043
2033
|
}
|
|
2034
|
+
// do final check if everything was extended
|
|
2035
|
+
// we set `extended` flag on extended selectors
|
|
2036
|
+
if (b->is_root()) {
|
|
2037
|
+
// debug_subset_map(subset_map);
|
|
2038
|
+
for(auto const &it : subset_map.values()) {
|
|
2039
|
+
Complex_Selector* sel = it.first ? it.first->first() : NULL;
|
|
2040
|
+
Compound_Selector* ext = it.second ? it.second : NULL;
|
|
2041
|
+
if (ext && (ext->extended() || ext->is_optional())) continue;
|
|
2042
|
+
std::string str_sel(sel->to_string({ NESTED, 5 }));
|
|
2043
|
+
std::string str_ext(ext->to_string({ NESTED, 5 }));
|
|
2044
|
+
// debug_ast(sel, "sel: ");
|
|
2045
|
+
// debug_ast(ext, "ext: ");
|
|
2046
|
+
error("\"" + str_sel + "\" failed to @extend \"" + str_ext + "\".\n"
|
|
2047
|
+
"The selector \"" + str_ext + "\" was not found.\n"
|
|
2048
|
+
"Use \"@extend " + str_ext + " !optional\" if the"
|
|
2049
|
+
" extend should be able to fail.", ext->pstate());
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2044
2053
|
}
|
|
2045
2054
|
|
|
2046
2055
|
void Extend::operator()(Ruleset* pRuleset)
|