sassc 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/libsass/ast.cpp +124 -43
- data/ext/libsass/ast.hpp +15 -7
- data/ext/libsass/bind.cpp +57 -10
- data/ext/libsass/context.cpp +9 -7
- data/ext/libsass/contextualize.cpp +7 -0
- data/ext/libsass/contextualize_eval.cpp +1 -1
- data/ext/libsass/debugger.hpp +27 -70
- data/ext/libsass/emitter.cpp +5 -2
- data/ext/libsass/emitter.hpp +7 -1
- data/ext/libsass/eval.cpp +27 -13
- data/ext/libsass/expand.cpp +2 -2
- data/ext/libsass/functions.cpp +34 -9
- data/ext/libsass/functions.hpp +2 -0
- data/ext/libsass/inspect.cpp +111 -39
- data/ext/libsass/lexer.cpp +8 -8
- data/ext/libsass/lexer.hpp +8 -8
- data/ext/libsass/output.cpp +13 -5
- data/ext/libsass/parser.cpp +185 -46
- data/ext/libsass/parser.hpp +4 -0
- data/ext/libsass/prelexer.cpp +58 -7
- data/ext/libsass/prelexer.hpp +20 -2
- data/ext/libsass/sass_values.cpp +1 -1
- data/ext/libsass/sass_values.h +1 -1
- data/ext/libsass/to_string.cpp +3 -3
- data/ext/libsass/to_string.hpp +2 -1
- data/ext/libsass/units.cpp +134 -34
- data/ext/libsass/units.hpp +78 -4
- data/ext/libsass/util.cpp +8 -10
- data/ext/libsass/util.hpp +1 -1
- data/lib/sassc/engine.rb +7 -3
- data/lib/sassc/version.rb +1 -1
- data/test/native_test.rb +1 -1
- data/test/output_style_test.rb +7 -0
- metadata +2 -2
data/ext/libsass/context.cpp
CHANGED
@@ -4,6 +4,13 @@
|
|
4
4
|
#define PATH_SEP ':'
|
5
5
|
#endif
|
6
6
|
|
7
|
+
#include <string>
|
8
|
+
#include <cstdlib>
|
9
|
+
#include <cstring>
|
10
|
+
#include <iomanip>
|
11
|
+
#include <sstream>
|
12
|
+
#include <iostream>
|
13
|
+
|
7
14
|
#include "ast.hpp"
|
8
15
|
#include "util.hpp"
|
9
16
|
#include "sass.h"
|
@@ -29,13 +36,6 @@
|
|
29
36
|
#include "prelexer.hpp"
|
30
37
|
#include "emitter.hpp"
|
31
38
|
|
32
|
-
#include <string>
|
33
|
-
#include <cstdlib>
|
34
|
-
#include <cstring>
|
35
|
-
#include <iomanip>
|
36
|
-
#include <sstream>
|
37
|
-
#include <iostream>
|
38
|
-
|
39
39
|
namespace Sass {
|
40
40
|
using namespace Constants;
|
41
41
|
using namespace File;
|
@@ -539,6 +539,8 @@ namespace Sass {
|
|
539
539
|
// Misc Functions
|
540
540
|
register_function(ctx, inspect_sig, inspect, env);
|
541
541
|
register_function(ctx, unique_id_sig, unique_id, env);
|
542
|
+
// Selector functions
|
543
|
+
register_function(ctx, is_superselector_sig, is_superselector, env);
|
542
544
|
}
|
543
545
|
|
544
546
|
void register_c_functions(Context& ctx, Env* env, Sass_Function_List descrs)
|
@@ -32,12 +32,19 @@ namespace Sass {
|
|
32
32
|
Selector_List* ss = 0;
|
33
33
|
if (p) {
|
34
34
|
ss = new (ctx.mem) Selector_List(s->pstate(), p->length() * s->length());
|
35
|
+
if (s->length() == 0) {
|
36
|
+
Complex_Selector* comb = static_cast<Complex_Selector*>(parent->perform(this));
|
37
|
+
if (parent->has_line_feed()) comb->has_line_feed(true);
|
38
|
+
if (comb) *ss << comb;
|
39
|
+
else cerr << "Warning: contextualize returned null" << endl;
|
40
|
+
}
|
35
41
|
for (size_t i = 0, L = p->length(); i < L; ++i) {
|
36
42
|
for (size_t j = 0, L = s->length(); j < L; ++j) {
|
37
43
|
parent = (*p)[i];
|
38
44
|
Complex_Selector* comb = static_cast<Complex_Selector*>((*s)[j]->perform(this));
|
39
45
|
if (parent->has_line_feed()) comb->has_line_feed(true);
|
40
46
|
if (comb) *ss << comb;
|
47
|
+
else cerr << "Warning: contextualize returned null" << endl;
|
41
48
|
}
|
42
49
|
}
|
43
50
|
}
|
@@ -64,7 +64,7 @@ namespace Sass {
|
|
64
64
|
// the value might be interpolated; evaluate it
|
65
65
|
String* v = s->value();
|
66
66
|
if (v && eval) {
|
67
|
-
Eval* eval_with = eval->with(env, backtrace);
|
67
|
+
Eval* eval_with = eval->with(parent, env, backtrace);
|
68
68
|
v = static_cast<String*>(v->perform(eval_with));
|
69
69
|
}
|
70
70
|
To_String toString;
|
data/ext/libsass/debugger.hpp
CHANGED
@@ -264,6 +264,9 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
|
|
264
264
|
cerr << ind << "If " << block;
|
265
265
|
cerr << " (" << pstate_source_position(node) << ")";
|
266
266
|
cerr << " " << block->tabs() << endl;
|
267
|
+
debug_ast(block->predicate(), ind + " = ");
|
268
|
+
debug_ast(block->consequent(), ind + " <>");
|
269
|
+
debug_ast(block->alternative(), ind + " ><");
|
267
270
|
} else if (dynamic_cast<Return*>(node)) {
|
268
271
|
Return* block = dynamic_cast<Return*>(node);
|
269
272
|
cerr << ind << "Return " << block;
|
@@ -290,7 +293,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
|
|
290
293
|
cerr << ind << "Import " << block;
|
291
294
|
cerr << " (" << pstate_source_position(node) << ")";
|
292
295
|
cerr << " " << block->tabs() << endl;
|
293
|
-
debug_ast(block->media_queries(), ind + " @ ");
|
296
|
+
// debug_ast(block->media_queries(), ind + " @ ");
|
294
297
|
// vector<string> files_;
|
295
298
|
for (auto imp : block->urls()) debug_ast(imp, "@ ", env);
|
296
299
|
} else if (dynamic_cast<Assignment*>(node)) {
|
@@ -353,7 +356,9 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
|
|
353
356
|
if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
|
354
357
|
} else if (dynamic_cast<Mixin_Call*>(node)) {
|
355
358
|
Mixin_Call* block = dynamic_cast<Mixin_Call*>(node);
|
356
|
-
cerr << ind << "Mixin_Call " << block << " " << block->tabs()
|
359
|
+
cerr << ind << "Mixin_Call " << block << " " << block->tabs();
|
360
|
+
cerr << " [" << block->name() << "]" << endl;
|
361
|
+
debug_ast(block->arguments(), ind + " args: ");
|
357
362
|
if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
|
358
363
|
} else if (dynamic_cast<Ruleset*>(node)) {
|
359
364
|
Ruleset* ruleset = dynamic_cast<Ruleset*>(node);
|
@@ -380,9 +385,6 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
|
|
380
385
|
cerr << endl;
|
381
386
|
} else if (dynamic_cast<Variable*>(node)) {
|
382
387
|
Variable* expression = dynamic_cast<Variable*>(node);
|
383
|
-
cerr << ind << "Variable " << expression << " [" << expression->name() << "]";
|
384
|
-
if (expression->is_delayed()) cerr << " [delayed]";
|
385
|
-
cerr << endl;
|
386
388
|
cerr << ind << "Variable " << expression;
|
387
389
|
cerr << " (" << pstate_source_position(node) << ")";
|
388
390
|
cerr << " [" << expression->name() << "]" << endl;
|
@@ -390,9 +392,6 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
|
|
390
392
|
if (env && env->has(name)) debug_ast(static_cast<Expression*>((*env)[name]), ind + " -> ", env);
|
391
393
|
} else if (dynamic_cast<Function_Call_Schema*>(node)) {
|
392
394
|
Function_Call_Schema* expression = dynamic_cast<Function_Call_Schema*>(node);
|
393
|
-
cerr << ind << "Function_Call_Schema " << expression << "]";
|
394
|
-
if (expression->is_delayed()) cerr << " [delayed]";
|
395
|
-
cerr << endl;
|
396
395
|
cerr << ind << "Function_Call_Schema " << expression;
|
397
396
|
cerr << " (" << pstate_source_position(node) << ")";
|
398
397
|
cerr << "" << endl;
|
@@ -400,29 +399,19 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
|
|
400
399
|
debug_ast(expression->arguments(), ind + " args: ", env);
|
401
400
|
} else if (dynamic_cast<Function_Call*>(node)) {
|
402
401
|
Function_Call* expression = dynamic_cast<Function_Call*>(node);
|
403
|
-
cerr << ind << "Function_Call " << expression << " [" << expression->name() << "]";
|
404
|
-
if (expression->is_delayed()) cerr << " [delayed]";
|
405
|
-
cerr << endl;
|
406
402
|
cerr << ind << "Function_Call " << expression;
|
407
403
|
cerr << " (" << pstate_source_position(node) << ")";
|
408
404
|
cerr << " [" << expression->name() << "]" << endl;
|
409
405
|
debug_ast(expression->arguments(), ind + " args: ", env);
|
410
406
|
} else if (dynamic_cast<Arguments*>(node)) {
|
411
407
|
Arguments* expression = dynamic_cast<Arguments*>(node);
|
412
|
-
cerr << ind << "Arguments " << expression << "]";
|
413
|
-
if (expression->is_delayed()) cerr << " [delayed]";
|
414
|
-
cerr << endl;
|
415
408
|
cerr << ind << "Arguments " << expression;
|
409
|
+
if (expression->is_delayed()) cerr << " [delayed]";
|
416
410
|
cerr << " (" << pstate_source_position(node) << ")";
|
417
411
|
cerr << endl;
|
418
412
|
for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
|
419
413
|
} else if (dynamic_cast<Argument*>(node)) {
|
420
414
|
Argument* expression = dynamic_cast<Argument*>(node);
|
421
|
-
cerr << ind << "Argument " << expression << " [" << expression->value() << "]";
|
422
|
-
if (expression->is_delayed()) cerr << " [delayed]";
|
423
|
-
if (expression->is_rest_argument()) cerr << " [is_rest_argument]";
|
424
|
-
if (expression->is_keyword_argument()) cerr << " [is_keyword_argument]";
|
425
|
-
cerr << endl;
|
426
415
|
cerr << ind << "Argument " << expression;
|
427
416
|
cerr << " (" << pstate_source_position(node) << ")";
|
428
417
|
cerr << " [" << expression->value() << "]";
|
@@ -447,21 +436,15 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
|
|
447
436
|
cerr << " [rest: " << expression->is_rest_parameter() << "] " << endl;
|
448
437
|
} else if (dynamic_cast<Unary_Expression*>(node)) {
|
449
438
|
Unary_Expression* expression = dynamic_cast<Unary_Expression*>(node);
|
450
|
-
cerr << ind << "Unary_Expression " << expression << " [" << expression->type_name() << "]";
|
451
|
-
if (expression->is_delayed()) cerr << " [delayed]";
|
452
|
-
cerr << endl;
|
453
439
|
cerr << ind << "Unary_Expression " << expression;
|
454
440
|
cerr << " (" << pstate_source_position(node) << ")";
|
455
441
|
cerr << " [" << expression->type() << "]" << endl;
|
456
442
|
debug_ast(expression->operand(), ind + " operand: ", env);
|
457
443
|
} else if (dynamic_cast<Binary_Expression*>(node)) {
|
458
444
|
Binary_Expression* expression = dynamic_cast<Binary_Expression*>(node);
|
459
|
-
cerr << ind << "Binary_Expression " << expression << " [" << expression->type_name() << "]";
|
460
|
-
if (expression->is_delayed()) cerr << " [delayed]";
|
461
|
-
cerr << endl;
|
462
445
|
cerr << ind << "Binary_Expression " << expression;
|
463
446
|
cerr << " (" << pstate_source_position(node) << ")";
|
464
|
-
cerr << " [" << expression->
|
447
|
+
cerr << " [" << expression->type_name() << "]" << endl;
|
465
448
|
debug_ast(expression->left(), ind + " left: ", env);
|
466
449
|
debug_ast(expression->right(), ind + " right: ", env);
|
467
450
|
} else if (dynamic_cast<Map*>(node)) {
|
@@ -469,6 +452,10 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
|
|
469
452
|
cerr << ind << "Map " << expression;
|
470
453
|
cerr << " (" << pstate_source_position(node) << ")";
|
471
454
|
cerr << " [Hashed]" << endl;
|
455
|
+
// for (auto i : expression->elements()) {
|
456
|
+
// debug_ast(i.first, ind + " key: ");
|
457
|
+
// debug_ast(i.second, ind + " val: ");
|
458
|
+
// }
|
472
459
|
} else if (dynamic_cast<List*>(node)) {
|
473
460
|
List* expression = dynamic_cast<List*>(node);
|
474
461
|
cerr << ind << "List " << expression;
|
@@ -476,9 +463,6 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
|
|
476
463
|
cerr << " (" << expression->length() << ") " <<
|
477
464
|
(expression->separator() == Sass::List::Separator::COMMA ? "Comma " : "Space ") <<
|
478
465
|
" [delayed: " << expression->is_delayed() << "] " <<
|
479
|
-
" [interpolant: " << expression->is_interpolant() << "]";
|
480
|
-
if (expression->is_arglist()) cerr << " [is_arglist]";
|
481
|
-
cerr << endl;
|
482
466
|
" [interpolant: " << expression->is_interpolant() << "] " <<
|
483
467
|
" [arglist: " << expression->is_arglist() << "] " <<
|
484
468
|
endl;
|
@@ -490,79 +474,52 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
|
|
490
474
|
cerr << " [Statement]" << endl;
|
491
475
|
} else if (dynamic_cast<Boolean*>(node)) {
|
492
476
|
Boolean* expression = dynamic_cast<Boolean*>(node);
|
493
|
-
cerr << ind << "Boolean " << expression << " [" << expression->value() << "]";
|
494
|
-
if (expression->is_delayed()) cerr << " [delayed]";
|
495
|
-
cerr << endl;
|
496
477
|
cerr << ind << "Boolean " << expression;
|
497
478
|
cerr << " (" << pstate_source_position(node) << ")";
|
498
479
|
cerr << " [" << expression->value() << "]" << endl;
|
499
480
|
} else if (dynamic_cast<Color*>(node)) {
|
500
481
|
Color* expression = dynamic_cast<Color*>(node);
|
501
|
-
cerr << ind << "Color " << expression << " [" << expression->r() << ":" << expression->g() << ":" << expression->b() << "@" << expression->a() << "]";
|
502
|
-
if (expression->is_delayed()) cerr << " [delayed]";
|
503
|
-
cerr << endl;
|
504
482
|
cerr << ind << "Color " << expression;
|
505
483
|
cerr << " (" << pstate_source_position(node) << ")";
|
506
484
|
cerr << " [" << expression->r() << ":" << expression->g() << ":" << expression->b() << "@" << expression->a() << "]" << endl;
|
507
485
|
} else if (dynamic_cast<Number*>(node)) {
|
508
486
|
Number* expression = dynamic_cast<Number*>(node);
|
509
|
-
cerr << ind << "Number " << expression << " [" << expression->value() << expression->unit() << "]";
|
510
|
-
if (expression->is_delayed()) cerr << " [delayed]";
|
511
|
-
cerr << endl;
|
512
487
|
cerr << ind << "Number " << expression;
|
513
488
|
cerr << " (" << pstate_source_position(node) << ")";
|
514
489
|
cerr << " [" << expression->value() << expression->unit() << "]" << endl;
|
515
490
|
} else if (dynamic_cast<String_Quoted*>(node)) {
|
516
491
|
String_Quoted* expression = dynamic_cast<String_Quoted*>(node);
|
517
|
-
cerr << ind << "String_Quoted
|
518
|
-
cerr <<
|
492
|
+
cerr << ind << "String_Quoted " << expression;
|
493
|
+
cerr << " (" << pstate_source_position(node) << ")";
|
494
|
+
cerr << " [" << prettyprint(expression->value()) << "]";
|
519
495
|
if (expression->is_delayed()) cerr << " [delayed]";
|
520
496
|
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
|
521
|
-
if (expression->quote_mark()) cerr << " [quote_mark]";
|
497
|
+
if (expression->quote_mark()) cerr << " [quote_mark: " << expression->quote_mark() << "]";
|
522
498
|
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
|
523
|
-
cerr << ind << "String_Quoted : " << expression;
|
524
|
-
cerr << " (" << pstate_source_position(node) << ")";
|
525
|
-
cerr << " [" << prettyprint(expression->value()) << "]" <<
|
526
|
-
(expression->is_delayed() ? " {delayed}" : "") <<
|
527
|
-
(expression->sass_fix_1291() ? " {sass_fix_1291}" : "") <<
|
528
|
-
(expression->quote_mark() != 0 ? " {qm:" + string(1, expression->quote_mark()) + "}" : "") <<
|
529
|
-
" <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
|
530
499
|
} else if (dynamic_cast<String_Constant*>(node)) {
|
531
500
|
String_Constant* expression = dynamic_cast<String_Constant*>(node);
|
532
|
-
cerr << ind << "String_Constant
|
501
|
+
cerr << ind << "String_Constant " << expression;
|
502
|
+
cerr << " " << expression->concrete_type() <<
|
503
|
+
cerr << " (" << pstate_source_position(node) << ")";
|
533
504
|
cerr << " [" << prettyprint(expression->value()) << "]";
|
534
505
|
if (expression->is_delayed()) cerr << " [delayed]";
|
535
506
|
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
|
536
|
-
cerr " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
|
537
|
-
cerr << ind << "String_Constant : " << expression;
|
538
|
-
cerr << " (" << pstate_source_position(node) << ")";
|
539
|
-
cerr << " [" << prettyprint(expression->value()) << "]" <<
|
540
|
-
(expression->is_delayed() ? " {delayed}" : "") <<
|
541
|
-
(expression->sass_fix_1291() ? " {sass_fix_1291}" : "") <<
|
542
|
-
(expression->quote_mark() != 0 ? " {qm:" + string(1, expression->quote_mark()) + "}" : "") <<
|
543
|
-
" <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
|
507
|
+
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
|
544
508
|
} else if (dynamic_cast<String_Schema*>(node)) {
|
545
509
|
String_Schema* expression = dynamic_cast<String_Schema*>(node);
|
546
|
-
cerr << ind << "String_Schema " << expression
|
510
|
+
cerr << ind << "String_Schema " << expression;
|
511
|
+
cerr << " " << expression->concrete_type();
|
547
512
|
if (expression->is_delayed()) cerr << " [delayed]";
|
548
513
|
if (expression->has_interpolants()) cerr << " [has_interpolants]";
|
549
|
-
cerr " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
|
550
|
-
cerr << ind << "String_Schema " << expression;
|
551
|
-
cerr << " (" << pstate_source_position(node) << ")";
|
552
|
-
cerr << " " << expression->concrete_type() <<
|
553
|
-
(expression->has_interpolants() ? " {has_interpolants}" : "") <<
|
554
|
-
endl;
|
514
|
+
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
|
555
515
|
for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
|
556
516
|
} else if (dynamic_cast<String*>(node)) {
|
557
517
|
String* expression = dynamic_cast<String*>(node);
|
558
|
-
cerr << ind << "String " << expression << expression->concrete_type();
|
559
|
-
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
|
560
|
-
cerr " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
|
561
518
|
cerr << ind << "String " << expression;
|
519
|
+
cerr << " " << expression->concrete_type();
|
562
520
|
cerr << " (" << pstate_source_position(node) << ")";
|
563
|
-
|
564
|
-
|
565
|
-
endl;
|
521
|
+
if (expression->sass_fix_1291()) cerr << " [sass_fix_1291]";
|
522
|
+
cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
|
566
523
|
} else if (dynamic_cast<Expression*>(node)) {
|
567
524
|
Expression* expression = dynamic_cast<Expression*>(node);
|
568
525
|
cerr << ind << "Expression " << expression;
|
data/ext/libsass/emitter.cpp
CHANGED
@@ -18,7 +18,8 @@ namespace Sass {
|
|
18
18
|
in_wrapped(false),
|
19
19
|
in_media_block(false),
|
20
20
|
in_declaration(false),
|
21
|
-
|
21
|
+
in_space_array(false),
|
22
|
+
in_comma_array(false)
|
22
23
|
{ }
|
23
24
|
|
24
25
|
// return buffer as string
|
@@ -191,7 +192,9 @@ namespace Sass {
|
|
191
192
|
{
|
192
193
|
if (output_style() != COMPRESSED && buffer().size()) {
|
193
194
|
char lst = buffer().at(buffer().length() - 1);
|
194
|
-
if (!isspace(lst))
|
195
|
+
if (!isspace(lst) || scheduled_delimiter) {
|
196
|
+
append_mandatory_space();
|
197
|
+
}
|
195
198
|
}
|
196
199
|
}
|
197
200
|
|
data/ext/libsass/emitter.hpp
CHANGED
@@ -37,11 +37,17 @@ namespace Sass {
|
|
37
37
|
bool scheduled_delimiter;
|
38
38
|
|
39
39
|
public:
|
40
|
+
// output strings different in comments
|
40
41
|
bool in_comment;
|
42
|
+
// selector list does not get linefeeds
|
41
43
|
bool in_wrapped;
|
44
|
+
// lists always get a space after delimiter
|
42
45
|
bool in_media_block;
|
46
|
+
// nested list must not have parentheses
|
43
47
|
bool in_declaration;
|
44
|
-
|
48
|
+
// nested lists need parentheses
|
49
|
+
bool in_space_array;
|
50
|
+
bool in_comma_array;
|
45
51
|
|
46
52
|
public:
|
47
53
|
// return buffer as string
|
data/ext/libsass/eval.cpp
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
#include <cstdlib>
|
2
|
+
#include <cmath>
|
3
|
+
#include <iostream>
|
4
|
+
#include <sstream>
|
5
|
+
#include <iomanip>
|
6
|
+
#include <typeinfo>
|
7
|
+
|
1
8
|
#include "file.hpp"
|
2
9
|
#include "eval.hpp"
|
3
10
|
#include "ast.hpp"
|
@@ -11,12 +18,6 @@
|
|
11
18
|
#include "prelexer.hpp"
|
12
19
|
#include "parser.hpp"
|
13
20
|
|
14
|
-
#include <cstdlib>
|
15
|
-
#include <cmath>
|
16
|
-
#include <iostream>
|
17
|
-
#include <iomanip>
|
18
|
-
#include <typeinfo>
|
19
|
-
|
20
21
|
namespace Sass {
|
21
22
|
using namespace std;
|
22
23
|
|
@@ -397,6 +398,13 @@ namespace Sass {
|
|
397
398
|
for (auto key : m->keys()) {
|
398
399
|
*mm << std::make_pair(key->perform(this), m->at(key)->perform(this));
|
399
400
|
}
|
401
|
+
|
402
|
+
// check for duplicate keys
|
403
|
+
if (mm->has_duplicate_key()) {
|
404
|
+
To_String to_string(&ctx);
|
405
|
+
error("Duplicate key \"" + mm->get_duplicate_key()->perform(&to_string) + "\" in map " + m->perform(&to_string) + ".", m->pstate());
|
406
|
+
}
|
407
|
+
|
400
408
|
mm->is_expanded(true);
|
401
409
|
return mm;
|
402
410
|
}
|
@@ -528,7 +536,9 @@ namespace Sass {
|
|
528
536
|
Expression* Eval::operator()(Function_Call* c)
|
529
537
|
{
|
530
538
|
if (backtrace->parent != NULL && backtrace->depth() > Constants::MaxCallStack) {
|
531
|
-
|
539
|
+
ostringstream stm;
|
540
|
+
stm << "Stack depth exceeded max of " << Constants::MaxCallStack;
|
541
|
+
error(stm.str(), c->pstate(), backtrace);
|
532
542
|
}
|
533
543
|
string name(Util::normalize_underscores(c->name()));
|
534
544
|
string full_name(name + "[f]");
|
@@ -876,6 +886,7 @@ namespace Sass {
|
|
876
886
|
Expression* value = static_cast<Expression*>((*env)[name]);
|
877
887
|
return evacuate_quotes(interpolation(value));
|
878
888
|
} else if (Binary_Expression* var = dynamic_cast<Binary_Expression*>(s)) {
|
889
|
+
var->is_delayed(false);
|
879
890
|
Expression* ex = var->perform(this);
|
880
891
|
return evacuate_quotes(interpolation(ex));
|
881
892
|
} else if (Function_Call* var = dynamic_cast<Function_Call*>(s)) {
|
@@ -901,9 +912,9 @@ namespace Sass {
|
|
901
912
|
{
|
902
913
|
string acc;
|
903
914
|
for (size_t i = 0, L = s->length(); i < L; ++i) {
|
904
|
-
if (String_Quoted* str_quoted = dynamic_cast<String_Quoted*>((*s)[i])) {
|
905
|
-
if (!str_quoted->is_delayed()) str_quoted->value(string_eval_escapes(str_quoted->value()));
|
906
|
-
}
|
915
|
+
// if (String_Quoted* str_quoted = dynamic_cast<String_Quoted*>((*s)[i])) {
|
916
|
+
// if (!str_quoted->is_delayed()) str_quoted->value(string_eval_escapes(str_quoted->value()));
|
917
|
+
// }
|
907
918
|
acc += interpolation((*s)[i]);
|
908
919
|
}
|
909
920
|
String_Quoted* str = new (ctx.mem) String_Quoted(s->pstate(), acc);
|
@@ -1014,8 +1025,7 @@ namespace Sass {
|
|
1014
1025
|
is_rest_argument = false;
|
1015
1026
|
is_keyword_argument = true;
|
1016
1027
|
}
|
1017
|
-
else
|
1018
|
-
if(val->concrete_type() != Expression::LIST) {
|
1028
|
+
else if(val->concrete_type() != Expression::LIST) {
|
1019
1029
|
List* wrapper = new (ctx.mem) List(val->pstate(),
|
1020
1030
|
0,
|
1021
1031
|
List::COMMA,
|
@@ -1047,9 +1057,13 @@ namespace Sass {
|
|
1047
1057
|
|
1048
1058
|
Expression* Eval::operator()(Parent_Selector* p)
|
1049
1059
|
{
|
1060
|
+
// no idea why both calls are needed
|
1050
1061
|
Selector* s = p->perform(contextualize);
|
1062
|
+
if (!s) s = p->selector()->perform(contextualize);
|
1051
1063
|
// access to parent selector may return 0
|
1052
1064
|
Selector_List* l = static_cast<Selector_List*>(s);
|
1065
|
+
// some spec tests cause this (might be a valid case!)
|
1066
|
+
// if (!s) { cerr << "Parent Selector eval error" << endl; }
|
1053
1067
|
if (!s) { l = new (ctx.mem) Selector_List(p->pstate()); }
|
1054
1068
|
return l->perform(listize);
|
1055
1069
|
}
|
@@ -1186,7 +1200,7 @@ namespace Sass {
|
|
1186
1200
|
} else {
|
1187
1201
|
v->value(ops[op](lv, tmp.value()));
|
1188
1202
|
}
|
1189
|
-
|
1203
|
+
v->normalize();
|
1190
1204
|
return v;
|
1191
1205
|
}
|
1192
1206
|
|
data/ext/libsass/expand.cpp
CHANGED
@@ -54,8 +54,8 @@ namespace Sass {
|
|
54
54
|
}
|
55
55
|
|
56
56
|
Contextualize_Eval* contextual = contextualize_eval->with(selector_stack.back(), env, backtrace);
|
57
|
-
if (old_in_at_root && !r->selector()->has_reference())
|
58
|
-
|
57
|
+
// if (old_in_at_root && !r->selector()->has_reference())
|
58
|
+
// contextual = contextualize_eval->with(selector_stack.back(), env, backtrace);
|
59
59
|
|
60
60
|
Selector* sel_ctx = r->selector()->perform(contextual);
|
61
61
|
if (sel_ctx == 0) throw "Cannot expand null selector";
|
data/ext/libsass/functions.cpp
CHANGED
@@ -1107,7 +1107,7 @@ namespace Sass {
|
|
1107
1107
|
|
1108
1108
|
List* list = dynamic_cast<List*>(env["$list"]);
|
1109
1109
|
return new (ctx.mem) Number(pstate,
|
1110
|
-
list ? list->
|
1110
|
+
list ? list->size() : 1);
|
1111
1111
|
}
|
1112
1112
|
|
1113
1113
|
Signature nth_sig = "nth($list, $n)";
|
@@ -1217,7 +1217,18 @@ namespace Sass {
|
|
1217
1217
|
else if (sep_str == "comma") result->separator(List::COMMA);
|
1218
1218
|
else if (sep_str != "auto") error("argument `$separator` of `" + string(sig) + "` must be `space`, `comma`, or `auto`", pstate);
|
1219
1219
|
*result += l;
|
1220
|
-
|
1220
|
+
bool is_arglist = l->is_arglist();
|
1221
|
+
result->is_arglist(is_arglist);
|
1222
|
+
if (is_arglist) {
|
1223
|
+
*result << new (ctx.mem) Argument(v->pstate(),
|
1224
|
+
v,
|
1225
|
+
"",
|
1226
|
+
false,
|
1227
|
+
false);
|
1228
|
+
|
1229
|
+
} else {
|
1230
|
+
*result << v;
|
1231
|
+
}
|
1221
1232
|
return result;
|
1222
1233
|
}
|
1223
1234
|
|
@@ -1345,13 +1356,10 @@ namespace Sass {
|
|
1345
1356
|
{
|
1346
1357
|
List* arglist = new (ctx.mem) List(*ARG("$args", List));
|
1347
1358
|
Map* result = new (ctx.mem) Map(pstate, 1);
|
1348
|
-
|
1349
|
-
// isn't keyword argument list the first argument isn't a keyword argument
|
1350
|
-
if (!(arglist->empty() || ((Argument*)(*arglist)[0])->is_keyword_argument())) return result;
|
1351
|
-
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
1359
|
+
for (size_t i = arglist->size(), L = arglist->length(); i < L; ++i) {
|
1352
1360
|
string name = string(((Argument*)(*arglist)[i])->name());
|
1353
|
-
|
1354
|
-
*result << make_pair(new (ctx.mem) String_Constant(pstate,
|
1361
|
+
name = name.erase(0, 1); // sanitize name (remove dollar sign)
|
1362
|
+
*result << make_pair(new (ctx.mem) String_Constant(pstate, name),
|
1355
1363
|
((Argument*)(*arglist)[i])->value());
|
1356
1364
|
}
|
1357
1365
|
return result;
|
@@ -1540,11 +1548,14 @@ namespace Sass {
|
|
1540
1548
|
} else if (v->concrete_type() == Expression::STRING) {
|
1541
1549
|
return v;
|
1542
1550
|
} else {
|
1551
|
+
bool parentheses = v->concrete_type() == Expression::MAP ||
|
1552
|
+
v->concrete_type() == Expression::LIST;
|
1543
1553
|
Output_Style old_style;
|
1544
1554
|
old_style = ctx.output_style;
|
1545
1555
|
ctx.output_style = NESTED;
|
1546
|
-
To_String to_string(&ctx);
|
1556
|
+
To_String to_string(&ctx, false);
|
1547
1557
|
string inspect = v->perform(&to_string);
|
1558
|
+
if (inspect.empty() && parentheses) inspect = "()";
|
1548
1559
|
ctx.output_style = old_style;
|
1549
1560
|
return new (ctx.mem) String_Constant(pstate, inspect);
|
1550
1561
|
|
@@ -1553,6 +1564,20 @@ namespace Sass {
|
|
1553
1564
|
// return v;
|
1554
1565
|
}
|
1555
1566
|
|
1567
|
+
Signature is_superselector_sig = "is-superselector($super, $sub)";
|
1568
|
+
BUILT_IN(is_superselector)
|
1569
|
+
{
|
1570
|
+
To_String to_string(&ctx, false);
|
1571
|
+
Expression* ex_sup = ARG("$super", Expression);
|
1572
|
+
Expression* ex_sub = ARG("$sub", Expression);
|
1573
|
+
string sup_src = ex_sup->perform(&to_string) + "{";
|
1574
|
+
string sub_src = ex_sub->perform(&to_string) + "{";
|
1575
|
+
Selector_List* sel_sup = Parser::parse_selector(sup_src.c_str(), ctx);
|
1576
|
+
Selector_List* sel_sub = Parser::parse_selector(sub_src.c_str(), ctx);
|
1577
|
+
bool result = sel_sup->is_superselector_of(sel_sub);
|
1578
|
+
return new (ctx.mem) Boolean(pstate, result);
|
1579
|
+
}
|
1580
|
+
|
1556
1581
|
Signature unique_id_sig = "unique-id()";
|
1557
1582
|
BUILT_IN(unique_id)
|
1558
1583
|
{
|