sassc 1.9.0 → 1.10.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/README.md +30 -3
- data/ext/libsass/.gitignore +3 -0
- data/ext/libsass/.travis.yml +1 -1
- data/ext/libsass/GNUmakefile.am +7 -7
- data/ext/libsass/Makefile +7 -4
- data/ext/libsass/Makefile.conf +0 -1
- data/ext/libsass/appveyor.yml +6 -2
- data/ext/libsass/docs/api-context.md +4 -4
- data/ext/libsass/docs/api-doc.md +29 -11
- data/ext/libsass/docs/api-importer-example.md +5 -5
- data/ext/libsass/docs/build-on-windows.md +1 -1
- data/ext/libsass/include/sass/base.h +10 -0
- data/ext/libsass/include/sass/version.h +4 -0
- data/ext/libsass/include/sass/version.h.in +4 -0
- data/ext/libsass/include/sass2scss.h +1 -1
- data/ext/libsass/script/ci-build-libsass +15 -3
- data/ext/libsass/src/ast.cpp +161 -6
- data/ext/libsass/src/ast.hpp +71 -44
- data/ext/libsass/src/ast_factory.hpp +1 -1
- data/ext/libsass/src/ast_fwd_decl.hpp +2 -2
- data/ext/libsass/src/constants.cpp +2 -4
- data/ext/libsass/src/constants.hpp +3 -4
- data/ext/libsass/src/context.cpp +16 -17
- data/ext/libsass/src/context.hpp +2 -2
- data/ext/libsass/src/cssize.cpp +19 -8
- data/ext/libsass/src/cssize.hpp +5 -2
- data/ext/libsass/src/debugger.hpp +6 -3
- data/ext/libsass/src/emitter.cpp +1 -1
- data/ext/libsass/src/environment.cpp +1 -1
- data/ext/libsass/src/eval.cpp +42 -14
- data/ext/libsass/src/eval.hpp +1 -1
- data/ext/libsass/src/expand.cpp +24 -8
- data/ext/libsass/src/expand.hpp +2 -1
- data/ext/libsass/src/extend.cpp +55 -15
- data/ext/libsass/src/extend.hpp +5 -1
- data/ext/libsass/src/functions.cpp +10 -5
- data/ext/libsass/src/inspect.cpp +25 -19
- data/ext/libsass/src/inspect.hpp +2 -2
- data/ext/libsass/src/json.cpp +20 -9
- data/ext/libsass/src/json.hpp +5 -5
- data/ext/libsass/src/lexer.cpp +4 -1
- data/ext/libsass/src/lexer.hpp +21 -0
- data/ext/libsass/src/listize.cpp +2 -1
- data/ext/libsass/src/operation.hpp +4 -4
- data/ext/libsass/src/output.cpp +1 -1
- data/ext/libsass/src/output.hpp +1 -1
- data/ext/libsass/src/parser.cpp +189 -90
- data/ext/libsass/src/parser.hpp +42 -2
- data/ext/libsass/src/prelexer.cpp +474 -7
- data/ext/libsass/src/prelexer.hpp +15 -2
- data/ext/libsass/src/remove_placeholders.cpp +5 -5
- data/ext/libsass/src/remove_placeholders.hpp +3 -2
- data/ext/libsass/src/sass.cpp +33 -3
- data/ext/libsass/src/sass2scss.cpp +7 -0
- data/ext/libsass/src/sass_context.cpp +32 -62
- data/ext/libsass/src/sass_functions.cpp +3 -3
- data/ext/libsass/src/sass_values.cpp +5 -5
- data/ext/libsass/src/utf8/unchecked.h +16 -16
- data/ext/libsass/src/util.cpp +51 -30
- data/ext/libsass/src/util.hpp +6 -1
- data/ext/libsass/win/libsass.targets +0 -2
- data/ext/libsass/win/libsass.vcxproj.filters +0 -6
- data/lib/sassc/engine.rb +4 -1
- data/lib/sassc/error.rb +23 -1
- data/lib/sassc/version.rb +1 -1
- data/test/error_test.rb +27 -0
- data/test/native_test.rb +1 -1
- metadata +5 -5
- data/ext/libsass/include/sass/interface.h +0 -105
- data/ext/libsass/src/sass_interface.cpp +0 -215
data/ext/libsass/src/extend.hpp
CHANGED
@@ -24,6 +24,10 @@ namespace Sass {
|
|
24
24
|
public:
|
25
25
|
static Node subweave(Node& one, Node& two, Context& ctx);
|
26
26
|
static Selector_List* extendSelectorList(Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subset_map, bool isReplace, bool& extendedSomething);
|
27
|
+
static Selector_List* extendSelectorList(Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subset_map, bool isReplace = false) {
|
28
|
+
bool extendedSomething = false;
|
29
|
+
return extendSelectorList(pSelectorList, ctx, subset_map, isReplace, extendedSomething);
|
30
|
+
}
|
27
31
|
Extend(Context&, ExtensionSubsetMap&);
|
28
32
|
~Extend() { }
|
29
33
|
|
@@ -31,7 +35,7 @@ namespace Sass {
|
|
31
35
|
void operator()(Ruleset*);
|
32
36
|
void operator()(Supports_Block*);
|
33
37
|
void operator()(Media_Block*);
|
34
|
-
void operator()(
|
38
|
+
void operator()(Directive*);
|
35
39
|
|
36
40
|
template <typename U>
|
37
41
|
void fallback(U x) { return fallback_impl(x); }
|
@@ -902,9 +902,16 @@ namespace Sass {
|
|
902
902
|
BUILT_IN(sass_quote)
|
903
903
|
{
|
904
904
|
AST_Node* arg = env["$string"];
|
905
|
+
// only set quote mark to true if already a string
|
906
|
+
if (String_Quoted* qstr = dynamic_cast<String_Quoted*>(arg)) {
|
907
|
+
qstr->quote_mark('*');
|
908
|
+
return qstr;
|
909
|
+
}
|
910
|
+
// all other nodes must be converted to a string node
|
905
911
|
std::string str(quote(arg->to_string(ctx.c_options), String_Constant::double_quote()));
|
906
912
|
String_Quoted* result = SASS_MEMORY_NEW(ctx.mem, String_Quoted, pstate, str);
|
907
913
|
result->is_delayed(true);
|
914
|
+
result->quote_mark('*');
|
908
915
|
return result;
|
909
916
|
}
|
910
917
|
|
@@ -1815,7 +1822,7 @@ namespace Sass {
|
|
1815
1822
|
}
|
1816
1823
|
|
1817
1824
|
// Cannot be a Universal selector
|
1818
|
-
Type_Selector* pType = dynamic_cast<Type_Selector*>(
|
1825
|
+
Type_Selector* pType = dynamic_cast<Type_Selector*>(childSeq->head()->first());
|
1819
1826
|
if(pType && pType->name() == "*") {
|
1820
1827
|
std::string msg("Can't append `");
|
1821
1828
|
msg += childSeq->to_string();
|
@@ -1882,8 +1889,7 @@ namespace Sass {
|
|
1882
1889
|
ExtensionSubsetMap subset_map;
|
1883
1890
|
extender->populate_extends(extendee, ctx, subset_map);
|
1884
1891
|
|
1885
|
-
|
1886
|
-
Selector_List* result = Extend::extendSelectorList(selector, ctx, subset_map, false, extendedSomething);
|
1892
|
+
Selector_List* result = Extend::extendSelectorList(selector, ctx, subset_map, false);
|
1887
1893
|
|
1888
1894
|
Listize listize(ctx.mem);
|
1889
1895
|
return result->perform(&listize);
|
@@ -1899,8 +1905,7 @@ namespace Sass {
|
|
1899
1905
|
ExtensionSubsetMap subset_map;
|
1900
1906
|
replacement->populate_extends(original, ctx, subset_map);
|
1901
1907
|
|
1902
|
-
|
1903
|
-
Selector_List* result = Extend::extendSelectorList(selector, ctx, subset_map, true, extendedSomething);
|
1908
|
+
Selector_List* result = Extend::extendSelectorList(selector, ctx, subset_map, true);
|
1904
1909
|
|
1905
1910
|
Listize listize(ctx.mem);
|
1906
1911
|
return result->perform(&listize);
|
data/ext/libsass/src/inspect.cpp
CHANGED
@@ -96,7 +96,7 @@ namespace Sass {
|
|
96
96
|
at_root_block->block()->perform(this);
|
97
97
|
}
|
98
98
|
|
99
|
-
void Inspect::operator()(
|
99
|
+
void Inspect::operator()(Directive* at_rule)
|
100
100
|
{
|
101
101
|
append_indentation();
|
102
102
|
append_token(at_rule->keyword(), at_rule);
|
@@ -385,9 +385,12 @@ namespace Sass {
|
|
385
385
|
bool was_space_array = in_space_array;
|
386
386
|
bool was_comma_array = in_comma_array;
|
387
387
|
// probably ruby sass eqivalent of element_needs_parens
|
388
|
-
if (output_style() == TO_SASS &&
|
389
|
-
|
390
|
-
|
388
|
+
if (output_style() == TO_SASS &&
|
389
|
+
list->length() == 1 &&
|
390
|
+
!list->from_selector() &&
|
391
|
+
!dynamic_cast<List*>((*list)[0]) &&
|
392
|
+
!dynamic_cast<List*>((*list)[0]) &&
|
393
|
+
!dynamic_cast<Selector_List*>((*list)[0])) {
|
391
394
|
append_string("(");
|
392
395
|
}
|
393
396
|
else if (!in_declaration && (list->separator() == SASS_HASH ||
|
@@ -424,9 +427,12 @@ namespace Sass {
|
|
424
427
|
in_comma_array = was_comma_array;
|
425
428
|
in_space_array = was_space_array;
|
426
429
|
// probably ruby sass eqivalent of element_needs_parens
|
427
|
-
if (output_style() == TO_SASS &&
|
428
|
-
|
429
|
-
|
430
|
+
if (output_style() == TO_SASS &&
|
431
|
+
list->length() == 1 &&
|
432
|
+
!list->from_selector() &&
|
433
|
+
!dynamic_cast<List*>((*list)[0]) &&
|
434
|
+
!dynamic_cast<List*>((*list)[0]) &&
|
435
|
+
!dynamic_cast<Selector_List*>((*list)[0])) {
|
430
436
|
append_string(",)");
|
431
437
|
}
|
432
438
|
else if (!in_declaration && (list->separator() == SASS_HASH ||
|
@@ -806,20 +812,15 @@ namespace Sass {
|
|
806
812
|
}
|
807
813
|
}
|
808
814
|
|
809
|
-
void Inspect::operator()(
|
815
|
+
void Inspect::operator()(At_Root_Query* ae)
|
810
816
|
{
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
ae->feature()->perform(this);
|
817
|
-
if (ae->value()) {
|
818
|
-
append_colon_separator();
|
819
|
-
ae->value()->perform(this);
|
820
|
-
}
|
821
|
-
append_string(")");
|
817
|
+
append_string("(");
|
818
|
+
ae->feature()->perform(this);
|
819
|
+
if (ae->value()) {
|
820
|
+
append_colon_separator();
|
821
|
+
ae->value()->perform(this);
|
822
822
|
}
|
823
|
+
append_string(")");
|
823
824
|
}
|
824
825
|
|
825
826
|
void Inspect::operator()(Null* n)
|
@@ -974,6 +975,11 @@ namespace Sass {
|
|
974
975
|
Complex_Selector* tail = c->tail();
|
975
976
|
Complex_Selector::Combinator comb = c->combinator();
|
976
977
|
|
978
|
+
if (comb == Complex_Selector::ANCESTOR_OF && (!head || head->empty())) {
|
979
|
+
if (tail) tail->perform(this);
|
980
|
+
return;
|
981
|
+
}
|
982
|
+
|
977
983
|
if (c->has_line_feed()) {
|
978
984
|
if (!(c->has_parent_ref())) {
|
979
985
|
append_optional_linefeed();
|
data/ext/libsass/src/inspect.hpp
CHANGED
@@ -28,7 +28,7 @@ namespace Sass {
|
|
28
28
|
virtual void operator()(Supports_Block*);
|
29
29
|
virtual void operator()(Media_Block*);
|
30
30
|
virtual void operator()(At_Root_Block*);
|
31
|
-
virtual void operator()(
|
31
|
+
virtual void operator()(Directive*);
|
32
32
|
virtual void operator()(Keyframe_Rule*);
|
33
33
|
virtual void operator()(Declaration*);
|
34
34
|
virtual void operator()(Assignment*);
|
@@ -72,7 +72,7 @@ namespace Sass {
|
|
72
72
|
virtual void operator()(Supports_Interpolation*);
|
73
73
|
virtual void operator()(Media_Query*);
|
74
74
|
virtual void operator()(Media_Query_Expression*);
|
75
|
-
virtual void operator()(
|
75
|
+
virtual void operator()(At_Root_Query*);
|
76
76
|
virtual void operator()(Null*);
|
77
77
|
virtual void operator()(Parent_Selector* p);
|
78
78
|
// parameters and arguments
|
data/ext/libsass/src/json.cpp
CHANGED
@@ -28,6 +28,10 @@
|
|
28
28
|
|
29
29
|
#include "json.hpp"
|
30
30
|
|
31
|
+
// include utf8 library used by libsass
|
32
|
+
// ToDo: replace internal json utf8 code
|
33
|
+
#include "utf8.h"
|
34
|
+
|
31
35
|
#include <assert.h>
|
32
36
|
#include <stdint.h>
|
33
37
|
#include <stdio.h>
|
@@ -548,7 +552,7 @@ static void append_node(JsonNode *parent, JsonNode *child)
|
|
548
552
|
child->parent = parent;
|
549
553
|
child->prev = parent->children.tail;
|
550
554
|
child->next = NULL;
|
551
|
-
|
555
|
+
|
552
556
|
if (parent->children.tail != NULL)
|
553
557
|
parent->children.tail->next = child;
|
554
558
|
else
|
@@ -563,7 +567,7 @@ static void prepend_node(JsonNode *parent, JsonNode *child)
|
|
563
567
|
child->parent = parent;
|
564
568
|
child->prev = NULL;
|
565
569
|
child->next = parent->children.head;
|
566
|
-
|
570
|
+
|
567
571
|
if (parent->children.head != NULL)
|
568
572
|
parent->children.head->prev = child;
|
569
573
|
else
|
@@ -585,7 +589,7 @@ void json_append_element(JsonNode *array, JsonNode *element)
|
|
585
589
|
if (array != NULL && element !=NULL) {
|
586
590
|
assert(array->tag == JSON_ARRAY);
|
587
591
|
assert(element->parent == NULL);
|
588
|
-
|
592
|
+
|
589
593
|
append_node(array, element);
|
590
594
|
}
|
591
595
|
}
|
@@ -603,7 +607,7 @@ void json_append_member(JsonNode *object, const char *key, JsonNode *value)
|
|
603
607
|
if (object != NULL && key != NULL && value != NULL) {
|
604
608
|
assert(object->tag == JSON_OBJECT);
|
605
609
|
assert(value->parent == NULL);
|
606
|
-
|
610
|
+
|
607
611
|
append_member(object, json_strdup(key), value);
|
608
612
|
}
|
609
613
|
}
|
@@ -613,7 +617,7 @@ void json_prepend_member(JsonNode *object, const char *key, JsonNode *value)
|
|
613
617
|
if (object != NULL && key != NULL && value != NULL) {
|
614
618
|
assert(object->tag == JSON_OBJECT);
|
615
619
|
assert(value->parent == NULL);
|
616
|
-
|
620
|
+
|
617
621
|
value->key = json_strdup(key);
|
618
622
|
prepend_node(object, value);
|
619
623
|
}
|
@@ -623,20 +627,20 @@ void json_remove_from_parent(JsonNode *node)
|
|
623
627
|
{
|
624
628
|
if (node != NULL) {
|
625
629
|
JsonNode *parent = node->parent;
|
626
|
-
|
630
|
+
|
627
631
|
if (parent != NULL) {
|
628
632
|
if (node->prev != NULL)
|
629
633
|
node->prev->next = node->next;
|
630
634
|
else
|
631
635
|
parent->children.head = node->next;
|
632
|
-
|
636
|
+
|
633
637
|
if (node->next != NULL)
|
634
638
|
node->next->prev = node->prev;
|
635
639
|
else
|
636
640
|
parent->children.tail = node->prev;
|
637
|
-
|
641
|
+
|
638
642
|
free(node->key);
|
639
|
-
|
643
|
+
|
640
644
|
node->parent = NULL;
|
641
645
|
node->prev = node->next = NULL;
|
642
646
|
node->key = NULL;
|
@@ -1141,6 +1145,13 @@ void emit_string(SB *out, const char *str)
|
|
1141
1145
|
const char *s = str;
|
1142
1146
|
char *b;
|
1143
1147
|
|
1148
|
+
// make assertion catchable
|
1149
|
+
#ifndef NDEBUG
|
1150
|
+
if (!utf8_validate(str)) {
|
1151
|
+
throw utf8::invalid_utf8(0);
|
1152
|
+
}
|
1153
|
+
#endif
|
1154
|
+
|
1144
1155
|
assert(utf8_validate(str));
|
1145
1156
|
|
1146
1157
|
/*
|
data/ext/libsass/src/json.hpp
CHANGED
@@ -43,21 +43,21 @@ struct JsonNode
|
|
43
43
|
/* only if parent is an object or array (NULL otherwise) */
|
44
44
|
JsonNode *parent;
|
45
45
|
JsonNode *prev, *next;
|
46
|
-
|
46
|
+
|
47
47
|
/* only if parent is an object (NULL otherwise) */
|
48
48
|
char *key; /* Must be valid UTF-8. */
|
49
|
-
|
49
|
+
|
50
50
|
JsonTag tag;
|
51
51
|
union {
|
52
52
|
/* JSON_BOOL */
|
53
53
|
bool bool_;
|
54
|
-
|
54
|
+
|
55
55
|
/* JSON_STRING */
|
56
56
|
char *string_; /* Must be valid UTF-8. */
|
57
|
-
|
57
|
+
|
58
58
|
/* JSON_NUMBER */
|
59
59
|
double number_;
|
60
|
-
|
60
|
+
|
61
61
|
/* JSON_ARRAY */
|
62
62
|
/* JSON_OBJECT */
|
63
63
|
struct {
|
data/ext/libsass/src/lexer.cpp
CHANGED
@@ -91,7 +91,8 @@ namespace Sass {
|
|
91
91
|
// valid in a uri (copied from Ruby Sass)
|
92
92
|
bool is_uri_character(const char& chr)
|
93
93
|
{
|
94
|
-
return unsigned(chr) > 41 && unsigned(chr) < 127
|
94
|
+
return (unsigned(chr) > 41 && unsigned(chr) < 127) ||
|
95
|
+
unsigned(chr) == ':' || unsigned(chr) == '/';
|
95
96
|
}
|
96
97
|
|
97
98
|
// check if char is within a reduced ascii range
|
@@ -121,6 +122,7 @@ namespace Sass {
|
|
121
122
|
const char* xdigit(const char* src) { return is_xdigit(*src) ? src + 1 : 0; }
|
122
123
|
const char* alnum(const char* src) { return is_alnum(*src) ? src + 1 : 0; }
|
123
124
|
const char* punct(const char* src) { return is_punct(*src) ? src + 1 : 0; }
|
125
|
+
const char* hyphen(const char* src) { return *src && *src == '-' ? src + 1 : 0; }
|
124
126
|
const char* character(const char* src) { return is_character(*src) ? src + 1 : 0; }
|
125
127
|
const char* uri_character(const char* src) { return is_uri_character(*src) ? src + 1 : 0; }
|
126
128
|
const char* escapable_character(const char* src) { return is_escapable_character(*src) ? src + 1 : 0; }
|
@@ -128,6 +130,7 @@ namespace Sass {
|
|
128
130
|
// Match multiple ctype characters.
|
129
131
|
const char* spaces(const char* src) { return one_plus<space>(src); }
|
130
132
|
const char* digits(const char* src) { return one_plus<digit>(src); }
|
133
|
+
const char* hyphens(const char* src) { return one_plus<hyphen>(src); }
|
131
134
|
|
132
135
|
// Whitespace handling.
|
133
136
|
const char* no_spaces(const char* src) { return negate< space >(src); }
|
data/ext/libsass/src/lexer.hpp
CHANGED
@@ -44,6 +44,7 @@ namespace Sass {
|
|
44
44
|
const char* xdigit(const char* src);
|
45
45
|
const char* alnum(const char* src);
|
46
46
|
const char* punct(const char* src);
|
47
|
+
const char* hyphen(const char* src);
|
47
48
|
const char* unicode(const char* src);
|
48
49
|
const char* nonascii(const char* src);
|
49
50
|
const char* character(const char* src);
|
@@ -53,6 +54,7 @@ namespace Sass {
|
|
53
54
|
// Match multiple ctype characters.
|
54
55
|
const char* spaces(const char* src);
|
55
56
|
const char* digits(const char* src);
|
57
|
+
const char* hyphens(const char* src);
|
56
58
|
|
57
59
|
// Whitespace handling.
|
58
60
|
const char* no_spaces(const char* src);
|
@@ -142,6 +144,25 @@ namespace Sass {
|
|
142
144
|
return p == src ? 0 : p;
|
143
145
|
}
|
144
146
|
|
147
|
+
// Match for members of char class.
|
148
|
+
// Regex equivalent: /[^axy]/
|
149
|
+
template <const char* neg_char_class>
|
150
|
+
const char* neg_class_char(const char* src) {
|
151
|
+
if (*src == 0) return 0;
|
152
|
+
const char* cc = neg_char_class;
|
153
|
+
while (*cc && *src != *cc) ++cc;
|
154
|
+
return *cc ? 0 : src + 1;
|
155
|
+
}
|
156
|
+
|
157
|
+
// Match for members of char class.
|
158
|
+
// Regex equivalent: /[^axy]+/
|
159
|
+
template <const char* neg_char_class>
|
160
|
+
const char* neg_class_chars(const char* src) {
|
161
|
+
const char* p = src;
|
162
|
+
while (neg_class_char<neg_char_class>(p)) ++p;
|
163
|
+
return p == src ? 0 : p;
|
164
|
+
}
|
165
|
+
|
145
166
|
// Match all except the supplied one.
|
146
167
|
// Regex equivalent: /[^x]/
|
147
168
|
template <const char chr>
|
data/ext/libsass/src/listize.cpp
CHANGED
@@ -17,6 +17,7 @@ namespace Sass {
|
|
17
17
|
Expression* Listize::operator()(Selector_List* sel)
|
18
18
|
{
|
19
19
|
List* l = SASS_MEMORY_NEW(mem, List, sel->pstate(), sel->length(), SASS_COMMA);
|
20
|
+
l->from_selector(true);
|
20
21
|
for (size_t i = 0, L = sel->length(); i < L; ++i) {
|
21
22
|
if (!(*sel)[i]) continue;
|
22
23
|
*l << (*sel)[i]->perform(this);
|
@@ -38,7 +39,7 @@ namespace Sass {
|
|
38
39
|
Expression* Listize::operator()(Complex_Selector* sel)
|
39
40
|
{
|
40
41
|
List* l = SASS_MEMORY_NEW(mem, List, sel->pstate(), 2);
|
41
|
-
|
42
|
+
l->from_selector(true);
|
42
43
|
Compound_Selector* head = sel->head();
|
43
44
|
if (head && !head->is_empty_reference())
|
44
45
|
{
|
@@ -18,7 +18,7 @@ namespace Sass {
|
|
18
18
|
virtual T operator()(Supports_Block* x) = 0;
|
19
19
|
virtual T operator()(Media_Block* x) = 0;
|
20
20
|
virtual T operator()(At_Root_Block* x) = 0;
|
21
|
-
virtual T operator()(
|
21
|
+
virtual T operator()(Directive* x) = 0;
|
22
22
|
virtual T operator()(Keyframe_Rule* x) = 0;
|
23
23
|
virtual T operator()(Declaration* x) = 0;
|
24
24
|
virtual T operator()(Assignment* x) = 0;
|
@@ -61,7 +61,7 @@ namespace Sass {
|
|
61
61
|
virtual T operator()(Supports_Interpolation* x) = 0;
|
62
62
|
virtual T operator()(Media_Query* x) = 0;
|
63
63
|
virtual T operator()(Media_Query_Expression* x) = 0;
|
64
|
-
virtual T operator()(
|
64
|
+
virtual T operator()(At_Root_Query* x) = 0;
|
65
65
|
virtual T operator()(Null* x) = 0;
|
66
66
|
virtual T operator()(Parent_Selector* x) = 0;
|
67
67
|
// parameters and arguments
|
@@ -99,7 +99,7 @@ namespace Sass {
|
|
99
99
|
T operator()(Supports_Block* x) { return static_cast<D*>(this)->fallback(x); }
|
100
100
|
T operator()(Media_Block* x) { return static_cast<D*>(this)->fallback(x); }
|
101
101
|
T operator()(At_Root_Block* x) { return static_cast<D*>(this)->fallback(x); }
|
102
|
-
T operator()(
|
102
|
+
T operator()(Directive* x) { return static_cast<D*>(this)->fallback(x); }
|
103
103
|
T operator()(Keyframe_Rule* x) { return static_cast<D*>(this)->fallback(x); }
|
104
104
|
T operator()(Declaration* x) { return static_cast<D*>(this)->fallback(x); }
|
105
105
|
T operator()(Assignment* x) { return static_cast<D*>(this)->fallback(x); }
|
@@ -142,7 +142,7 @@ namespace Sass {
|
|
142
142
|
T operator()(Supports_Interpolation* x) { return static_cast<D*>(this)->fallback(x); }
|
143
143
|
T operator()(Media_Query* x) { return static_cast<D*>(this)->fallback(x); }
|
144
144
|
T operator()(Media_Query_Expression* x) { return static_cast<D*>(this)->fallback(x); }
|
145
|
-
T operator()(
|
145
|
+
T operator()(At_Root_Query* x) { return static_cast<D*>(this)->fallback(x); }
|
146
146
|
T operator()(Null* x) { return static_cast<D*>(this)->fallback(x); }
|
147
147
|
T operator()(Parent_Selector* x) { return static_cast<D*>(this)->fallback(x); }
|
148
148
|
// parameters and arguments
|
data/ext/libsass/src/output.cpp
CHANGED
data/ext/libsass/src/output.hpp
CHANGED
@@ -38,7 +38,7 @@ namespace Sass {
|
|
38
38
|
// virtual void operator()(Propset*);
|
39
39
|
virtual void operator()(Supports_Block*);
|
40
40
|
virtual void operator()(Media_Block*);
|
41
|
-
virtual void operator()(
|
41
|
+
virtual void operator()(Directive*);
|
42
42
|
virtual void operator()(Keyframe_Rule*);
|
43
43
|
virtual void operator()(Import*);
|
44
44
|
virtual void operator()(Comment*);
|
data/ext/libsass/src/parser.cpp
CHANGED
@@ -250,7 +250,9 @@ namespace Sass {
|
|
250
250
|
else if (lex< kwd_charset_directive >(true)) { parse_charset_directive(); }
|
251
251
|
|
252
252
|
// generic at keyword (keep last)
|
253
|
-
else if (lex<
|
253
|
+
else if (lex< re_special_directive >(true)) { (*block) << parse_special_directive(); }
|
254
|
+
else if (lex< re_prefixed_directive >(true)) { (*block) << parse_prefixed_directive(); }
|
255
|
+
else if (lex< at_keyword >(true)) { (*block) << parse_directive(); }
|
254
256
|
|
255
257
|
else if (block->is_root()) {
|
256
258
|
lex< css_whitespace >();
|
@@ -1325,10 +1327,7 @@ namespace Sass {
|
|
1325
1327
|
else if (peek< ie_keyword_arg >()) {
|
1326
1328
|
return parse_ie_keyword_arg();
|
1327
1329
|
}
|
1328
|
-
else if (peek<
|
1329
|
-
peek< exactly< moz_calc_kwd > >() ||
|
1330
|
-
peek< exactly< ms_calc_kwd > >() ||
|
1331
|
-
peek< exactly< webkit_calc_kwd > >()) {
|
1330
|
+
else if (peek< sequence < calc_fn_call, exactly <'('> > >()) {
|
1332
1331
|
return parse_calc_function();
|
1333
1332
|
}
|
1334
1333
|
else if (lex < functional_schema >()) {
|
@@ -1773,6 +1772,7 @@ namespace Sass {
|
|
1773
1772
|
prefix = std::string(lexed);
|
1774
1773
|
}
|
1775
1774
|
|
1775
|
+
lex < optional_spaces >();
|
1776
1776
|
String* url_string = parse_url_function_argument();
|
1777
1777
|
|
1778
1778
|
std::string suffix("");
|
@@ -1809,7 +1809,7 @@ namespace Sass {
|
|
1809
1809
|
if (peek< exactly< hash_lbrace > >()) {
|
1810
1810
|
const char* pp = position;
|
1811
1811
|
// TODO: error checking for unclosed interpolants
|
1812
|
-
while (peek< exactly< hash_lbrace > >(pp)) {
|
1812
|
+
while (pp && peek< exactly< hash_lbrace > >(pp)) {
|
1813
1813
|
pp = sequence< interpolant, real_uri_value >(pp);
|
1814
1814
|
}
|
1815
1815
|
position = pp;
|
@@ -2142,13 +2142,14 @@ namespace Sass {
|
|
2142
2142
|
{
|
2143
2143
|
ParserState at_source_position = pstate;
|
2144
2144
|
Block* body = 0;
|
2145
|
-
|
2145
|
+
At_Root_Query* expr = 0;
|
2146
2146
|
Lookahead lookahead_result;
|
2147
2147
|
LOCAL_FLAG(in_at_root, true);
|
2148
|
-
if (
|
2149
|
-
expr =
|
2148
|
+
if (lex_css< exactly<'('> >()) {
|
2149
|
+
expr = parse_at_root_query();
|
2150
2150
|
}
|
2151
|
-
if (
|
2151
|
+
if (peek_css < exactly<'{'> >()) {
|
2152
|
+
lex <optional_spaces>();
|
2152
2153
|
body = parse_block(true);
|
2153
2154
|
}
|
2154
2155
|
else if ((lookahead_result = lookahead_for_selector(position)).found) {
|
@@ -2161,7 +2162,7 @@ namespace Sass {
|
|
2161
2162
|
return at_root;
|
2162
2163
|
}
|
2163
2164
|
|
2164
|
-
|
2165
|
+
At_Root_Query* Parser::parse_at_root_query()
|
2165
2166
|
{
|
2166
2167
|
if (peek< exactly<')'> >()) error("at-root feature required in at-root expression", pstate);
|
2167
2168
|
|
@@ -2169,29 +2170,60 @@ namespace Sass {
|
|
2169
2170
|
css_error("Invalid CSS", " after ", ": expected \"with\" or \"without\", was ");
|
2170
2171
|
}
|
2171
2172
|
|
2172
|
-
|
2173
|
-
|
2173
|
+
Expression* feature = parse_list();
|
2174
|
+
if (!lex_css< exactly<':'> >()) error("style declaration must contain a value", pstate);
|
2175
|
+
Expression* expression = parse_list();
|
2176
|
+
List* value = SASS_MEMORY_NEW(ctx.mem, List, feature->pstate(), 1);
|
2174
2177
|
|
2175
|
-
if (
|
2176
|
-
value = static_cast<List*>(
|
2178
|
+
if (expression->concrete_type() == Expression::LIST) {
|
2179
|
+
value = static_cast<List*>(expression);
|
2177
2180
|
}
|
2178
|
-
else *value <<
|
2181
|
+
else *value << expression;
|
2179
2182
|
|
2180
|
-
|
2181
|
-
|
2182
|
-
|
2183
|
-
|
2184
|
-
if (!
|
2183
|
+
At_Root_Query* cond = SASS_MEMORY_NEW(ctx.mem, At_Root_Query,
|
2184
|
+
value->pstate(),
|
2185
|
+
feature,
|
2186
|
+
value);
|
2187
|
+
if (!lex_css< exactly<')'> >()) error("unclosed parenthesis in @at-root expression", pstate);
|
2185
2188
|
return cond;
|
2186
2189
|
}
|
2187
2190
|
|
2188
|
-
|
2191
|
+
Directive* Parser::parse_special_directive()
|
2192
|
+
{
|
2193
|
+
std::string kwd(lexed);
|
2194
|
+
|
2195
|
+
if (lexed == "@else") error("Invalid CSS: @else must come after @if", pstate);
|
2196
|
+
|
2197
|
+
Directive* at_rule = SASS_MEMORY_NEW(ctx.mem, Directive, pstate, kwd);
|
2198
|
+
Lookahead lookahead = lookahead_for_include(position);
|
2199
|
+
if (lookahead.found && !lookahead.has_interpolants) {
|
2200
|
+
at_rule->selector(parse_selector_list(true));
|
2201
|
+
}
|
2202
|
+
|
2203
|
+
lex < css_comments >(false);
|
2204
|
+
|
2205
|
+
if (lex < static_property >()) {
|
2206
|
+
at_rule->value(parse_interpolated_chunk(Token(lexed)));
|
2207
|
+
} else if (!(peek < alternatives < exactly<'{'>, exactly<'}'>, exactly<';'> > >())) {
|
2208
|
+
at_rule->value(parse_list());
|
2209
|
+
}
|
2210
|
+
|
2211
|
+
lex < css_comments >(false);
|
2212
|
+
|
2213
|
+
if (peek< exactly<'{'> >()) {
|
2214
|
+
at_rule->block(parse_block());
|
2215
|
+
}
|
2216
|
+
|
2217
|
+
return at_rule;
|
2218
|
+
}
|
2219
|
+
|
2220
|
+
Directive* Parser::parse_prefixed_directive()
|
2189
2221
|
{
|
2190
2222
|
std::string kwd(lexed);
|
2191
2223
|
|
2192
2224
|
if (lexed == "@else") error("Invalid CSS: @else must come after @if", pstate);
|
2193
2225
|
|
2194
|
-
|
2226
|
+
Directive* at_rule = SASS_MEMORY_NEW(ctx.mem, Directive, pstate, kwd);
|
2195
2227
|
Lookahead lookahead = lookahead_for_include(position);
|
2196
2228
|
if (lookahead.found && !lookahead.has_interpolants) {
|
2197
2229
|
at_rule->selector(parse_selector_list(true));
|
@@ -2214,6 +2246,137 @@ namespace Sass {
|
|
2214
2246
|
return at_rule;
|
2215
2247
|
}
|
2216
2248
|
|
2249
|
+
|
2250
|
+
Directive* Parser::parse_directive()
|
2251
|
+
{
|
2252
|
+
Directive* directive = SASS_MEMORY_NEW(ctx.mem, Directive, pstate, lexed);
|
2253
|
+
Expression* val = parse_almost_any_value();
|
2254
|
+
// strip left and right if they are of type string
|
2255
|
+
// debug_ast(val);
|
2256
|
+
// std::cerr << "HAASDASD\n";
|
2257
|
+
directive->value(val);
|
2258
|
+
if (peek< exactly<'{'> >()) {
|
2259
|
+
directive->block(parse_block());
|
2260
|
+
} else if (!val) {
|
2261
|
+
css_error("most def");
|
2262
|
+
}
|
2263
|
+
return directive;
|
2264
|
+
}
|
2265
|
+
|
2266
|
+
Expression* Parser::lex_interpolation()
|
2267
|
+
{
|
2268
|
+
if (lex < interpolant >(true) != NULL) {
|
2269
|
+
return parse_interpolated_chunk(lexed, true);
|
2270
|
+
}
|
2271
|
+
return 0;
|
2272
|
+
}
|
2273
|
+
|
2274
|
+
Expression* Parser::lex_interp_uri()
|
2275
|
+
{
|
2276
|
+
// create a string schema by lexing optional interpolations
|
2277
|
+
return lex_interp< re_string_uri_open, re_string_uri_close >();
|
2278
|
+
}
|
2279
|
+
|
2280
|
+
Expression* Parser::lex_interp_string()
|
2281
|
+
{
|
2282
|
+
Expression* rv = 0;
|
2283
|
+
if ((rv = lex_interp< re_string_double_open, re_string_double_close >()) != NULL) return rv;
|
2284
|
+
if ((rv = lex_interp< re_string_single_open, re_string_single_close >()) != NULL) return rv;
|
2285
|
+
return rv;
|
2286
|
+
}
|
2287
|
+
|
2288
|
+
Expression* Parser::lex_almost_any_value_chars()
|
2289
|
+
{
|
2290
|
+
const char* match =
|
2291
|
+
lex <
|
2292
|
+
one_plus <
|
2293
|
+
alternatives <
|
2294
|
+
sequence <
|
2295
|
+
exactly <'\\'>,
|
2296
|
+
any_char
|
2297
|
+
>,
|
2298
|
+
sequence <
|
2299
|
+
negate <
|
2300
|
+
sequence <
|
2301
|
+
exactly < url_kwd >,
|
2302
|
+
exactly <'('>
|
2303
|
+
>
|
2304
|
+
>,
|
2305
|
+
neg_class_char <
|
2306
|
+
almost_any_value_class
|
2307
|
+
>
|
2308
|
+
>,
|
2309
|
+
sequence <
|
2310
|
+
exactly <'/'>,
|
2311
|
+
negate <
|
2312
|
+
alternatives <
|
2313
|
+
exactly <'/'>,
|
2314
|
+
exactly <'*'>
|
2315
|
+
>
|
2316
|
+
>
|
2317
|
+
>,
|
2318
|
+
sequence <
|
2319
|
+
exactly <'\\'>,
|
2320
|
+
exactly <'#'>,
|
2321
|
+
negate <
|
2322
|
+
exactly <'{'>
|
2323
|
+
>
|
2324
|
+
>,
|
2325
|
+
sequence <
|
2326
|
+
exactly <'!'>,
|
2327
|
+
negate <
|
2328
|
+
alpha
|
2329
|
+
>
|
2330
|
+
>
|
2331
|
+
>
|
2332
|
+
>
|
2333
|
+
>(false);
|
2334
|
+
if (match) {
|
2335
|
+
// std::cerr << "[[" << std::string(lexed) << "]\n";
|
2336
|
+
return SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
|
2337
|
+
}
|
2338
|
+
return NULL;
|
2339
|
+
}
|
2340
|
+
|
2341
|
+
Expression* Parser::lex_almost_any_value_token()
|
2342
|
+
{
|
2343
|
+
Expression* rv = 0;
|
2344
|
+
if (*position == 0) return 0;
|
2345
|
+
if ((rv = lex_almost_any_value_chars()) != NULL) return rv;
|
2346
|
+
// if ((rv = lex_block_comment()) != NULL) return rv;
|
2347
|
+
// if ((rv = lex_single_line_comment()) != NULL) return rv;
|
2348
|
+
if ((rv = lex_interp_string()) != NULL) return rv;
|
2349
|
+
if ((rv = lex_interp_uri()) != NULL) return rv;
|
2350
|
+
if ((rv = lex_interpolation()) != NULL) return rv;
|
2351
|
+
return rv;
|
2352
|
+
}
|
2353
|
+
|
2354
|
+
String_Schema* Parser::parse_almost_any_value()
|
2355
|
+
{
|
2356
|
+
|
2357
|
+
String_Schema* schema = SASS_MEMORY_NEW(ctx.mem, String_Schema, pstate);
|
2358
|
+
if (*position == 0) return 0;
|
2359
|
+
lex < spaces >(false);
|
2360
|
+
Expression* token = lex_almost_any_value_token();
|
2361
|
+
if (!token) return 0;
|
2362
|
+
// std::cerr << "LEX [" << std::string(lexed) << "]\n";
|
2363
|
+
*schema << token;
|
2364
|
+
if (*position == 0) {
|
2365
|
+
schema->rtrim();
|
2366
|
+
return schema;
|
2367
|
+
}
|
2368
|
+
|
2369
|
+
while ((token = lex_almost_any_value_token())) {
|
2370
|
+
*schema << token;
|
2371
|
+
}
|
2372
|
+
|
2373
|
+
lex < css_whitespace >();
|
2374
|
+
|
2375
|
+
schema->rtrim();
|
2376
|
+
|
2377
|
+
return schema;
|
2378
|
+
}
|
2379
|
+
|
2217
2380
|
Warning* Parser::parse_warning()
|
2218
2381
|
{
|
2219
2382
|
if (stack.back() != Scope::Root &&
|
@@ -2268,72 +2431,7 @@ namespace Sass {
|
|
2268
2431
|
rv.error = p;
|
2269
2432
|
if (const char* q =
|
2270
2433
|
peek <
|
2271
|
-
|
2272
|
-
// partial BEM selector
|
2273
|
-
sequence <
|
2274
|
-
ampersand,
|
2275
|
-
one_plus <
|
2276
|
-
exactly < '-' >
|
2277
|
-
>,
|
2278
|
-
word_boundary
|
2279
|
-
>,
|
2280
|
-
// main selector matching
|
2281
|
-
one_plus <
|
2282
|
-
alternatives <
|
2283
|
-
// consume whitespace and comments
|
2284
|
-
spaces, block_comment, line_comment,
|
2285
|
-
// match `/deep/` selector (pass-trough)
|
2286
|
-
// there is no functionality for it yet
|
2287
|
-
schema_reference_combinator,
|
2288
|
-
// match selector ops /[*&%,()\[\]]/
|
2289
|
-
class_char < selector_lookahead_ops >,
|
2290
|
-
// match selector combinators /[>+~]/
|
2291
|
-
class_char < selector_combinator_ops >,
|
2292
|
-
// match attribute compare operators
|
2293
|
-
alternatives <
|
2294
|
-
exact_match, class_match, dash_match,
|
2295
|
-
prefix_match, suffix_match, substring_match
|
2296
|
-
>,
|
2297
|
-
// main selector match
|
2298
|
-
sequence <
|
2299
|
-
// allow namespace prefix
|
2300
|
-
optional < namespace_schema >,
|
2301
|
-
// modifiers prefixes
|
2302
|
-
alternatives <
|
2303
|
-
sequence <
|
2304
|
-
exactly <'#'>,
|
2305
|
-
// not for interpolation
|
2306
|
-
negate < exactly <'{'> >
|
2307
|
-
>,
|
2308
|
-
// class match
|
2309
|
-
exactly <'.'>,
|
2310
|
-
// single or double colon
|
2311
|
-
optional < pseudo_prefix >
|
2312
|
-
>,
|
2313
|
-
// accept hyphens in token
|
2314
|
-
one_plus < sequence <
|
2315
|
-
// can start with hyphens
|
2316
|
-
zero_plus < exactly<'-'> >,
|
2317
|
-
// now the main token
|
2318
|
-
alternatives <
|
2319
|
-
kwd_optional,
|
2320
|
-
exactly <'*'>,
|
2321
|
-
quoted_string,
|
2322
|
-
interpolant,
|
2323
|
-
identifier,
|
2324
|
-
variable,
|
2325
|
-
percentage,
|
2326
|
-
binomial,
|
2327
|
-
dimension,
|
2328
|
-
alnum
|
2329
|
-
>
|
2330
|
-
> >,
|
2331
|
-
// can also end with hyphens
|
2332
|
-
zero_plus < exactly<'-'> >
|
2333
|
-
>
|
2334
|
-
>
|
2335
|
-
>
|
2336
|
-
>
|
2434
|
+
re_selector_list
|
2337
2435
|
>(p)
|
2338
2436
|
) {
|
2339
2437
|
while (p < q) {
|
@@ -2353,6 +2451,7 @@ namespace Sass {
|
|
2353
2451
|
// check expected opening bracket
|
2354
2452
|
// only after successfull matching
|
2355
2453
|
if (peek < exactly<'{'> >(q)) rv.found = q;
|
2454
|
+
else if (peek < exactly<'('> >(q)) rv.found = q;
|
2356
2455
|
// else if (peek < exactly<';'> >(q)) rv.found = q;
|
2357
2456
|
// else if (peek < exactly<'}'> >(q)) rv.found = q;
|
2358
2457
|
if (rv.found || *p == 0) rv.error = 0;
|
@@ -2366,7 +2465,7 @@ namespace Sass {
|
|
2366
2465
|
}
|
2367
2466
|
// EO lookahead_for_selector
|
2368
2467
|
|
2369
|
-
// used in parse_block_nodes and
|
2468
|
+
// used in parse_block_nodes and parse_special_directive
|
2370
2469
|
// ToDo: actual usage is still not really clear to me?
|
2371
2470
|
Lookahead Parser::lookahead_for_include(const char* start)
|
2372
2471
|
{
|