sassc 1.8.4 → 1.8.5
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 +2 -0
- data/ext/libsass/LICENSE +1 -1
- data/ext/libsass/Readme.md +8 -13
- data/ext/libsass/appveyor.yml +1 -1
- data/ext/libsass/src/ast.cpp +10 -16
- data/ext/libsass/src/ast.hpp +1 -0
- data/ext/libsass/src/context.cpp +3 -2
- data/ext/libsass/src/debugger.hpp +1 -0
- data/ext/libsass/src/eval.cpp +19 -11
- data/ext/libsass/src/expand.cpp +11 -0
- data/ext/libsass/src/functions.cpp +0 -1
- data/ext/libsass/src/inspect.cpp +4 -1
- data/ext/libsass/src/json.cpp +65 -50
- data/ext/libsass/src/lexer.cpp +1 -1
- data/ext/libsass/src/output.cpp +2 -1
- data/ext/libsass/src/parser.cpp +62 -44
- data/ext/libsass/src/parser.hpp +7 -1
- data/ext/libsass/src/sass_context.cpp +4 -1
- data/lib/sassc/version.rb +1 -1
- data/lib/tasks/libsass.rb +10 -1
- data/test/native_test.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab6f4c497bb370c122244297018added959a8af8
|
4
|
+
data.tar.gz: ad910a4be141fd033b143c1723f7a8dfef523243
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cd8b55db12f25fca765171af3e7ae3f11702e39a0df778009088dc254777ee90bd138467ef4efcbc865e507c096ce165f3dcd8abae3bfe925eec9e084eaa83d
|
7
|
+
data.tar.gz: 45205737303fbaca70c190457d30d234eec1c814bd279810bac275a7360c09a59f8f1a0552c6321b658023d986f5e6d4fb7887d8682bcbc45fbdbf1ea685e310
|
data/README.md
CHANGED
data/ext/libsass/LICENSE
CHANGED
data/ext/libsass/Readme.md
CHANGED
@@ -3,7 +3,7 @@ LibSass
|
|
3
3
|
|
4
4
|
by Aaron Leung ([@akhleung]), Hampton Catlin ([@hcatlin]), Marcel Greter ([@mgreter]) and Michael Mifsud ([@xzyfer])
|
5
5
|
|
6
|
-
[](https://travis-ci.org/sass/libsass)
|
7
7
|
[](https://ci.appveyor.com/project/sass/libsass/branch/master)
|
8
8
|
[](https://www.bountysource.com/trackers/283068-libsass?utm_source=283068&utm_medium=shield&utm_campaign=TRACKER_BADGE)
|
9
9
|
[](https://coveralls.io/r/sass/libsass?branch=feature%2Ftest-travis-ci-3)
|
@@ -13,7 +13,7 @@ https://github.com/sass/libsass
|
|
13
13
|
|
14
14
|
LibSass is just a library, but if you want to RUN LibSass,
|
15
15
|
then go to https://github.com/sass/sassc or
|
16
|
-
https://github.com/sass/ruby
|
16
|
+
https://github.com/sass/sassc-ruby or
|
17
17
|
[find your local implementer](docs/implementations.md).
|
18
18
|
|
19
19
|
LibSass requires GCC 4.6+ or Clang/LLVM. If your OS is older, this version may not compile.
|
@@ -68,20 +68,16 @@ Sass is a CSS pre-processor language to add on exciting, new,
|
|
68
68
|
awesome features to CSS. Sass was the first language of its kind
|
69
69
|
and by far the most mature and up to date codebase.
|
70
70
|
|
71
|
-
Sass was originally
|
72
|
-
Hampton Catlin ([@hcatlin]).
|
73
|
-
of
|
74
|
-
Weizenbaum ([@nex3]) and Chris Eppstein ([@chriseppstein]).
|
71
|
+
Sass was originally concieved of by the co-creator of this library,
|
72
|
+
Hampton Catlin ([@hcatlin]). Most of the language has been the result of years
|
73
|
+
of work by Natalie Weizenbaum ([@nex3]) and Chris Eppstein ([@chriseppstein]).
|
75
74
|
|
76
75
|
For more information about Sass itself, please visit http://sass-lang.com
|
77
76
|
|
78
|
-
|
79
|
-
----------------------
|
77
|
+
Initial development of libsass by Aaron Leung and Hampton Catlin was supported by [Moovweb](http://www.moovweb.com).
|
80
78
|
|
81
|
-
|
82
|
-
|
83
|
-
assign copyright on your work. The intention here is to ensure that the project
|
84
|
-
remains totally free (liberal, like).
|
79
|
+
Licensing
|
80
|
+
---------
|
85
81
|
|
86
82
|
Our MIT license is designed to be as simple, and liberal as possible.
|
87
83
|
|
@@ -94,4 +90,3 @@ Our MIT license is designed to be as simple, and liberal as possible.
|
|
94
90
|
|
95
91
|
sass2scss was originally written by [Marcel Greter](@mgreter)
|
96
92
|
and he happily agreed to have it merged into the project.
|
97
|
-
|
data/ext/libsass/appveyor.yml
CHANGED
data/ext/libsass/src/ast.cpp
CHANGED
@@ -949,6 +949,7 @@ namespace Sass {
|
|
949
949
|
|
950
950
|
Selector_List* Selector_List::parentize(Selector_List* ps, Context& ctx)
|
951
951
|
{
|
952
|
+
if (!this->has_parent_ref()) return this;
|
952
953
|
Selector_List* ss = SASS_MEMORY_NEW(ctx.mem, Selector_List, pstate());
|
953
954
|
for (size_t pi = 0, pL = ps->length(); pi < pL; ++pi) {
|
954
955
|
Selector_List* list = SASS_MEMORY_NEW(ctx.mem, Selector_List, pstate());
|
@@ -1085,18 +1086,16 @@ namespace Sass {
|
|
1085
1086
|
Complex_Selector* Complex_Selector::first()
|
1086
1087
|
{
|
1087
1088
|
// declare variables used in loop
|
1088
|
-
Complex_Selector* cur = this
|
1089
|
-
const Compound_Selector* head
|
1089
|
+
Complex_Selector* cur = this;
|
1090
|
+
const Compound_Selector* head;
|
1090
1091
|
// processing loop
|
1091
1092
|
while (cur)
|
1092
1093
|
{
|
1093
1094
|
// get the head
|
1094
1095
|
head = cur->head_;
|
1095
|
-
//
|
1096
|
-
if (head
|
1097
|
-
|
1098
|
-
// abort (and return) if it is not a parent selector
|
1099
|
-
if (!dynamic_cast<Parent_Selector*>((*head)[0])) break;
|
1096
|
+
// abort (and return) if it is not a parent selector
|
1097
|
+
if (!head || head->length() != 1 || !dynamic_cast<Parent_Selector*>((*head)[0])) {
|
1098
|
+
break;
|
1100
1099
|
}
|
1101
1100
|
// advance to next
|
1102
1101
|
cur = cur->tail_;
|
@@ -1897,6 +1896,10 @@ namespace Sass {
|
|
1897
1896
|
return false;
|
1898
1897
|
}
|
1899
1898
|
|
1899
|
+
bool String_Constant::is_invisible() const {
|
1900
|
+
return value_.empty() && quote_mark_ == 0;
|
1901
|
+
}
|
1902
|
+
|
1900
1903
|
bool String_Constant::operator== (const Expression& rhs) const
|
1901
1904
|
{
|
1902
1905
|
if (const String_Quoted* qstr = dynamic_cast<const String_Quoted*>(&rhs)) {
|
@@ -2030,14 +2033,6 @@ namespace Sass {
|
|
2030
2033
|
return to_string({ NESTED, 5 });
|
2031
2034
|
}
|
2032
2035
|
|
2033
|
-
// helper function for serializing colors
|
2034
|
-
template <size_t range>
|
2035
|
-
static double cap_channel(double c) {
|
2036
|
-
if (c > range) return range;
|
2037
|
-
else if (c < 0) return 0;
|
2038
|
-
else return c;
|
2039
|
-
}
|
2040
|
-
|
2041
2036
|
std::string String_Quoted::inspect() const
|
2042
2037
|
{
|
2043
2038
|
return quote(value_, '*');
|
@@ -2064,4 +2059,3 @@ namespace Sass {
|
|
2064
2059
|
}
|
2065
2060
|
|
2066
2061
|
}
|
2067
|
-
|
data/ext/libsass/src/ast.hpp
CHANGED
data/ext/libsass/src/context.cpp
CHANGED
@@ -351,8 +351,9 @@ namespace Sass {
|
|
351
351
|
|
352
352
|
// process the resolved entry
|
353
353
|
else if (resolved.size() == 1) {
|
354
|
+
bool use_cache = c_importers.size() == 0;
|
354
355
|
// use cache for the resource loading
|
355
|
-
if (sheets.count(resolved[0].abs_path)) return resolved[0];
|
356
|
+
if (use_cache && sheets.count(resolved[0].abs_path)) return resolved[0];
|
356
357
|
// try to read the content of the resolved file entry
|
357
358
|
// the memory buffer returned must be freed by us!
|
358
359
|
if (char* contents = read_file(resolved[0].abs_path)) {
|
@@ -436,7 +437,7 @@ namespace Sass {
|
|
436
437
|
// query data from the current include
|
437
438
|
Sass_Import_Entry include = *it_includes;
|
438
439
|
char* source = sass_import_take_source(include);
|
439
|
-
char* srcmap =
|
440
|
+
char* srcmap = sass_import_take_srcmap(include);
|
440
441
|
size_t line = sass_import_get_error_line(include);
|
441
442
|
size_t column = sass_import_get_error_column(include);
|
442
443
|
const char *abs_path = sass_import_get_abs_path(include);
|
@@ -357,6 +357,7 @@ inline void debug_ast(AST_Node* node, std::string ind, Env* env)
|
|
357
357
|
Import_Stub* block = dynamic_cast<Import_Stub*>(node);
|
358
358
|
std::cerr << ind << "Import_Stub " << block;
|
359
359
|
std::cerr << " (" << pstate_source_position(node) << ")";
|
360
|
+
std::cerr << " [" << block->imp_path() << "] ";
|
360
361
|
std::cerr << " " << block->tabs() << std::endl;
|
361
362
|
} else if (dynamic_cast<Import*>(node)) {
|
362
363
|
Import* block = dynamic_cast<Import*>(node);
|
data/ext/libsass/src/eval.cpp
CHANGED
@@ -504,22 +504,22 @@ namespace Sass {
|
|
504
504
|
}
|
505
505
|
|
506
506
|
// only the last item will be used to eval the binary expression
|
507
|
-
if (String_Schema*
|
508
|
-
if (!
|
509
|
-
ret_schema = SASS_MEMORY_NEW(ctx.mem, String_Schema,
|
507
|
+
if (String_Schema* s_l = dynamic_cast<String_Schema*>(b->left())) {
|
508
|
+
if (!s_l->has_interpolant() && (!s_l->is_right_interpolant())) {
|
509
|
+
ret_schema = SASS_MEMORY_NEW(ctx.mem, String_Schema, s_l->pstate());
|
510
510
|
Binary_Expression* bin_ex = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, b->pstate(),
|
511
|
-
b->op(),
|
511
|
+
b->op(), s_l->last(), b->right());
|
512
512
|
bin_ex->is_delayed(b->left()->is_delayed() || b->right()->is_delayed());
|
513
513
|
// bin_ex->is_interpolant(b->left()->is_interpolant());
|
514
|
-
for (size_t i = 0; i <
|
515
|
-
*ret_schema <<
|
514
|
+
for (size_t i = 0; i < s_l->length() - 1; ++i) {
|
515
|
+
*ret_schema << s_l->at(i)->perform(this);
|
516
516
|
}
|
517
517
|
*ret_schema << bin_ex->perform(this);
|
518
518
|
return ret_schema->perform(this);
|
519
519
|
}
|
520
520
|
}
|
521
521
|
if (String_Schema* s_r = dynamic_cast<String_Schema*>(b->right())) {
|
522
|
-
if (!s_r->is_left_interpolant() || op_type == Sass_OP::DIV) {
|
522
|
+
if (!s_r->has_interpolant() && (!s_r->is_left_interpolant() || op_type == Sass_OP::DIV)) {
|
523
523
|
ret_schema = SASS_MEMORY_NEW(ctx.mem, String_Schema, s_r->pstate());
|
524
524
|
Binary_Expression* bin_ex = SASS_MEMORY_NEW(ctx.mem, Binary_Expression, b->pstate(),
|
525
525
|
b->op(), b->left(), s_r->first());
|
@@ -691,7 +691,7 @@ namespace Sass {
|
|
691
691
|
}
|
692
692
|
}
|
693
693
|
|
694
|
-
|
694
|
+
if (force_delay) {
|
695
695
|
std::string str("");
|
696
696
|
str += v_l->to_string(ctx.c_options);
|
697
697
|
if (b->op().ws_before) str += " ";
|
@@ -1125,11 +1125,12 @@ namespace Sass {
|
|
1125
1125
|
if (List* l = dynamic_cast<List*>(ex)) {
|
1126
1126
|
List* ll = SASS_MEMORY_NEW(ctx.mem, List, l->pstate(), 0, l->separator());
|
1127
1127
|
// this fixes an issue with bourbon sample, not really sure why
|
1128
|
-
if (l->size() && dynamic_cast<Null*>((*l)[0])) { res += "
|
1128
|
+
// if (l->size() && dynamic_cast<Null*>((*l)[0])) { res += ""; }
|
1129
1129
|
for(auto item : *l) {
|
1130
1130
|
item->is_interpolant(l->is_interpolant());
|
1131
1131
|
std::string rl(""); interpolation(ctx, rl, item, into_quotes, l->is_interpolant());
|
1132
|
-
|
1132
|
+
bool is_null = dynamic_cast<Null*>(item) != 0; // rl != ""
|
1133
|
+
if (!is_null) *ll << SASS_MEMORY_NEW(ctx.mem, String_Quoted, item->pstate(), rl);
|
1133
1134
|
}
|
1134
1135
|
res += (ll->to_string(ctx.c_options));
|
1135
1136
|
ll->is_interpolant(l->is_interpolant());
|
@@ -1170,15 +1171,22 @@ namespace Sass {
|
|
1170
1171
|
}
|
1171
1172
|
}
|
1172
1173
|
}
|
1174
|
+
bool was_quoted = false;
|
1175
|
+
bool was_interpolant = false;
|
1173
1176
|
std::string res("");
|
1174
1177
|
for (size_t i = 0; i < L; ++i) {
|
1178
|
+
bool is_quoted = dynamic_cast<String_Quoted*>((*s)[i]) != NULL;
|
1175
1179
|
(*s)[i]->perform(this);
|
1180
|
+
if (was_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
|
1181
|
+
else if (i > 0 && is_quoted && !(*s)[i]->is_interpolant() && !was_interpolant) { res += " "; }
|
1176
1182
|
Expression* ex = (*s)[i]->is_delayed() ? (*s)[i] : (*s)[i]->perform(this);
|
1177
1183
|
interpolation(ctx, res, ex, into_quotes, ex->is_interpolant());
|
1184
|
+
was_quoted = dynamic_cast<String_Quoted*>((*s)[i]) != NULL;
|
1185
|
+
was_interpolant = (*s)[i]->is_interpolant();
|
1178
1186
|
|
1179
1187
|
}
|
1180
1188
|
if (!s->is_interpolant()) {
|
1181
|
-
if (res == "") return SASS_MEMORY_NEW(ctx.mem, Null, s->pstate());
|
1189
|
+
if (s->length() > 1 && res == "") return SASS_MEMORY_NEW(ctx.mem, Null, s->pstate());
|
1182
1190
|
return SASS_MEMORY_NEW(ctx.mem, String_Constant, s->pstate(), res);
|
1183
1191
|
}
|
1184
1192
|
String_Quoted* str = SASS_MEMORY_NEW(ctx.mem, String_Quoted, s->pstate(), res);
|
data/ext/libsass/src/expand.cpp
CHANGED
@@ -117,6 +117,17 @@ namespace Sass {
|
|
117
117
|
Selector_List* sel = dynamic_cast<Selector_List*>(ex);
|
118
118
|
if (sel == 0) throw std::runtime_error("Expanded null selector");
|
119
119
|
|
120
|
+
if (sel->length() == 0 || sel->has_parent_ref()) {
|
121
|
+
bool has_parent_selector = false;
|
122
|
+
for (size_t i = 0, L = selector_stack.size(); i < L && !has_parent_selector; i++) {
|
123
|
+
Selector_List* ll = selector_stack.at(i);
|
124
|
+
has_parent_selector = ll != 0 && ll->length() > 0;
|
125
|
+
}
|
126
|
+
if (!has_parent_selector) {
|
127
|
+
error("Base-level rules cannot contain the parent-selector-referencing character '&'.", sel->pstate(), backtrace());
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
120
131
|
selector_stack.push_back(sel);
|
121
132
|
Env* env = 0;
|
122
133
|
if (block_stack.back()->is_root()) {
|
@@ -1690,7 +1690,6 @@ namespace Sass {
|
|
1690
1690
|
Sass_Output_Style old_style;
|
1691
1691
|
old_style = ctx.c_options.output_style;
|
1692
1692
|
ctx.c_options.output_style = TO_SASS;
|
1693
|
-
Sass_Output_Options out(ctx.c_options);
|
1694
1693
|
Emitter emitter(ctx.c_options);
|
1695
1694
|
Inspect i(emitter);
|
1696
1695
|
i.in_declaration = false;
|
data/ext/libsass/src/inspect.cpp
CHANGED
@@ -406,7 +406,10 @@ namespace Sass {
|
|
406
406
|
Expression* list_item = (*list)[i];
|
407
407
|
if (output_style() != TO_SASS) {
|
408
408
|
if (list_item->is_invisible()) {
|
409
|
-
|
409
|
+
// this fixes an issue with "" in a list
|
410
|
+
if (!dynamic_cast<String_Constant*>(list_item)) {
|
411
|
+
continue;
|
412
|
+
}
|
410
413
|
}
|
411
414
|
}
|
412
415
|
if (items_output) {
|
data/ext/libsass/src/json.cpp
CHANGED
@@ -544,42 +544,50 @@ JsonNode *json_mkobject(void)
|
|
544
544
|
|
545
545
|
static void append_node(JsonNode *parent, JsonNode *child)
|
546
546
|
{
|
547
|
-
child
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
547
|
+
if (child != NULL && parent != NULL) {
|
548
|
+
child->parent = parent;
|
549
|
+
child->prev = parent->children.tail;
|
550
|
+
child->next = NULL;
|
551
|
+
|
552
|
+
if (parent->children.tail != NULL)
|
553
|
+
parent->children.tail->next = child;
|
554
|
+
else
|
555
|
+
parent->children.head = child;
|
556
|
+
parent->children.tail = child;
|
557
|
+
}
|
556
558
|
}
|
557
559
|
|
558
560
|
static void prepend_node(JsonNode *parent, JsonNode *child)
|
559
561
|
{
|
560
|
-
child
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
562
|
+
if (child != NULL && parent != NULL) {
|
563
|
+
child->parent = parent;
|
564
|
+
child->prev = NULL;
|
565
|
+
child->next = parent->children.head;
|
566
|
+
|
567
|
+
if (parent->children.head != NULL)
|
568
|
+
parent->children.head->prev = child;
|
569
|
+
else
|
570
|
+
parent->children.tail = child;
|
571
|
+
parent->children.head = child;
|
572
|
+
}
|
569
573
|
}
|
570
574
|
|
571
575
|
static void append_member(JsonNode *object, char *key, JsonNode *value)
|
572
576
|
{
|
573
|
-
value
|
574
|
-
|
577
|
+
if (value != NULL && object != NULL) {
|
578
|
+
value->key = key;
|
579
|
+
append_node(object, value);
|
580
|
+
}
|
575
581
|
}
|
576
582
|
|
577
583
|
void json_append_element(JsonNode *array, JsonNode *element)
|
578
584
|
{
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
585
|
+
if (array != NULL && element !=NULL) {
|
586
|
+
assert(array->tag == JSON_ARRAY);
|
587
|
+
assert(element->parent == NULL);
|
588
|
+
|
589
|
+
append_node(array, element);
|
590
|
+
}
|
583
591
|
}
|
584
592
|
|
585
593
|
void json_prepend_element(JsonNode *array, JsonNode *element)
|
@@ -592,40 +600,47 @@ void json_prepend_element(JsonNode *array, JsonNode *element)
|
|
592
600
|
|
593
601
|
void json_append_member(JsonNode *object, const char *key, JsonNode *value)
|
594
602
|
{
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
603
|
+
if (object != NULL && key != NULL && value != NULL) {
|
604
|
+
assert(object->tag == JSON_OBJECT);
|
605
|
+
assert(value->parent == NULL);
|
606
|
+
|
607
|
+
append_member(object, json_strdup(key), value);
|
608
|
+
}
|
599
609
|
}
|
600
610
|
|
601
611
|
void json_prepend_member(JsonNode *object, const char *key, JsonNode *value)
|
602
612
|
{
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
613
|
+
if (object != NULL && key != NULL && value != NULL) {
|
614
|
+
assert(object->tag == JSON_OBJECT);
|
615
|
+
assert(value->parent == NULL);
|
616
|
+
|
617
|
+
value->key = json_strdup(key);
|
618
|
+
prepend_node(object, value);
|
619
|
+
}
|
608
620
|
}
|
609
621
|
|
610
622
|
void json_remove_from_parent(JsonNode *node)
|
611
623
|
{
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
624
|
+
if (node != NULL) {
|
625
|
+
JsonNode *parent = node->parent;
|
626
|
+
|
627
|
+
if (parent != NULL) {
|
628
|
+
if (node->prev != NULL)
|
629
|
+
node->prev->next = node->next;
|
630
|
+
else
|
631
|
+
parent->children.head = node->next;
|
632
|
+
|
633
|
+
if (node->next != NULL)
|
634
|
+
node->next->prev = node->prev;
|
635
|
+
else
|
636
|
+
parent->children.tail = node->prev;
|
637
|
+
|
638
|
+
free(node->key);
|
639
|
+
|
640
|
+
node->parent = NULL;
|
641
|
+
node->prev = node->next = NULL;
|
642
|
+
node->key = NULL;
|
643
|
+
}
|
629
644
|
}
|
630
645
|
}
|
631
646
|
|
data/ext/libsass/src/lexer.cpp
CHANGED
@@ -137,7 +137,7 @@ namespace Sass {
|
|
137
137
|
const char* any_char(const char* src) { return *src ? src + 1 : src; }
|
138
138
|
|
139
139
|
// Match word boundary (zero-width lookahead).
|
140
|
-
const char* word_boundary(const char* src) { return is_character(*src) ? 0 : src; }
|
140
|
+
const char* word_boundary(const char* src) { return is_character(*src) || *src == '#' ? 0 : src; }
|
141
141
|
|
142
142
|
// Match linefeed /(?:\n|\r\n?)/
|
143
143
|
const char* re_linebreak(const char* src)
|
data/ext/libsass/src/output.cpp
CHANGED
@@ -67,7 +67,8 @@ namespace Sass {
|
|
67
67
|
// search for unicode char
|
68
68
|
for(const char& chr : wbuf.buffer) {
|
69
69
|
// skip all ascii chars
|
70
|
-
|
70
|
+
// static cast to unsigned to handle `char` being signed / unsigned
|
71
|
+
if (static_cast<unsigned>(chr) < 128) continue;
|
71
72
|
// declare the charset
|
72
73
|
if (output_style() != COMPRESSED)
|
73
74
|
charset = "@charset \"UTF-8\";"
|
data/ext/libsass/src/parser.cpp
CHANGED
@@ -200,7 +200,7 @@ namespace Sass {
|
|
200
200
|
|
201
201
|
// abort if we are in function context and have nothing parsed yet
|
202
202
|
else if (stack.back() == Scope::Function) {
|
203
|
-
error("Functions can only contain variable declarations and control directives", pstate);
|
203
|
+
error("Functions can only contain variable declarations and control directives.", pstate);
|
204
204
|
}
|
205
205
|
|
206
206
|
// parse imports to process later
|
@@ -221,8 +221,7 @@ namespace Sass {
|
|
221
221
|
}
|
222
222
|
|
223
223
|
else if (lex < kwd_extend >(true)) {
|
224
|
-
|
225
|
-
if (parent == Scope::Root) {
|
224
|
+
if (block->is_root()) {
|
226
225
|
error("Extend directives may only be used within rules.", pstate);
|
227
226
|
}
|
228
227
|
|
@@ -290,12 +289,7 @@ namespace Sass {
|
|
290
289
|
do {
|
291
290
|
while (lex< block_comment >());
|
292
291
|
if (lex< quoted_string >()) {
|
293
|
-
|
294
|
-
{
|
295
|
-
// push single file import
|
296
|
-
// import_single_file(imp, lexed);
|
297
|
-
to_import.push_back(std::pair<std::string,Function_Call*>(std::string(lexed), 0));
|
298
|
-
}
|
292
|
+
to_import.push_back(std::pair<std::string,Function_Call*>(std::string(lexed), 0));
|
299
293
|
}
|
300
294
|
else if (lex< uri_prefix >()) {
|
301
295
|
Arguments* args = SASS_MEMORY_NEW(ctx.mem, Arguments, pstate);
|
@@ -333,7 +327,7 @@ namespace Sass {
|
|
333
327
|
for(auto location : to_import) {
|
334
328
|
if (location.second) {
|
335
329
|
imp->urls().push_back(location.second);
|
336
|
-
} else {
|
330
|
+
} else if (!ctx.call_importers(unquote(location.first), path, pstate, imp)) {
|
337
331
|
ctx.import_url(imp, location.first, path);
|
338
332
|
}
|
339
333
|
}
|
@@ -345,7 +339,12 @@ namespace Sass {
|
|
345
339
|
{
|
346
340
|
Scope parent = stack.empty() ? Scope::Rules : stack.back();
|
347
341
|
if (parent != Scope::Root && parent != Scope::Rules && parent != Scope::Function) {
|
348
|
-
|
342
|
+
if (which_type == Definition::FUNCTION) {
|
343
|
+
error("Functions may not be defined within control directives or other mixins.", pstate);
|
344
|
+
} else {
|
345
|
+
error("Mixins may not be defined within control directives or other mixins.", pstate);
|
346
|
+
}
|
347
|
+
|
349
348
|
}
|
350
349
|
std::string which_str(lexed);
|
351
350
|
if (!lex< identifier >()) error("invalid name in " + which_str + " definition", pstate);
|
@@ -615,7 +614,7 @@ namespace Sass {
|
|
615
614
|
while (peek_css< exactly<','> >())
|
616
615
|
{
|
617
616
|
lex< css_comments >(false);
|
618
|
-
// consume everything up and including the comma
|
617
|
+
// consume everything up and including the comma separator
|
619
618
|
reloop = lex< exactly<','> >() != 0;
|
620
619
|
// remember line break (also between some commas)
|
621
620
|
had_linefeed = had_linefeed || peek_newline();
|
@@ -719,7 +718,7 @@ namespace Sass {
|
|
719
718
|
// EO parse_complex_selector
|
720
719
|
|
721
720
|
// parse one compound selector, which is basically
|
722
|
-
// a list of simple selectors (directly
|
721
|
+
// a list of simple selectors (directly adjacent)
|
723
722
|
// lex them exactly (without skipping white-space)
|
724
723
|
Compound_Selector* Parser::parse_compound_selector()
|
725
724
|
{
|
@@ -747,7 +746,7 @@ namespace Sass {
|
|
747
746
|
seq->has_parent_reference(true);
|
748
747
|
(*seq) << SASS_MEMORY_NEW(ctx.mem, Parent_Selector, pstate);
|
749
748
|
// parent selector only allowed at start
|
750
|
-
// upcoming
|
749
|
+
// upcoming Sass may allow also trailing
|
751
750
|
if (seq->length() > 1) {
|
752
751
|
ParserState state(pstate);
|
753
752
|
Simple_Selector* cur = (*seq)[seq->length()-1];
|
@@ -834,7 +833,7 @@ namespace Sass {
|
|
834
833
|
}
|
835
834
|
|
836
835
|
// a pseudo selector often starts with one or two colons
|
837
|
-
// it can contain more selectors inside
|
836
|
+
// it can contain more selectors inside parentheses
|
838
837
|
Simple_Selector* Parser::parse_pseudo_selector() {
|
839
838
|
if (lex< sequence<
|
840
839
|
optional < pseudo_prefix >,
|
@@ -1213,9 +1212,9 @@ namespace Sass {
|
|
1213
1212
|
: lex<kwd_lte>() ? Sass_OP::LTE
|
1214
1213
|
: lex<kwd_gt>() ? Sass_OP::GT
|
1215
1214
|
: lex<kwd_lt>() ? Sass_OP::LT
|
1216
|
-
// we checked the
|
1215
|
+
// we checked the possibilities on top of fn
|
1217
1216
|
: Sass_OP::EQ;
|
1218
|
-
// is directly
|
1217
|
+
// is directly adjacent to expression?
|
1219
1218
|
bool right_ws = peek < css_comments >() != NULL;
|
1220
1219
|
operators.push_back({ op, left_ws, right_ws });
|
1221
1220
|
operands.push_back(parse_expression());
|
@@ -1238,7 +1237,6 @@ namespace Sass {
|
|
1238
1237
|
// NOTE: dashes do NOT count as subtract operation
|
1239
1238
|
Expression* lhs = parse_operators();
|
1240
1239
|
// if it's a singleton, return it (don't wrap it)
|
1241
|
-
// if it's a singleton, return it (don't wrap it)
|
1242
1240
|
if (!(peek_css< exactly<'+'> >(position) ||
|
1243
1241
|
// condition is a bit misterious, but some combinations should not be counted as operations
|
1244
1242
|
(peek< no_spaces >(position) && peek< sequence< negate< unsigned_number >, exactly<'-'>, negate< space > > >(position)) ||
|
@@ -1308,7 +1306,6 @@ namespace Sass {
|
|
1308
1306
|
if (!lex_css< exactly<')'> >()) error("unclosed parenthesis", pstate);
|
1309
1307
|
// expression can be evaluated
|
1310
1308
|
// make sure wrapped lists and division expressions are non-delayed within parentheses
|
1311
|
-
// make sure wrapped lists and division expressions are non-delayed within parentheses
|
1312
1309
|
if (value->concrete_type() == Expression::LIST) {
|
1313
1310
|
// List* l = static_cast<List*>(value);
|
1314
1311
|
// if (!l->empty()) (*l)[0]->is_delayed(false);
|
@@ -1416,7 +1413,7 @@ namespace Sass {
|
|
1416
1413
|
if (lex< percentage >())
|
1417
1414
|
{ return SASS_MEMORY_NEW(ctx.mem, Textual, pstate, Textual::PERCENTAGE, lexed); }
|
1418
1415
|
|
1419
|
-
// match hex number first because 0x000 looks like a number followed by an
|
1416
|
+
// match hex number first because 0x000 looks like a number followed by an identifier
|
1420
1417
|
if (lex< sequence < alternatives< hex, hex0 >, negate < exactly<'-'> > > >())
|
1421
1418
|
{ return SASS_MEMORY_NEW(ctx.mem, Textual, pstate, Textual::HEX, lexed); }
|
1422
1419
|
|
@@ -1598,6 +1595,8 @@ namespace Sass {
|
|
1598
1595
|
}
|
1599
1596
|
|
1600
1597
|
const char* e = 0;
|
1598
|
+
const char* ee = end;
|
1599
|
+
end = stop;
|
1601
1600
|
size_t num_items = 0;
|
1602
1601
|
bool need_space = false;
|
1603
1602
|
while (position < stop) {
|
@@ -1607,7 +1606,7 @@ namespace Sass {
|
|
1607
1606
|
}
|
1608
1607
|
if (need_space) {
|
1609
1608
|
need_space = false;
|
1610
|
-
(*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, " ");
|
1609
|
+
// (*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, " ");
|
1611
1610
|
}
|
1612
1611
|
if ((e = peek< re_functional >()) && e < stop) {
|
1613
1612
|
(*schema) << parse_function_call();
|
@@ -1630,23 +1629,26 @@ namespace Sass {
|
|
1630
1629
|
lex < exactly < rbrace > >();
|
1631
1630
|
}
|
1632
1631
|
// lex some string constants or other valid token
|
1633
|
-
// Note: [-+] chars are left over from
|
1632
|
+
// Note: [-+] chars are left over from i.e. `#{3}+3`
|
1634
1633
|
else if (lex< alternatives < exactly<'%'>, exactly < '-' >, exactly < '+' > > >()) {
|
1635
1634
|
(*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
|
1636
1635
|
}
|
1637
|
-
|
1638
|
-
|
1636
|
+
// lex a quoted string
|
1637
|
+
else if (lex< quoted_string >()) {
|
1638
|
+
// need_space = true;
|
1639
|
+
// if (schema->length()) (*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, " ");
|
1640
|
+
// else need_space = true;
|
1641
|
+
(*schema) << parse_string();
|
1639
1642
|
if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) {
|
1640
|
-
need_space = true;
|
1643
|
+
// need_space = true;
|
1641
1644
|
}
|
1645
|
+
if (peek < exactly < '-' > >()) break;
|
1642
1646
|
}
|
1643
|
-
|
1644
|
-
|
1645
|
-
(*schema) << SASS_MEMORY_NEW(ctx.mem, String_Quoted, pstate, lexed, '"');
|
1647
|
+
else if (lex< sequence < identifier > >()) {
|
1648
|
+
(*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
|
1646
1649
|
if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) {
|
1647
|
-
|
1650
|
+
// need_space = true;
|
1648
1651
|
}
|
1649
|
-
if (peek < exactly < '-' > >()) return schema;
|
1650
1652
|
}
|
1651
1653
|
// lex (normalized) variable
|
1652
1654
|
else if (lex< variable >()) {
|
@@ -1677,10 +1679,15 @@ namespace Sass {
|
|
1677
1679
|
(*schema) << parse_factor();
|
1678
1680
|
}
|
1679
1681
|
else {
|
1680
|
-
|
1682
|
+
break;
|
1681
1683
|
}
|
1682
1684
|
++num_items;
|
1683
1685
|
}
|
1686
|
+
if (position != stop) {
|
1687
|
+
(*schema) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, std::string(position, stop));
|
1688
|
+
position = stop;
|
1689
|
+
}
|
1690
|
+
end = ee;
|
1684
1691
|
return schema;
|
1685
1692
|
}
|
1686
1693
|
|
@@ -1773,6 +1780,11 @@ namespace Sass {
|
|
1773
1780
|
suffix = std::string(lexed);
|
1774
1781
|
}
|
1775
1782
|
|
1783
|
+
std::string uri("");
|
1784
|
+
if (url_string) {
|
1785
|
+
uri = url_string->to_string({ NESTED, 5 });
|
1786
|
+
}
|
1787
|
+
|
1776
1788
|
if (String_Schema* schema = dynamic_cast<String_Schema*>(url_string)) {
|
1777
1789
|
String_Schema* res = SASS_MEMORY_NEW(ctx.mem, String_Schema, pstate);
|
1778
1790
|
(*res) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, prefix);
|
@@ -1780,7 +1792,7 @@ namespace Sass {
|
|
1780
1792
|
(*res) << SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, suffix);
|
1781
1793
|
return res;
|
1782
1794
|
} else {
|
1783
|
-
std::string res = prefix +
|
1795
|
+
std::string res = prefix + uri + suffix;
|
1784
1796
|
return SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, res);
|
1785
1797
|
}
|
1786
1798
|
}
|
@@ -1894,7 +1906,7 @@ namespace Sass {
|
|
1894
1906
|
if (!peek< exactly <'$'> >()) {
|
1895
1907
|
css_error("Invalid CSS", " after ", ": expected \"$\", was ");
|
1896
1908
|
}
|
1897
|
-
// we expect a simple
|
1909
|
+
// we expect a simple identifier as the call name
|
1898
1910
|
if (!lex< sequence < exactly <'$'>, identifier > >()) {
|
1899
1911
|
lex< exactly <'$'> >(); // move pstate and position up
|
1900
1912
|
css_error("Invalid CSS", " after ", ": expected identifier, was ");
|
@@ -1905,7 +1917,7 @@ namespace Sass {
|
|
1905
1917
|
// helper to parse identifier
|
1906
1918
|
Token Parser::lex_identifier()
|
1907
1919
|
{
|
1908
|
-
// we expect a simple
|
1920
|
+
// we expect a simple identifier as the call name
|
1909
1921
|
if (!lex< identifier >()) { // ToDo: pstate wrong?
|
1910
1922
|
css_error("Invalid CSS", " after ", ": expected identifier, was ");
|
1911
1923
|
}
|
@@ -2092,7 +2104,7 @@ namespace Sass {
|
|
2092
2104
|
}
|
2093
2105
|
|
2094
2106
|
// TODO: This needs some major work. Although feature conditions
|
2095
|
-
// look like declarations their semantics differ
|
2107
|
+
// look like declarations their semantics differ significantly
|
2096
2108
|
Supports_Condition* Parser::parse_supports_declaration()
|
2097
2109
|
{
|
2098
2110
|
Supports_Condition* cond = 0;
|
@@ -2132,7 +2144,6 @@ namespace Sass {
|
|
2132
2144
|
Block* body = 0;
|
2133
2145
|
At_Root_Expression* expr = 0;
|
2134
2146
|
Lookahead lookahead_result;
|
2135
|
-
// stack.push_back(Scope::Root);
|
2136
2147
|
LOCAL_FLAG(in_at_root, true);
|
2137
2148
|
if (lex< exactly<'('> >()) {
|
2138
2149
|
expr = parse_at_root_expression();
|
@@ -2147,7 +2158,6 @@ namespace Sass {
|
|
2147
2158
|
}
|
2148
2159
|
At_Root_Block* at_root = SASS_MEMORY_NEW(ctx.mem, At_Root_Block, at_source_position, body);
|
2149
2160
|
if (expr) at_root->expression(expr);
|
2150
|
-
// stack.pop_back();
|
2151
2161
|
return at_root;
|
2152
2162
|
}
|
2153
2163
|
|
@@ -2259,7 +2269,7 @@ namespace Sass {
|
|
2259
2269
|
if (const char* q =
|
2260
2270
|
peek <
|
2261
2271
|
alternatives <
|
2262
|
-
// partial
|
2272
|
+
// partial BEM selector
|
2263
2273
|
sequence <
|
2264
2274
|
ampersand,
|
2265
2275
|
one_plus <
|
@@ -2300,7 +2310,7 @@ namespace Sass {
|
|
2300
2310
|
// single or double colon
|
2301
2311
|
optional < pseudo_prefix >
|
2302
2312
|
>,
|
2303
|
-
// accept
|
2313
|
+
// accept hyphens in token
|
2304
2314
|
one_plus < sequence <
|
2305
2315
|
// can start with hyphens
|
2306
2316
|
zero_plus < exactly<'-'> >,
|
@@ -2389,19 +2399,27 @@ namespace Sass {
|
|
2389
2399
|
non_greedy <
|
2390
2400
|
alternatives <
|
2391
2401
|
// consume whitespace
|
2392
|
-
block_comment, spaces,
|
2402
|
+
block_comment, // spaces,
|
2393
2403
|
// main tokens
|
2394
|
-
|
2404
|
+
sequence <
|
2405
|
+
interpolant,
|
2406
|
+
optional <
|
2407
|
+
quoted_string
|
2408
|
+
>
|
2409
|
+
>,
|
2395
2410
|
identifier,
|
2396
2411
|
variable,
|
2397
2412
|
// issue #442
|
2398
2413
|
sequence <
|
2399
2414
|
parenthese_scope,
|
2400
|
-
interpolant
|
2415
|
+
interpolant,
|
2416
|
+
optional <
|
2417
|
+
quoted_string
|
2418
|
+
>
|
2401
2419
|
>
|
2402
2420
|
>,
|
2403
2421
|
sequence <
|
2404
|
-
optional_spaces,
|
2422
|
+
// optional_spaces,
|
2405
2423
|
alternatives <
|
2406
2424
|
exactly<'{'>,
|
2407
2425
|
exactly<'}'>,
|
@@ -2424,7 +2442,7 @@ namespace Sass {
|
|
2424
2442
|
// ToDo: remove
|
2425
2443
|
rv.position = q;
|
2426
2444
|
// check expected opening bracket
|
2427
|
-
// only after
|
2445
|
+
// only after successful matching
|
2428
2446
|
if (peek < exactly<'{'> >(q)) rv.found = q;
|
2429
2447
|
else if (peek < exactly<';'> >(q)) rv.found = q;
|
2430
2448
|
else if (peek < exactly<'}'> >(q)) rv.found = q;
|
data/ext/libsass/src/parser.hpp
CHANGED
@@ -116,7 +116,10 @@ namespace Sass {
|
|
116
116
|
const char* it_before_token = sneak < mx >(start);
|
117
117
|
|
118
118
|
// match the given prelexer
|
119
|
-
|
119
|
+
const char* match = mx(it_before_token);
|
120
|
+
|
121
|
+
// check if match is in valid range
|
122
|
+
return match <= end ? match : 0;
|
120
123
|
|
121
124
|
}
|
122
125
|
|
@@ -142,6 +145,9 @@ namespace Sass {
|
|
142
145
|
// now call matcher to get position after token
|
143
146
|
const char* it_after_token = mx(it_before_token);
|
144
147
|
|
148
|
+
// check if match is in valid range
|
149
|
+
if (it_after_token > end) return 0;
|
150
|
+
|
145
151
|
// maybe we want to update the parser state anyway?
|
146
152
|
if (force == false) {
|
147
153
|
// assertion that we got a valid match
|
@@ -220,7 +220,10 @@ extern "C" {
|
|
220
220
|
size_t imp_size = 0; while (imp) { imp_size ++; imp = imp->next; }
|
221
221
|
// create char* array to hold all paths plus null terminator
|
222
222
|
const char** plugin_paths = (const char**) calloc(imp_size + 1, sizeof(char*));
|
223
|
-
if (plugin_paths == 0)
|
223
|
+
if (plugin_paths == 0) {
|
224
|
+
free(include_paths); //free include_paths before throw
|
225
|
+
throw(std::bad_alloc());
|
226
|
+
}
|
224
227
|
// reset iterator
|
225
228
|
imp = c_ctx->plugin_paths;
|
226
229
|
// copy over the paths
|
data/lib/sassc/version.rb
CHANGED
data/lib/tasks/libsass.rb
CHANGED
@@ -17,6 +17,15 @@ namespace :libsass do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
file "lib/libsass.so" => "Makefile" do
|
20
|
-
|
20
|
+
make_program = ENV['MAKE']
|
21
|
+
make_program ||= case RUBY_PLATFORM
|
22
|
+
when /mswin/
|
23
|
+
'nmake'
|
24
|
+
when /(bsd|solaris)/
|
25
|
+
'gmake'
|
26
|
+
else
|
27
|
+
'make'
|
28
|
+
end
|
29
|
+
sh "#{make_program} lib/libsass.so"
|
21
30
|
end
|
22
31
|
end
|
data/test/native_test.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sassc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
4
|
+
version: 1.8.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Boland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|