sassc 1.8.4 → 1.8.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Linux CI](https://travis-ci.org/sass/libsass.
|
6
|
+
[![Linux CI](https://travis-ci.org/sass/libsass.svg?branch=master)](https://travis-ci.org/sass/libsass)
|
7
7
|
[![Windows CI](https://ci.appveyor.com/api/projects/status/github/sass/libsass?svg=true)](https://ci.appveyor.com/project/sass/libsass/branch/master)
|
8
8
|
[![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=283068)](https://www.bountysource.com/trackers/283068-libsass?utm_source=283068&utm_medium=shield&utm_campaign=TRACKER_BADGE)
|
9
9
|
[![Coverage Status](https://img.shields.io/coveralls/sass/libsass.svg)](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
|