sassc 2.0.1 → 2.1.0.pre1
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/.gitignore +1 -0
- data/.gitmodules +1 -1
- data/.travis.yml +7 -3
- data/CHANGELOG.md +3 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/README.md +1 -1
- data/Rakefile +23 -8
- data/ext/extconf.rb +39 -0
- data/ext/libsass/.gitignore +1 -0
- data/ext/libsass/GNUmakefile.am +23 -39
- data/ext/libsass/Makefile +56 -91
- data/ext/libsass/Makefile.conf +16 -2
- data/ext/libsass/configure.ac +8 -12
- data/ext/libsass/include/sass/base.h +1 -0
- data/ext/libsass/include/sass/context.h +1 -1
- data/ext/libsass/src/GNUmakefile.am +1 -5
- data/ext/libsass/src/ast.cpp +747 -2010
- data/ext/libsass/src/ast.hpp +239 -2383
- data/ext/libsass/src/{to_c.cpp → ast2c.cpp} +22 -16
- data/ext/libsass/src/ast2c.hpp +39 -0
- data/ext/libsass/src/ast_def_macros.hpp +62 -10
- data/ext/libsass/src/ast_fwd_decl.cpp +1 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +43 -165
- data/ext/libsass/src/ast_sel_cmp.cpp +909 -0
- data/ext/libsass/src/ast_sel_unify.cpp +280 -0
- data/ext/libsass/src/ast_selectors.cpp +1475 -0
- data/ext/libsass/src/ast_selectors.hpp +568 -0
- data/ext/libsass/src/ast_supports.cpp +130 -0
- data/ext/libsass/src/ast_supports.hpp +121 -0
- data/ext/libsass/src/ast_values.cpp +967 -0
- data/ext/libsass/src/ast_values.hpp +489 -0
- data/ext/libsass/src/backtrace.cpp +4 -0
- data/ext/libsass/src/base64vlq.cpp +3 -0
- data/ext/libsass/src/bind.cpp +18 -17
- data/ext/libsass/src/bind.hpp +3 -1
- data/ext/libsass/src/c2ast.cpp +64 -0
- data/ext/libsass/src/c2ast.hpp +14 -0
- data/ext/libsass/src/cencode.c +2 -2
- data/ext/libsass/src/check_nesting.cpp +52 -56
- data/ext/libsass/src/check_nesting.hpp +35 -34
- data/ext/libsass/src/color_maps.cpp +156 -153
- data/ext/libsass/src/color_maps.hpp +152 -152
- data/ext/libsass/src/constants.cpp +15 -0
- data/ext/libsass/src/constants.hpp +13 -0
- data/ext/libsass/src/context.cpp +24 -14
- data/ext/libsass/src/context.hpp +6 -6
- data/ext/libsass/src/cssize.cpp +69 -71
- data/ext/libsass/src/cssize.hpp +50 -50
- data/ext/libsass/src/debugger.hpp +117 -110
- data/ext/libsass/src/emitter.cpp +13 -12
- data/ext/libsass/src/emitter.hpp +13 -9
- data/ext/libsass/src/environment.cpp +15 -1
- data/ext/libsass/src/environment.hpp +6 -0
- data/ext/libsass/src/error_handling.cpp +36 -59
- data/ext/libsass/src/error_handling.hpp +29 -16
- data/ext/libsass/src/eval.cpp +302 -323
- data/ext/libsass/src/eval.hpp +64 -55
- data/ext/libsass/src/expand.cpp +94 -88
- data/ext/libsass/src/expand.hpp +33 -37
- data/ext/libsass/src/extend.cpp +38 -36
- data/ext/libsass/src/extend.hpp +15 -15
- data/ext/libsass/src/file.cpp +34 -2
- data/ext/libsass/src/fn_colors.cpp +594 -0
- data/ext/libsass/src/fn_colors.hpp +85 -0
- data/ext/libsass/src/fn_lists.cpp +284 -0
- data/ext/libsass/src/fn_lists.hpp +34 -0
- data/ext/libsass/src/fn_maps.cpp +94 -0
- data/ext/libsass/src/fn_maps.hpp +30 -0
- data/ext/libsass/src/fn_miscs.cpp +256 -0
- data/ext/libsass/src/fn_miscs.hpp +40 -0
- data/ext/libsass/src/fn_numbers.cpp +220 -0
- data/ext/libsass/src/fn_numbers.hpp +45 -0
- data/ext/libsass/src/fn_selectors.cpp +235 -0
- data/ext/libsass/src/fn_selectors.hpp +35 -0
- data/ext/libsass/src/fn_strings.cpp +254 -0
- data/ext/libsass/src/fn_strings.hpp +34 -0
- data/ext/libsass/src/fn_utils.cpp +156 -0
- data/ext/libsass/src/fn_utils.hpp +56 -0
- data/ext/libsass/src/inspect.cpp +101 -152
- data/ext/libsass/src/inspect.hpp +69 -73
- data/ext/libsass/src/json.cpp +2 -2
- data/ext/libsass/src/lexer.cpp +6 -3
- data/ext/libsass/src/listize.cpp +9 -11
- data/ext/libsass/src/listize.hpp +11 -7
- data/ext/libsass/src/memory/SharedPtr.cpp +2 -83
- data/ext/libsass/src/memory/SharedPtr.hpp +127 -143
- data/ext/libsass/src/node.cpp +13 -10
- data/ext/libsass/src/node.hpp +3 -3
- data/ext/libsass/src/operation.hpp +184 -144
- data/ext/libsass/src/operators.cpp +43 -17
- data/ext/libsass/src/operators.hpp +5 -5
- data/ext/libsass/src/output.cpp +21 -18
- data/ext/libsass/src/output.hpp +14 -21
- data/ext/libsass/src/parser.cpp +215 -183
- data/ext/libsass/src/parser.hpp +28 -24
- data/ext/libsass/src/plugins.cpp +5 -1
- data/ext/libsass/src/position.cpp +3 -0
- data/ext/libsass/src/prelexer.cpp +9 -3
- data/ext/libsass/src/prelexer.hpp +9 -9
- data/ext/libsass/src/remove_placeholders.cpp +14 -11
- data/ext/libsass/src/remove_placeholders.hpp +8 -9
- data/ext/libsass/src/sass.cpp +9 -3
- data/ext/libsass/src/sass.hpp +12 -9
- data/ext/libsass/src/sass2scss.cpp +45 -14
- data/ext/libsass/src/sass_context.cpp +18 -15
- data/ext/libsass/src/sass_functions.cpp +6 -3
- data/ext/libsass/src/sass_functions.hpp +1 -1
- data/ext/libsass/src/sass_util.cpp +3 -0
- data/ext/libsass/src/sass_values.cpp +21 -13
- data/ext/libsass/src/source_map.cpp +5 -2
- data/ext/libsass/src/source_map.hpp +2 -2
- data/ext/libsass/src/subset_map.cpp +4 -1
- data/ext/libsass/src/to_value.cpp +23 -21
- data/ext/libsass/src/to_value.hpp +18 -22
- data/ext/libsass/src/units.cpp +4 -0
- data/ext/libsass/src/units.hpp +1 -0
- data/ext/libsass/src/utf8/checked.h +12 -10
- data/ext/libsass/src/utf8/core.h +3 -0
- data/ext/libsass/src/utf8_string.cpp +3 -0
- data/ext/libsass/src/util.cpp +67 -75
- data/ext/libsass/src/util.hpp +64 -19
- data/ext/libsass/src/util_string.cpp +75 -0
- data/ext/libsass/src/util_string.hpp +19 -0
- data/ext/libsass/src/values.cpp +22 -13
- data/ext/libsass/src/values.hpp +2 -2
- data/ext/libsass/win/libsass.targets +30 -4
- data/ext/libsass/win/libsass.vcxproj.filters +82 -4
- data/lib/sassc.rb +24 -0
- data/lib/sassc/engine.rb +2 -2
- data/lib/sassc/native.rb +8 -1
- data/lib/sassc/version.rb +1 -1
- data/sassc.gemspec +19 -11
- data/test/engine_test.rb +26 -1
- data/test/native_test.rb +1 -1
- metadata +66 -72
- data/ext/Rakefile +0 -3
- data/ext/libsass/.github/CONTRIBUTING.md +0 -65
- data/ext/libsass/.github/ISSUE_TEMPLATE.md +0 -54
- data/ext/libsass/.travis.yml +0 -64
- data/ext/libsass/Readme.md +0 -104
- data/ext/libsass/SECURITY.md +0 -10
- data/ext/libsass/appveyor.yml +0 -91
- data/ext/libsass/docs/README.md +0 -20
- data/ext/libsass/docs/api-context-example.md +0 -45
- data/ext/libsass/docs/api-context-internal.md +0 -163
- data/ext/libsass/docs/api-context.md +0 -295
- data/ext/libsass/docs/api-doc.md +0 -215
- data/ext/libsass/docs/api-function-example.md +0 -67
- data/ext/libsass/docs/api-function-internal.md +0 -8
- data/ext/libsass/docs/api-function.md +0 -74
- data/ext/libsass/docs/api-importer-example.md +0 -112
- data/ext/libsass/docs/api-importer-internal.md +0 -20
- data/ext/libsass/docs/api-importer.md +0 -86
- data/ext/libsass/docs/api-value-example.md +0 -55
- data/ext/libsass/docs/api-value-internal.md +0 -76
- data/ext/libsass/docs/api-value.md +0 -154
- data/ext/libsass/docs/build-on-darwin.md +0 -27
- data/ext/libsass/docs/build-on-gentoo.md +0 -55
- data/ext/libsass/docs/build-on-windows.md +0 -139
- data/ext/libsass/docs/build-shared-library.md +0 -35
- data/ext/libsass/docs/build-with-autotools.md +0 -78
- data/ext/libsass/docs/build-with-makefiles.md +0 -68
- data/ext/libsass/docs/build-with-mingw.md +0 -107
- data/ext/libsass/docs/build-with-visual-studio.md +0 -90
- data/ext/libsass/docs/build.md +0 -97
- data/ext/libsass/docs/compatibility-plan.md +0 -48
- data/ext/libsass/docs/contributing.md +0 -17
- data/ext/libsass/docs/custom-functions-internal.md +0 -122
- data/ext/libsass/docs/dev-ast-memory.md +0 -223
- data/ext/libsass/docs/implementations.md +0 -56
- data/ext/libsass/docs/plugins.md +0 -47
- data/ext/libsass/docs/setup-environment.md +0 -68
- data/ext/libsass/docs/source-map-internals.md +0 -51
- data/ext/libsass/docs/trace.md +0 -26
- data/ext/libsass/docs/triage.md +0 -17
- data/ext/libsass/docs/unicode.md +0 -39
- data/ext/libsass/extconf.rb +0 -6
- data/ext/libsass/script/bootstrap +0 -13
- data/ext/libsass/script/branding +0 -10
- data/ext/libsass/script/ci-build-libsass +0 -134
- data/ext/libsass/script/ci-build-plugin +0 -62
- data/ext/libsass/script/ci-install-compiler +0 -6
- data/ext/libsass/script/ci-install-deps +0 -20
- data/ext/libsass/script/ci-report-coverage +0 -42
- data/ext/libsass/script/spec +0 -5
- data/ext/libsass/script/tap-driver +0 -652
- data/ext/libsass/script/tap-runner +0 -1
- data/ext/libsass/script/test-leaks.pl +0 -103
- data/ext/libsass/src/functions.cpp +0 -2234
- data/ext/libsass/src/functions.hpp +0 -198
- data/ext/libsass/src/to_c.hpp +0 -39
- data/ext/libsass/test/test_node.cpp +0 -94
- data/ext/libsass/test/test_paths.cpp +0 -28
- data/ext/libsass/test/test_selector_difference.cpp +0 -25
- data/ext/libsass/test/test_specificity.cpp +0 -25
- data/ext/libsass/test/test_subset_map.cpp +0 -472
- data/ext/libsass/test/test_superselector.cpp +0 -69
- data/ext/libsass/test/test_unification.cpp +0 -31
- data/lib/tasks/libsass.rb +0 -33
@@ -1,4 +1,7 @@
|
|
1
|
+
// sass.hpp must go before all system headers to get the
|
2
|
+
// __EXTENSIONS__ fix on Solaris.
|
1
3
|
#include "sass.hpp"
|
4
|
+
|
2
5
|
#include "operators.hpp"
|
3
6
|
|
4
7
|
namespace Sass {
|
@@ -54,13 +57,24 @@ namespace Sass {
|
|
54
57
|
bool lte(Expression_Obj lhs, Expression_Obj rhs) { return cmp(lhs, rhs, Sass_OP::LTE) || eq(lhs, rhs); }
|
55
58
|
bool gte(Expression_Obj lhs, Expression_Obj rhs) { return !cmp(lhs, rhs, Sass_OP::GTE) || eq(lhs, rhs); }
|
56
59
|
|
60
|
+
/* colour math deprecation warning */
|
61
|
+
void op_color_deprecation(enum Sass_OP op, std::string lsh, std::string rhs, const ParserState& pstate)
|
62
|
+
{
|
63
|
+
deprecated(
|
64
|
+
"The operation `" + lsh + " " + sass_op_to_name(op) + " " + rhs +
|
65
|
+
"` is deprecated and will be an error in future versions.",
|
66
|
+
"Consider using Sass's color functions instead.\n"
|
67
|
+
"https://sass-lang.com/documentation/Sass/Script/Functions.html#other_color_functions",
|
68
|
+
/*with_column=*/false, pstate);
|
69
|
+
}
|
70
|
+
|
57
71
|
/* static function, throws OperationError, has no traces but optional pstate for returned value */
|
58
|
-
|
72
|
+
Value* op_strings(Sass::Operand operand, Value& lhs, Value& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
|
59
73
|
{
|
60
74
|
enum Sass_OP op = operand.operand;
|
61
75
|
|
62
|
-
|
63
|
-
|
76
|
+
String_Quoted* lqstr = Cast<String_Quoted>(&lhs);
|
77
|
+
String_Quoted* rqstr = Cast<String_Quoted>(&rhs);
|
64
78
|
|
65
79
|
std::string lstr(lqstr ? lqstr->value() : lhs.to_string(opt));
|
66
80
|
std::string rstr(rqstr ? rqstr->value() : rhs.to_string(opt));
|
@@ -104,16 +118,21 @@ namespace Sass {
|
|
104
118
|
return SASS_MEMORY_NEW(String_Constant, pstate, lstr + sep + rstr);
|
105
119
|
}
|
106
120
|
|
121
|
+
/* ToDo: allow to operate also with hsla colors */
|
107
122
|
/* static function, throws OperationError, has no traces but optional pstate for returned value */
|
108
|
-
|
123
|
+
Value* op_colors(enum Sass_OP op, const Color_RGBA& lhs, const Color_RGBA& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
|
109
124
|
{
|
125
|
+
|
110
126
|
if (lhs.a() != rhs.a()) {
|
111
127
|
throw Exception::AlphaChannelsNotEqual(&lhs, &rhs, op);
|
112
128
|
}
|
113
|
-
if (op == Sass_OP::DIV && (!rhs.r() || !rhs.g() || !rhs.b())) {
|
129
|
+
if ((op == Sass_OP::DIV || op == Sass_OP::MOD) && (!rhs.r() || !rhs.g() || !rhs.b())) {
|
114
130
|
throw Exception::ZeroDivisionError(lhs, rhs);
|
115
131
|
}
|
116
|
-
|
132
|
+
|
133
|
+
op_color_deprecation(op, lhs.to_string(), rhs.to_string(), pstate);
|
134
|
+
|
135
|
+
return SASS_MEMORY_NEW(Color_RGBA,
|
117
136
|
pstate,
|
118
137
|
ops[op](lhs.r(), rhs.r()),
|
119
138
|
ops[op](lhs.g(), rhs.g()),
|
@@ -122,20 +141,20 @@ namespace Sass {
|
|
122
141
|
}
|
123
142
|
|
124
143
|
/* static function, throws OperationError, has no traces but optional pstate for returned value */
|
125
|
-
|
144
|
+
Value* op_numbers(enum Sass_OP op, const Number& lhs, const Number& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
|
126
145
|
{
|
127
146
|
double lval = lhs.value();
|
128
147
|
double rval = rhs.value();
|
129
148
|
|
149
|
+
if (op == Sass_OP::MOD && rval == 0) {
|
150
|
+
return SASS_MEMORY_NEW(String_Quoted, pstate, "NaN");
|
151
|
+
}
|
152
|
+
|
130
153
|
if (op == Sass_OP::DIV && rval == 0) {
|
131
154
|
std::string result(lval ? "Infinity" : "NaN");
|
132
155
|
return SASS_MEMORY_NEW(String_Quoted, pstate, result);
|
133
156
|
}
|
134
157
|
|
135
|
-
if (op == Sass_OP::MOD && rval == 0) {
|
136
|
-
throw Exception::ZeroDivisionError(lhs, rhs);
|
137
|
-
}
|
138
|
-
|
139
158
|
size_t l_n_units = lhs.numerators.size();
|
140
159
|
size_t l_d_units = lhs.numerators.size();
|
141
160
|
size_t r_n_units = rhs.denominators.size();
|
@@ -145,7 +164,7 @@ namespace Sass {
|
|
145
164
|
if (l_n_units + l_d_units <= 1 && r_n_units + r_d_units <= 1) {
|
146
165
|
if (lhs.numerators == rhs.numerators) {
|
147
166
|
if (lhs.denominators == rhs.denominators) {
|
148
|
-
|
167
|
+
Number* v = SASS_MEMORY_COPY(&lhs);
|
149
168
|
v->value(ops[op](lval, rval));
|
150
169
|
return v;
|
151
170
|
}
|
@@ -192,13 +211,15 @@ namespace Sass {
|
|
192
211
|
}
|
193
212
|
|
194
213
|
/* static function, throws OperationError, has no traces but optional pstate for returned value */
|
195
|
-
|
214
|
+
Value* op_number_color(enum Sass_OP op, const Number& lhs, const Color_RGBA& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
|
196
215
|
{
|
197
216
|
double lval = lhs.value();
|
217
|
+
|
198
218
|
switch (op) {
|
199
219
|
case Sass_OP::ADD:
|
200
220
|
case Sass_OP::MUL: {
|
201
|
-
|
221
|
+
op_color_deprecation(op, lhs.to_string(), rhs.to_string(opt), pstate);
|
222
|
+
return SASS_MEMORY_NEW(Color_RGBA,
|
202
223
|
pstate,
|
203
224
|
ops[op](lval, rhs.r()),
|
204
225
|
ops[op](lval, rhs.g()),
|
@@ -208,6 +229,7 @@ namespace Sass {
|
|
208
229
|
case Sass_OP::SUB:
|
209
230
|
case Sass_OP::DIV: {
|
210
231
|
std::string color(rhs.to_string(opt));
|
232
|
+
op_color_deprecation(op, lhs.to_string(), color, pstate);
|
211
233
|
return SASS_MEMORY_NEW(String_Quoted,
|
212
234
|
pstate,
|
213
235
|
lhs.to_string(opt)
|
@@ -220,14 +242,18 @@ namespace Sass {
|
|
220
242
|
}
|
221
243
|
|
222
244
|
/* static function, throws OperationError, has no traces but optional pstate for returned value */
|
223
|
-
|
245
|
+
Value* op_color_number(enum Sass_OP op, const Color_RGBA& lhs, const Number& rhs, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed)
|
224
246
|
{
|
225
247
|
double rval = rhs.value();
|
226
|
-
|
248
|
+
|
249
|
+
if ((op == Sass_OP::DIV || op == Sass_OP::DIV) && rval == 0) {
|
227
250
|
// comparison of Fixnum with Float failed?
|
228
251
|
throw Exception::ZeroDivisionError(lhs, rhs);
|
229
252
|
}
|
230
|
-
|
253
|
+
|
254
|
+
op_color_deprecation(op, lhs.to_string(), rhs.to_string(), pstate);
|
255
|
+
|
256
|
+
return SASS_MEMORY_NEW(Color_RGBA,
|
231
257
|
pstate,
|
232
258
|
ops[op](lhs.r(), rval),
|
233
259
|
ops[op](lhs.g(), rval),
|
@@ -17,11 +17,11 @@ namespace Sass {
|
|
17
17
|
bool lte(Expression_Obj, Expression_Obj);
|
18
18
|
bool gte(Expression_Obj, Expression_Obj);
|
19
19
|
// arithmetic for all the combinations that matter
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
Value* op_strings(Sass::Operand, Value&, Value&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
|
21
|
+
Value* op_colors(enum Sass_OP, const Color_RGBA&, const Color_RGBA&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
|
22
|
+
Value* op_numbers(enum Sass_OP, const Number&, const Number&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
|
23
|
+
Value* op_number_color(enum Sass_OP, const Number&, const Color_RGBA&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
|
24
|
+
Value* op_color_number(enum Sass_OP, const Color_RGBA&, const Number&, struct Sass_Inspect_Options opt, const ParserState& pstate, bool delayed = false);
|
25
25
|
|
26
26
|
};
|
27
27
|
|
data/ext/libsass/src/output.cpp
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
// sass.hpp must go before all system headers to get the
|
2
|
+
// __EXTENSIONS__ fix on Solaris.
|
1
3
|
#include "sass.hpp"
|
4
|
+
|
2
5
|
#include "ast.hpp"
|
3
6
|
#include "output.hpp"
|
7
|
+
#include "util.hpp"
|
4
8
|
|
5
9
|
namespace Sass {
|
6
10
|
|
@@ -12,12 +16,12 @@ namespace Sass {
|
|
12
16
|
|
13
17
|
Output::~Output() { }
|
14
18
|
|
15
|
-
void Output::fallback_impl(
|
19
|
+
void Output::fallback_impl(AST_Node* n)
|
16
20
|
{
|
17
21
|
return n->perform(this);
|
18
22
|
}
|
19
23
|
|
20
|
-
void Output::operator()(
|
24
|
+
void Output::operator()(Number* n)
|
21
25
|
{
|
22
26
|
// check for a valid unit here
|
23
27
|
// includes result for reporting
|
@@ -31,12 +35,12 @@ namespace Sass {
|
|
31
35
|
append_token(res, n);
|
32
36
|
}
|
33
37
|
|
34
|
-
void Output::operator()(
|
38
|
+
void Output::operator()(Import* imp)
|
35
39
|
{
|
36
40
|
top_nodes.push_back(imp);
|
37
41
|
}
|
38
42
|
|
39
|
-
void Output::operator()(
|
43
|
+
void Output::operator()(Map* m)
|
40
44
|
{
|
41
45
|
// should be handle in check_expression
|
42
46
|
throw Exception::InvalidValue({}, *m);
|
@@ -86,9 +90,8 @@ namespace Sass {
|
|
86
90
|
|
87
91
|
}
|
88
92
|
|
89
|
-
void Output::operator()(
|
93
|
+
void Output::operator()(Comment* c)
|
90
94
|
{
|
91
|
-
std::string txt = c->text()->to_string(opt);
|
92
95
|
// if (indentation && txt == "/**/") return;
|
93
96
|
bool important = c->is_important();
|
94
97
|
if (output_style() != COMPRESSED || important) {
|
@@ -108,7 +111,7 @@ namespace Sass {
|
|
108
111
|
}
|
109
112
|
}
|
110
113
|
|
111
|
-
void Output::operator()(
|
114
|
+
void Output::operator()(Ruleset* r)
|
112
115
|
{
|
113
116
|
Selector_Obj s = r->selector();
|
114
117
|
Block_Obj b = r->block();
|
@@ -142,19 +145,19 @@ namespace Sass {
|
|
142
145
|
Statement_Obj stm = b->at(i);
|
143
146
|
bool bPrintExpression = true;
|
144
147
|
// Check print conditions
|
145
|
-
if (
|
146
|
-
if (
|
148
|
+
if (Declaration* dec = Cast<Declaration>(stm)) {
|
149
|
+
if (String_Constant* valConst = Cast<String_Constant>(dec->value())) {
|
147
150
|
std::string val(valConst->value());
|
148
|
-
if (
|
151
|
+
if (String_Quoted* qstr = Cast<String_Quoted>(valConst)) {
|
149
152
|
if (!qstr->quote_mark() && val.empty()) {
|
150
153
|
bPrintExpression = false;
|
151
154
|
}
|
152
155
|
}
|
153
156
|
}
|
154
|
-
else if (
|
157
|
+
else if (List* list = Cast<List>(dec->value())) {
|
155
158
|
bool all_invisible = true;
|
156
159
|
for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) {
|
157
|
-
|
160
|
+
Expression* item = list->at(list_i);
|
158
161
|
if (!item->is_invisible()) all_invisible = false;
|
159
162
|
}
|
160
163
|
if (all_invisible && !list->is_bracketed()) bPrintExpression = false;
|
@@ -169,7 +172,7 @@ namespace Sass {
|
|
169
172
|
append_scope_closer(b);
|
170
173
|
|
171
174
|
}
|
172
|
-
void Output::operator()(
|
175
|
+
void Output::operator()(Keyframe_Rule* r)
|
173
176
|
{
|
174
177
|
Block_Obj b = r->block();
|
175
178
|
Selector_Obj v = r->name();
|
@@ -192,7 +195,7 @@ namespace Sass {
|
|
192
195
|
append_scope_closer();
|
193
196
|
}
|
194
197
|
|
195
|
-
void Output::operator()(
|
198
|
+
void Output::operator()(Supports_Block* f)
|
196
199
|
{
|
197
200
|
if (f->is_invisible()) return;
|
198
201
|
|
@@ -229,7 +232,7 @@ namespace Sass {
|
|
229
232
|
|
230
233
|
}
|
231
234
|
|
232
|
-
void Output::operator()(
|
235
|
+
void Output::operator()(Media_Block* m)
|
233
236
|
{
|
234
237
|
if (m->is_invisible()) return;
|
235
238
|
|
@@ -266,7 +269,7 @@ namespace Sass {
|
|
266
269
|
append_scope_closer();
|
267
270
|
}
|
268
271
|
|
269
|
-
void Output::operator()(
|
272
|
+
void Output::operator()(Directive* a)
|
270
273
|
{
|
271
274
|
std::string kwd = a->keyword();
|
272
275
|
Selector_Obj s = a->selector();
|
@@ -309,7 +312,7 @@ namespace Sass {
|
|
309
312
|
append_scope_closer();
|
310
313
|
}
|
311
314
|
|
312
|
-
void Output::operator()(
|
315
|
+
void Output::operator()(String_Quoted* s)
|
313
316
|
{
|
314
317
|
if (s->quote_mark()) {
|
315
318
|
append_token(quote(s->value(), s->quote_mark()), s);
|
@@ -320,7 +323,7 @@ namespace Sass {
|
|
320
323
|
}
|
321
324
|
}
|
322
325
|
|
323
|
-
void Output::operator()(
|
326
|
+
void Output::operator()(String_Constant* s)
|
324
327
|
{
|
325
328
|
std::string value(s->value());
|
326
329
|
if (s->can_compress_whitespace() && output_style() == COMPRESSED) {
|
data/ext/libsass/src/output.hpp
CHANGED
@@ -11,13 +11,6 @@
|
|
11
11
|
namespace Sass {
|
12
12
|
class Context;
|
13
13
|
|
14
|
-
// Refactor to make it generic to find linefeed (look behind)
|
15
|
-
inline bool ends_with(std::string const & value, std::string const & ending)
|
16
|
-
{
|
17
|
-
if (ending.size() > value.size()) return false;
|
18
|
-
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
19
|
-
}
|
20
|
-
|
21
14
|
class Output : public Inspect {
|
22
15
|
protected:
|
23
16
|
using Inspect::operator();
|
@@ -28,24 +21,24 @@ namespace Sass {
|
|
28
21
|
|
29
22
|
protected:
|
30
23
|
std::string charset;
|
31
|
-
std::vector<
|
24
|
+
std::vector<AST_Node*> top_nodes;
|
32
25
|
|
33
26
|
public:
|
34
27
|
OutputBuffer get_buffer(void);
|
35
28
|
|
36
|
-
virtual void operator()(
|
37
|
-
virtual void operator()(
|
38
|
-
virtual void operator()(
|
39
|
-
virtual void operator()(
|
40
|
-
virtual void operator()(
|
41
|
-
virtual void operator()(
|
42
|
-
virtual void operator()(
|
43
|
-
virtual void operator()(
|
44
|
-
virtual void operator()(
|
45
|
-
virtual void operator()(
|
46
|
-
virtual void operator()(
|
47
|
-
|
48
|
-
void fallback_impl(
|
29
|
+
virtual void operator()(Map*);
|
30
|
+
virtual void operator()(Ruleset*);
|
31
|
+
virtual void operator()(Supports_Block*);
|
32
|
+
virtual void operator()(Media_Block*);
|
33
|
+
virtual void operator()(Directive*);
|
34
|
+
virtual void operator()(Keyframe_Rule*);
|
35
|
+
virtual void operator()(Import*);
|
36
|
+
virtual void operator()(Comment*);
|
37
|
+
virtual void operator()(Number*);
|
38
|
+
virtual void operator()(String_Quoted*);
|
39
|
+
virtual void operator()(String_Constant*);
|
40
|
+
|
41
|
+
void fallback_impl(AST_Node* n);
|
49
42
|
|
50
43
|
};
|
51
44
|
|
data/ext/libsass/src/parser.cpp
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
// sass.hpp must go before all system headers to get the
|
2
|
+
// __EXTENSIONS__ fix on Solaris.
|
1
3
|
#include "sass.hpp"
|
4
|
+
|
2
5
|
#include "parser.hpp"
|
3
6
|
#include "file.hpp"
|
4
7
|
#include "inspect.hpp"
|
@@ -8,6 +11,7 @@
|
|
8
11
|
#include "color_maps.hpp"
|
9
12
|
#include "sass/functions.h"
|
10
13
|
#include "error_handling.hpp"
|
14
|
+
#include "util_string.hpp"
|
11
15
|
|
12
16
|
// Notes about delayed: some ast nodes can have delayed evaluation so
|
13
17
|
// they can preserve their original semantics if needed. This is most
|
@@ -30,11 +34,11 @@ namespace Sass {
|
|
30
34
|
using namespace Constants;
|
31
35
|
using namespace Prelexer;
|
32
36
|
|
33
|
-
Parser Parser::from_c_str(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
|
37
|
+
Parser Parser::from_c_str(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
|
34
38
|
{
|
35
39
|
pstate.offset.column = 0;
|
36
40
|
pstate.offset.line = 0;
|
37
|
-
Parser p(ctx, pstate, traces);
|
41
|
+
Parser p(ctx, pstate, traces, allow_parent);
|
38
42
|
p.source = source ? source : beg;
|
39
43
|
p.position = beg ? beg : p.source;
|
40
44
|
p.end = p.position + strlen(p.position);
|
@@ -44,11 +48,11 @@ namespace Sass {
|
|
44
48
|
return p;
|
45
49
|
}
|
46
50
|
|
47
|
-
Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
|
51
|
+
Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
|
48
52
|
{
|
49
53
|
pstate.offset.column = 0;
|
50
54
|
pstate.offset.line = 0;
|
51
|
-
Parser p(ctx, pstate, traces);
|
55
|
+
Parser p(ctx, pstate, traces, allow_parent);
|
52
56
|
p.source = source ? source : beg;
|
53
57
|
p.position = beg ? beg : p.source;
|
54
58
|
p.end = end ? end : p.position + strlen(p.position);
|
@@ -66,10 +70,9 @@ namespace Sass {
|
|
66
70
|
pstate.offset.line = 0;
|
67
71
|
}
|
68
72
|
|
69
|
-
Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
|
73
|
+
Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
|
70
74
|
{
|
71
|
-
Parser p = Parser::from_c_str(beg, ctx, traces, pstate, source);
|
72
|
-
// ToDo: ruby sass errors on parent references
|
75
|
+
Parser p = Parser::from_c_str(beg, ctx, traces, pstate, source, allow_parent);
|
73
76
|
// ToDo: remap the source-map entries somehow
|
74
77
|
return p.parse_selector_list(false);
|
75
78
|
}
|
@@ -333,11 +336,11 @@ namespace Sass {
|
|
333
336
|
do {
|
334
337
|
while (lex< block_comment >());
|
335
338
|
if (lex< quoted_string >()) {
|
336
|
-
to_import.push_back(std::pair<std::string,Function_Call_Obj>(std::string(lexed),
|
339
|
+
to_import.push_back(std::pair<std::string,Function_Call_Obj>(std::string(lexed), {}));
|
337
340
|
}
|
338
341
|
else if (lex< uri_prefix >()) {
|
339
342
|
Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
|
340
|
-
Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, "url", args);
|
343
|
+
Function_Call_Obj result = SASS_MEMORY_NEW(Function_Call, pstate, std::string("url"), args);
|
341
344
|
|
342
345
|
if (lex< quoted_string >()) {
|
343
346
|
Expression_Obj quoted_url = parse_string();
|
@@ -479,7 +482,7 @@ namespace Sass {
|
|
479
482
|
bool is_arglist = false;
|
480
483
|
bool is_keyword = false;
|
481
484
|
Expression_Obj val = parse_space_list();
|
482
|
-
|
485
|
+
List* l = Cast<List>(val);
|
483
486
|
if (lex_css< exactly< ellipsis > >()) {
|
484
487
|
if (val->concrete_type() == Expression::MAP || (
|
485
488
|
(l != NULL && l->separator() == SASS_HASH)
|
@@ -556,7 +559,7 @@ namespace Sass {
|
|
556
559
|
lex< optional_spaces >();
|
557
560
|
const char* i = position;
|
558
561
|
// selector schema re-uses string schema implementation
|
559
|
-
|
562
|
+
String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
560
563
|
// the selector schema is pretty much just a wrapper for the string schema
|
561
564
|
Selector_Schema_Obj selector_schema = SASS_MEMORY_NEW(Selector_Schema, pstate, schema);
|
562
565
|
selector_schema->connect_parent(chroot == false);
|
@@ -645,13 +648,27 @@ namespace Sass {
|
|
645
648
|
// normalize underscores to hyphens
|
646
649
|
std::string name(Util::normalize_underscores(lexed));
|
647
650
|
// create the initial mixin call object
|
648
|
-
Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name,
|
651
|
+
Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call, pstate, name, {}, {}, {});
|
649
652
|
// parse mandatory arguments
|
650
653
|
call->arguments(parse_arguments());
|
654
|
+
// parse using and optional block parameters
|
655
|
+
bool has_parameters = lex< kwd_using >() != nullptr;
|
656
|
+
|
657
|
+
if (has_parameters) {
|
658
|
+
if (!peek< exactly<'('> >()) css_error("Invalid CSS", " after ", ": expected \"(\", was ");
|
659
|
+
} else {
|
660
|
+
if (peek< exactly<'('> >()) css_error("Invalid CSS", " after ", ": expected \";\", was ");
|
661
|
+
}
|
662
|
+
|
663
|
+
if (has_parameters) call->block_parameters(parse_parameters());
|
664
|
+
|
651
665
|
// parse optional block
|
652
666
|
if (peek < exactly <'{'> >()) {
|
653
667
|
call->block(parse_block());
|
654
668
|
}
|
669
|
+
else if (has_parameters) {
|
670
|
+
css_error("Invalid CSS", " after ", ": expected \"{\", was ");
|
671
|
+
}
|
655
672
|
// return ast node
|
656
673
|
return call.detach();
|
657
674
|
}
|
@@ -706,7 +723,7 @@ namespace Sass {
|
|
706
723
|
}
|
707
724
|
// update for end position
|
708
725
|
group->update_pstate(pstate);
|
709
|
-
if (sel) sel->
|
726
|
+
if (sel) sel->mutable_last()->has_line_break(false);
|
710
727
|
return group.detach();
|
711
728
|
}
|
712
729
|
// EO parse_selector_list
|
@@ -719,12 +736,12 @@ namespace Sass {
|
|
719
736
|
{
|
720
737
|
|
721
738
|
NESTING_GUARD(nestings);
|
722
|
-
String_Obj reference
|
739
|
+
String_Obj reference;
|
723
740
|
lex < block_comment >();
|
724
741
|
advanceToNextToken();
|
725
742
|
Complex_Selector_Obj sel = SASS_MEMORY_NEW(Complex_Selector, pstate);
|
726
743
|
|
727
|
-
if (peek < end_of_file >()) return
|
744
|
+
if (peek < end_of_file >()) return {};
|
728
745
|
|
729
746
|
// parse the left hand side
|
730
747
|
Compound_Selector_Obj lhs;
|
@@ -743,12 +760,12 @@ namespace Sass {
|
|
743
760
|
else if (lex< sequence < exactly<'/'>, negate < exactly < '*' > > > >()) {
|
744
761
|
// comments are allowed, but not spaces?
|
745
762
|
combinator = Complex_Selector::REFERENCE;
|
746
|
-
if (!lex < re_reference_combinator >()) return
|
763
|
+
if (!lex < re_reference_combinator >()) return {};
|
747
764
|
reference = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
748
|
-
if (!lex < exactly < '/' > >()) return
|
765
|
+
if (!lex < exactly < '/' > >()) return {}; // ToDo: error msg?
|
749
766
|
}
|
750
767
|
|
751
|
-
if (!lhs && combinator == Complex_Selector::ANCESTOR_OF) return
|
768
|
+
if (!lhs && combinator == Complex_Selector::ANCESTOR_OF) return {};
|
752
769
|
|
753
770
|
// lex < block_comment >();
|
754
771
|
sel->head(lhs);
|
@@ -771,7 +788,7 @@ namespace Sass {
|
|
771
788
|
if (!sel->has_parent_ref() && !chroot) {
|
772
789
|
// create the objects to wrap parent selector reference
|
773
790
|
Compound_Selector_Obj head = SASS_MEMORY_NEW(Compound_Selector, pstate);
|
774
|
-
|
791
|
+
Parent_Selector* parent = SASS_MEMORY_NEW(Parent_Selector, pstate, false);
|
775
792
|
parent->media_block(last_media_block);
|
776
793
|
head->media_block(last_media_block);
|
777
794
|
// add simple selector
|
@@ -818,6 +835,7 @@ namespace Sass {
|
|
818
835
|
// parse parent selector
|
819
836
|
else if (lex< exactly<'&'> >(false))
|
820
837
|
{
|
838
|
+
if (!allow_parent) error("Parent selectors aren't allowed here.");
|
821
839
|
// this produces a linefeed!?
|
822
840
|
seq->has_parent_reference(true);
|
823
841
|
seq->append(SASS_MEMORY_NEW(Parent_Selector, pstate));
|
@@ -837,7 +855,7 @@ namespace Sass {
|
|
837
855
|
// parse type selector
|
838
856
|
else if (lex< re_type_selector >(false))
|
839
857
|
{
|
840
|
-
seq->append(SASS_MEMORY_NEW(
|
858
|
+
seq->append(SASS_MEMORY_NEW(Type_Selector, pstate, lexed));
|
841
859
|
}
|
842
860
|
// peek for abort conditions
|
843
861
|
else if (peek< spaces >()) break;
|
@@ -847,7 +865,7 @@ namespace Sass {
|
|
847
865
|
// otherwise parse another simple selector
|
848
866
|
else {
|
849
867
|
Simple_Selector_Obj sel = parse_simple_selector();
|
850
|
-
if (!sel) return
|
868
|
+
if (!sel) return {};
|
851
869
|
seq->append(sel);
|
852
870
|
}
|
853
871
|
}
|
@@ -872,7 +890,7 @@ namespace Sass {
|
|
872
890
|
return SASS_MEMORY_NEW(Id_Selector, pstate, lexed);
|
873
891
|
}
|
874
892
|
else if (lex< alternatives < variable, number, static_reference_combinator > >()) {
|
875
|
-
return SASS_MEMORY_NEW(
|
893
|
+
return SASS_MEMORY_NEW(Type_Selector, pstate, lexed);
|
876
894
|
}
|
877
895
|
else if (peek< pseudo_not >()) {
|
878
896
|
return parse_negated_selector();
|
@@ -887,7 +905,7 @@ namespace Sass {
|
|
887
905
|
return parse_attribute_selector();
|
888
906
|
}
|
889
907
|
else if (lex< placeholder >()) {
|
890
|
-
|
908
|
+
Placeholder_Selector* sel = SASS_MEMORY_NEW(Placeholder_Selector, pstate, lexed);
|
891
909
|
sel->media_block(last_media_block);
|
892
910
|
return sel;
|
893
911
|
}
|
@@ -895,7 +913,7 @@ namespace Sass {
|
|
895
913
|
css_error("Invalid CSS", " after ", ": expected selector, was ");
|
896
914
|
}
|
897
915
|
// failed
|
898
|
-
return
|
916
|
+
return {};
|
899
917
|
}
|
900
918
|
|
901
919
|
Wrapped_Selector_Obj Parser::parse_negated_selector()
|
@@ -915,7 +933,7 @@ namespace Sass {
|
|
915
933
|
// it can contain more selectors inside parentheses
|
916
934
|
Simple_Selector_Obj Parser::parse_pseudo_selector() {
|
917
935
|
if (lex< sequence<
|
918
|
-
|
936
|
+
pseudo_prefix,
|
919
937
|
// we keep the space within the name, strange enough
|
920
938
|
// ToDo: refactor output to schedule the space for it
|
921
939
|
// or do we really want to keep the real white-space?
|
@@ -966,7 +984,7 @@ namespace Sass {
|
|
966
984
|
css_error("Invalid CSS", " after ", ": expected \")\", was ");
|
967
985
|
|
968
986
|
// unreachable statement
|
969
|
-
return
|
987
|
+
return {};
|
970
988
|
}
|
971
989
|
|
972
990
|
const char* Parser::re_attr_sensitive_close(const char* src)
|
@@ -985,11 +1003,11 @@ namespace Sass {
|
|
985
1003
|
if (!lex_css< attribute_name >()) error("invalid attribute name in attribute selector");
|
986
1004
|
std::string name(lexed);
|
987
1005
|
if (lex_css< re_attr_sensitive_close >()) {
|
988
|
-
return SASS_MEMORY_NEW(Attribute_Selector, p, name, "",
|
1006
|
+
return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", {}, {});
|
989
1007
|
}
|
990
1008
|
else if (lex_css< re_attr_insensitive_close >()) {
|
991
1009
|
char modifier = lexed.begin[0];
|
992
|
-
return SASS_MEMORY_NEW(Attribute_Selector, p, name, "",
|
1010
|
+
return SASS_MEMORY_NEW(Attribute_Selector, p, name, "", {}, modifier);
|
993
1011
|
}
|
994
1012
|
if (!lex_css< alternatives< exact_match, class_match, dash_match,
|
995
1013
|
prefix_match, suffix_match, substring_match > >()) {
|
@@ -997,7 +1015,7 @@ namespace Sass {
|
|
997
1015
|
}
|
998
1016
|
std::string matcher(lexed);
|
999
1017
|
|
1000
|
-
String_Obj value
|
1018
|
+
String_Obj value;
|
1001
1019
|
if (lex_css< identifier >()) {
|
1002
1020
|
value = SASS_MEMORY_NEW(String_Constant, p, lexed);
|
1003
1021
|
}
|
@@ -1016,7 +1034,7 @@ namespace Sass {
|
|
1016
1034
|
return SASS_MEMORY_NEW(Attribute_Selector, p, name, matcher, value, modifier);
|
1017
1035
|
}
|
1018
1036
|
error("unterminated attribute selector for " + name);
|
1019
|
-
return
|
1037
|
+
return {}; // to satisfy compilers (error must not return)
|
1020
1038
|
}
|
1021
1039
|
|
1022
1040
|
/* parse block comment and add to block */
|
@@ -1072,7 +1090,7 @@ namespace Sass {
|
|
1072
1090
|
}
|
1073
1091
|
else {
|
1074
1092
|
value = parse_list(DELAYED);
|
1075
|
-
if (
|
1093
|
+
if (List* list = Cast<List>(value)) {
|
1076
1094
|
if (!list->is_bracketed() && list->length() == 0 && !peek< exactly <'{'> >()) {
|
1077
1095
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
1078
1096
|
}
|
@@ -1478,7 +1496,7 @@ namespace Sass {
|
|
1478
1496
|
}
|
1479
1497
|
else if (lex< identifier_schema >()) {
|
1480
1498
|
String_Obj string = parse_identifier_schema();
|
1481
|
-
if (
|
1499
|
+
if (String_Schema* schema = Cast<String_Schema>(string)) {
|
1482
1500
|
if (lex < exactly < '(' > >()) {
|
1483
1501
|
schema->append(parse_list());
|
1484
1502
|
lex < exactly < ')' > >();
|
@@ -1493,29 +1511,29 @@ namespace Sass {
|
|
1493
1511
|
return parse_function_call();
|
1494
1512
|
}
|
1495
1513
|
else if (lex< exactly<'+'> >()) {
|
1496
|
-
|
1514
|
+
Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::PLUS, parse_factor());
|
1497
1515
|
if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
|
1498
1516
|
return ex;
|
1499
1517
|
}
|
1500
1518
|
else if (lex< exactly<'-'> >()) {
|
1501
|
-
|
1519
|
+
Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_factor());
|
1502
1520
|
if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
|
1503
1521
|
return ex;
|
1504
1522
|
}
|
1505
1523
|
else if (lex< exactly<'/'> >()) {
|
1506
|
-
|
1524
|
+
Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::SLASH, parse_factor());
|
1507
1525
|
if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
|
1508
1526
|
return ex;
|
1509
1527
|
}
|
1510
1528
|
else if (lex< sequence< kwd_not > >()) {
|
1511
|
-
|
1529
|
+
Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::NOT, parse_factor());
|
1512
1530
|
if (ex && ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
|
1513
1531
|
return ex;
|
1514
1532
|
}
|
1515
1533
|
// this whole branch is never hit via spec tests
|
1516
1534
|
else if (peek < sequence < one_plus < alternatives < css_whitespace, exactly<'-'>, exactly<'+'> > >, number > >()) {
|
1517
1535
|
if (parse_number_prefix()) return parse_value(); // prefix is positive
|
1518
|
-
|
1536
|
+
Unary_Expression* ex = SASS_MEMORY_NEW(Unary_Expression, pstate, Unary_Expression::MINUS, parse_value());
|
1519
1537
|
if (ex->operand()) ex->is_delayed(ex->operand()->is_delayed());
|
1520
1538
|
return ex;
|
1521
1539
|
}
|
@@ -1533,9 +1551,9 @@ namespace Sass {
|
|
1533
1551
|
(L > 2 && parsed.substr(0, 3) == "-0.") );
|
1534
1552
|
}
|
1535
1553
|
|
1536
|
-
|
1554
|
+
Number* Parser::lexed_number(const ParserState& pstate, const std::string& parsed)
|
1537
1555
|
{
|
1538
|
-
|
1556
|
+
Number* nr = SASS_MEMORY_NEW(Number,
|
1539
1557
|
pstate,
|
1540
1558
|
sass_strtod(parsed.c_str()),
|
1541
1559
|
"",
|
@@ -1545,9 +1563,9 @@ namespace Sass {
|
|
1545
1563
|
return nr;
|
1546
1564
|
}
|
1547
1565
|
|
1548
|
-
|
1566
|
+
Number* Parser::lexed_percentage(const ParserState& pstate, const std::string& parsed)
|
1549
1567
|
{
|
1550
|
-
|
1568
|
+
Number* nr = SASS_MEMORY_NEW(Number,
|
1551
1569
|
pstate,
|
1552
1570
|
sass_strtod(parsed.c_str()),
|
1553
1571
|
"%",
|
@@ -1557,7 +1575,7 @@ namespace Sass {
|
|
1557
1575
|
return nr;
|
1558
1576
|
}
|
1559
1577
|
|
1560
|
-
|
1578
|
+
Number* Parser::lexed_dimension(const ParserState& pstate, const std::string& parsed)
|
1561
1579
|
{
|
1562
1580
|
size_t L = parsed.length();
|
1563
1581
|
size_t num_pos = parsed.find_first_not_of(" \n\r\t");
|
@@ -1568,7 +1586,7 @@ namespace Sass {
|
|
1568
1586
|
}
|
1569
1587
|
if (unit_pos == std::string::npos) unit_pos = L;
|
1570
1588
|
const std::string& num = parsed.substr(num_pos, unit_pos - num_pos);
|
1571
|
-
|
1589
|
+
Number* nr = SASS_MEMORY_NEW(Number,
|
1572
1590
|
pstate,
|
1573
1591
|
sass_strtod(num.c_str()),
|
1574
1592
|
Token(number(parsed.c_str())),
|
@@ -1578,9 +1596,9 @@ namespace Sass {
|
|
1578
1596
|
return nr;
|
1579
1597
|
}
|
1580
1598
|
|
1581
|
-
|
1599
|
+
Value* Parser::lexed_hex_color(const ParserState& pstate, const std::string& parsed)
|
1582
1600
|
{
|
1583
|
-
|
1601
|
+
Color_RGBA* color = NULL;
|
1584
1602
|
if (parsed[0] != '#') {
|
1585
1603
|
return SASS_MEMORY_NEW(String_Quoted, pstate, parsed);
|
1586
1604
|
}
|
@@ -1590,7 +1608,7 @@ namespace Sass {
|
|
1590
1608
|
std::string r(2, parsed[1]);
|
1591
1609
|
std::string g(2, parsed[2]);
|
1592
1610
|
std::string b(2, parsed[3]);
|
1593
|
-
color = SASS_MEMORY_NEW(
|
1611
|
+
color = SASS_MEMORY_NEW(Color_RGBA,
|
1594
1612
|
pstate,
|
1595
1613
|
static_cast<double>(strtol(r.c_str(), NULL, 16)),
|
1596
1614
|
static_cast<double>(strtol(g.c_str(), NULL, 16)),
|
@@ -1598,11 +1616,24 @@ namespace Sass {
|
|
1598
1616
|
1, // alpha channel
|
1599
1617
|
parsed);
|
1600
1618
|
}
|
1619
|
+
else if (parsed.length() == 5) {
|
1620
|
+
std::string r(2, parsed[1]);
|
1621
|
+
std::string g(2, parsed[2]);
|
1622
|
+
std::string b(2, parsed[3]);
|
1623
|
+
std::string a(2, parsed[4]);
|
1624
|
+
color = SASS_MEMORY_NEW(Color_RGBA,
|
1625
|
+
pstate,
|
1626
|
+
static_cast<double>(strtol(r.c_str(), NULL, 16)),
|
1627
|
+
static_cast<double>(strtol(g.c_str(), NULL, 16)),
|
1628
|
+
static_cast<double>(strtol(b.c_str(), NULL, 16)),
|
1629
|
+
static_cast<double>(strtol(a.c_str(), NULL, 16)) / 255,
|
1630
|
+
parsed);
|
1631
|
+
}
|
1601
1632
|
else if (parsed.length() == 7) {
|
1602
1633
|
std::string r(parsed.substr(1,2));
|
1603
1634
|
std::string g(parsed.substr(3,2));
|
1604
1635
|
std::string b(parsed.substr(5,2));
|
1605
|
-
color = SASS_MEMORY_NEW(
|
1636
|
+
color = SASS_MEMORY_NEW(Color_RGBA,
|
1606
1637
|
pstate,
|
1607
1638
|
static_cast<double>(strtol(r.c_str(), NULL, 16)),
|
1608
1639
|
static_cast<double>(strtol(g.c_str(), NULL, 16)),
|
@@ -1615,7 +1646,7 @@ namespace Sass {
|
|
1615
1646
|
std::string g(parsed.substr(3,2));
|
1616
1647
|
std::string b(parsed.substr(5,2));
|
1617
1648
|
std::string a(parsed.substr(7,2));
|
1618
|
-
color = SASS_MEMORY_NEW(
|
1649
|
+
color = SASS_MEMORY_NEW(Color_RGBA,
|
1619
1650
|
pstate,
|
1620
1651
|
static_cast<double>(strtol(r.c_str(), NULL, 16)),
|
1621
1652
|
static_cast<double>(strtol(g.c_str(), NULL, 16)),
|
@@ -1628,6 +1659,19 @@ namespace Sass {
|
|
1628
1659
|
return color;
|
1629
1660
|
}
|
1630
1661
|
|
1662
|
+
Value* Parser::color_or_string(const std::string& lexed) const
|
1663
|
+
{
|
1664
|
+
if (auto color = name_to_color(lexed)) {
|
1665
|
+
auto c = SASS_MEMORY_NEW(Color_RGBA, color);
|
1666
|
+
c->is_delayed(true);
|
1667
|
+
c->pstate(pstate);
|
1668
|
+
c->disp(lexed);
|
1669
|
+
return c;
|
1670
|
+
} else {
|
1671
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
1672
|
+
}
|
1673
|
+
}
|
1674
|
+
|
1631
1675
|
// parse one value for a list
|
1632
1676
|
Expression_Obj Parser::parse_value()
|
1633
1677
|
{
|
@@ -1637,7 +1681,7 @@ namespace Sass {
|
|
1637
1681
|
if (match< ampersand >()) {
|
1638
1682
|
warning("In Sass, \"&&\" means two copies of the parent selector. You probably want to use \"and\" instead.", pstate);
|
1639
1683
|
}
|
1640
|
-
return SASS_MEMORY_NEW(
|
1684
|
+
return SASS_MEMORY_NEW(Parent_Reference, pstate); }
|
1641
1685
|
|
1642
1686
|
if (lex< kwd_important >())
|
1643
1687
|
{ return SASS_MEMORY_NEW(String_Constant, pstate, "!important"); }
|
@@ -1670,7 +1714,7 @@ namespace Sass {
|
|
1670
1714
|
{ return SASS_MEMORY_NEW(Null, pstate); }
|
1671
1715
|
|
1672
1716
|
if (lex< identifier >()) {
|
1673
|
-
return
|
1717
|
+
return color_or_string(lexed);
|
1674
1718
|
}
|
1675
1719
|
|
1676
1720
|
if (lex< percentage >())
|
@@ -1681,17 +1725,7 @@ namespace Sass {
|
|
1681
1725
|
{ return lexed_hex_color(lexed); }
|
1682
1726
|
|
1683
1727
|
if (lex< hexa >())
|
1684
|
-
{
|
1685
|
-
std::string s = lexed.to_string();
|
1686
|
-
|
1687
|
-
deprecated(
|
1688
|
-
"The value \""+s+"\" is currently parsed as a string, but it will be parsed as a color in",
|
1689
|
-
"future versions of Sass. Use \"unquote('"+s+"')\" to continue parsing it as a string.",
|
1690
|
-
true, pstate
|
1691
|
-
);
|
1692
|
-
|
1693
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, lexed);
|
1694
|
-
}
|
1728
|
+
{ return lexed_hex_color(lexed); }
|
1695
1729
|
|
1696
1730
|
if (lex< sequence < exactly <'#'>, identifier > >())
|
1697
1731
|
{ return SASS_MEMORY_NEW(String_Quoted, pstate, lexed); }
|
@@ -1710,14 +1744,10 @@ namespace Sass {
|
|
1710
1744
|
if (lex< variable >())
|
1711
1745
|
{ return SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed)); }
|
1712
1746
|
|
1713
|
-
// Special case handling for `%` proceeding an interpolant.
|
1714
|
-
if (lex< sequence< exactly<'%'>, optional< percentage > > >())
|
1715
|
-
{ return SASS_MEMORY_NEW(String_Constant, pstate, lexed); }
|
1716
|
-
|
1717
1747
|
css_error("Invalid CSS", " after ", ": expected expression (e.g. 1px, bold), was ");
|
1718
1748
|
|
1719
1749
|
// unreachable statement
|
1720
|
-
return
|
1750
|
+
return {};
|
1721
1751
|
}
|
1722
1752
|
|
1723
1753
|
// this parses interpolation inside other strings
|
@@ -1730,7 +1760,7 @@ namespace Sass {
|
|
1730
1760
|
find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, chunk.end);
|
1731
1761
|
|
1732
1762
|
if (!p) {
|
1733
|
-
|
1763
|
+
String_Quoted* str_quoted = SASS_MEMORY_NEW(String_Quoted, pstate, std::string(i, chunk.end), 0, false, false, true, css);
|
1734
1764
|
if (!constant && str_quoted->quote_mark()) str_quoted->quote_mark('*');
|
1735
1765
|
return str_quoted;
|
1736
1766
|
}
|
@@ -1774,74 +1804,66 @@ namespace Sass {
|
|
1774
1804
|
return schema.detach();
|
1775
1805
|
}
|
1776
1806
|
|
1777
|
-
String_Schema_Obj Parser::parse_css_variable_value(
|
1807
|
+
String_Schema_Obj Parser::parse_css_variable_value()
|
1778
1808
|
{
|
1779
1809
|
String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
{
|
1795
|
-
String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
1796
|
-
if (
|
1797
|
-
(top_level && lex< css_variable_top_level_value >(false)) ||
|
1798
|
-
(!top_level && lex< css_variable_value >(false))
|
1799
|
-
) {
|
1800
|
-
Token str(lexed);
|
1801
|
-
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, str));
|
1802
|
-
}
|
1803
|
-
else if (Expression_Obj tok = lex_interpolation()) {
|
1804
|
-
if (String_Schema_Ptr s = Cast<String_Schema>(tok)) {
|
1805
|
-
schema->concat(s);
|
1806
|
-
} else {
|
1807
|
-
schema->append(tok);
|
1808
|
-
}
|
1809
|
-
}
|
1810
|
-
else if (lex< quoted_string >()) {
|
1811
|
-
Expression_Obj tok = parse_string();
|
1812
|
-
if (String_Schema_Ptr s = Cast<String_Schema>(tok)) {
|
1813
|
-
schema->concat(s);
|
1814
|
-
} else {
|
1815
|
-
schema->append(tok);
|
1816
|
-
}
|
1817
|
-
}
|
1818
|
-
else {
|
1819
|
-
if (peek< alternatives< exactly<'('>, exactly<'['>, exactly<'{'> > >()) {
|
1820
|
-
if (lex< exactly<'('> >()) {
|
1821
|
-
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string("(")));
|
1822
|
-
if (String_Schema_Obj tok = parse_css_variable_value(false)) schema->concat(tok);
|
1823
|
-
if (!lex< exactly<')'> >()) css_error("Invalid CSS", " after ", ": expected \")\", was ");
|
1824
|
-
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(")")));
|
1810
|
+
std::vector<char> brackets;
|
1811
|
+
while (true) {
|
1812
|
+
if (
|
1813
|
+
(brackets.empty() && lex< css_variable_top_level_value >(false)) ||
|
1814
|
+
(!brackets.empty() && lex< css_variable_value >(false))
|
1815
|
+
) {
|
1816
|
+
Token str(lexed);
|
1817
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, str));
|
1818
|
+
} else if (Expression_Obj tok = lex_interpolation()) {
|
1819
|
+
if (String_Schema* s = Cast<String_Schema>(tok)) {
|
1820
|
+
if (s->empty()) break;
|
1821
|
+
schema->concat(s);
|
1822
|
+
} else {
|
1823
|
+
schema->append(tok);
|
1825
1824
|
}
|
1826
|
-
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1825
|
+
} else if (lex< quoted_string >()) {
|
1826
|
+
Expression_Obj tok = parse_string();
|
1827
|
+
if (tok.isNull()) break;
|
1828
|
+
if (String_Schema* s = Cast<String_Schema>(tok)) {
|
1829
|
+
if (s->empty()) break;
|
1830
|
+
schema->concat(s);
|
1831
|
+
} else {
|
1832
|
+
schema->append(tok);
|
1831
1833
|
}
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
|
1834
|
+
} else if (lex< alternatives< exactly<'('>, exactly<'['>, exactly<'{'> > >()) {
|
1835
|
+
const char opening_bracket = *(position - 1);
|
1836
|
+
brackets.push_back(opening_bracket);
|
1837
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(1, opening_bracket)));
|
1838
|
+
} else if (const char *match = peek< alternatives< exactly<')'>, exactly<']'>, exactly<'}'> > >()) {
|
1839
|
+
if (brackets.empty()) break;
|
1840
|
+
const char closing_bracket = *(match - 1);
|
1841
|
+
if (brackets.back() != Util::opening_bracket_for(closing_bracket)) {
|
1842
|
+
std::string message = ": expected \"";
|
1843
|
+
message += Util::closing_bracket_for(brackets.back());
|
1844
|
+
message += "\", was ";
|
1845
|
+
css_error("Invalid CSS", " after ", message);
|
1837
1846
|
}
|
1847
|
+
lex< alternatives< exactly<')'>, exactly<']'>, exactly<'}'> > >();
|
1848
|
+
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, std::string(1, closing_bracket)));
|
1849
|
+
brackets.pop_back();
|
1850
|
+
} else {
|
1851
|
+
break;
|
1838
1852
|
}
|
1839
1853
|
}
|
1840
1854
|
|
1841
|
-
|
1855
|
+
if (!brackets.empty()) {
|
1856
|
+
std::string message = ": expected \"";
|
1857
|
+
message += Util::closing_bracket_for(brackets.back());
|
1858
|
+
message += "\", was ";
|
1859
|
+
css_error("Invalid CSS", " after ", message);
|
1860
|
+
}
|
1861
|
+
|
1862
|
+
if (schema->empty()) error("Custom property values may not be empty.");
|
1863
|
+
return schema.detach();
|
1842
1864
|
}
|
1843
1865
|
|
1844
|
-
|
1866
|
+
Value_Obj Parser::parse_static_value()
|
1845
1867
|
{
|
1846
1868
|
lex< static_value >();
|
1847
1869
|
Token str(lexed);
|
@@ -1852,8 +1874,7 @@ namespace Sass {
|
|
1852
1874
|
--str.end;
|
1853
1875
|
--position;
|
1854
1876
|
|
1855
|
-
|
1856
|
-
return str_node;
|
1877
|
+
return color_or_string(str.time_wspace());;
|
1857
1878
|
}
|
1858
1879
|
|
1859
1880
|
String_Obj Parser::parse_string()
|
@@ -1872,7 +1893,7 @@ namespace Sass {
|
|
1872
1893
|
return SASS_MEMORY_NEW(String_Quoted, pstate, std::string(str.begin, str.end));
|
1873
1894
|
}
|
1874
1895
|
|
1875
|
-
|
1896
|
+
String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
1876
1897
|
while (i < str.end) {
|
1877
1898
|
p = find_first_in_interval< exactly<hash_lbrace>, block_comment >(i, str.end);
|
1878
1899
|
if (p) {
|
@@ -1907,7 +1928,7 @@ namespace Sass {
|
|
1907
1928
|
|
1908
1929
|
String_Obj Parser::parse_ie_keyword_arg()
|
1909
1930
|
{
|
1910
|
-
|
1931
|
+
String_Schema_Obj kwd_arg = SASS_MEMORY_NEW(String_Schema, pstate, 3);
|
1911
1932
|
if (lex< variable >()) {
|
1912
1933
|
kwd_arg->append(SASS_MEMORY_NEW(Variable, pstate, Util::normalize_underscores(lexed)));
|
1913
1934
|
} else {
|
@@ -1962,7 +1983,7 @@ namespace Sass {
|
|
1962
1983
|
if (lex< re_static_expression >()) {
|
1963
1984
|
ex = SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
1964
1985
|
} else {
|
1965
|
-
ex = parse_list();
|
1986
|
+
ex = parse_list(true);
|
1966
1987
|
}
|
1967
1988
|
ex->is_interpolant(true);
|
1968
1989
|
schema->append(ex);
|
@@ -1986,7 +2007,7 @@ namespace Sass {
|
|
1986
2007
|
}
|
1987
2008
|
if (peek < exactly < '-' > >()) break;
|
1988
2009
|
}
|
1989
|
-
else if (lex<
|
2010
|
+
else if (lex< identifier >()) {
|
1990
2011
|
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
|
1991
2012
|
if ((*position == '"' || *position == '\'') || peek < alternatives < alpha > >()) {
|
1992
2013
|
// need_space = true;
|
@@ -2128,7 +2149,7 @@ namespace Sass {
|
|
2128
2149
|
uri = url_string->to_string({ NESTED, 5 });
|
2129
2150
|
}
|
2130
2151
|
|
2131
|
-
if (
|
2152
|
+
if (String_Schema* schema = Cast<String_Schema>(url_string)) {
|
2132
2153
|
String_Schema_Obj res = SASS_MEMORY_NEW(String_Schema, pstate);
|
2133
2154
|
res->append(SASS_MEMORY_NEW(String_Constant, pstate, prefix));
|
2134
2155
|
res->append(schema);
|
@@ -2155,6 +2176,7 @@ namespace Sass {
|
|
2155
2176
|
while (pp && peek< exactly< hash_lbrace > >(pp)) {
|
2156
2177
|
pp = sequence< interpolant, real_uri_value >(pp);
|
2157
2178
|
}
|
2179
|
+
if (!pp) return {};
|
2158
2180
|
position = pp;
|
2159
2181
|
return parse_interpolated_chunk(Token(p, position));
|
2160
2182
|
}
|
@@ -2163,7 +2185,7 @@ namespace Sass {
|
|
2163
2185
|
return SASS_MEMORY_NEW(String_Constant, pstate, res);
|
2164
2186
|
}
|
2165
2187
|
|
2166
|
-
return
|
2188
|
+
return {};
|
2167
2189
|
}
|
2168
2190
|
|
2169
2191
|
Function_Call_Obj Parser::parse_function_call()
|
@@ -2179,18 +2201,21 @@ namespace Sass {
|
|
2179
2201
|
return SASS_MEMORY_NEW(Function_Call, call_pos, name, args);
|
2180
2202
|
}
|
2181
2203
|
|
2182
|
-
|
2204
|
+
Function_Call_Obj Parser::parse_function_call_schema()
|
2183
2205
|
{
|
2184
2206
|
String_Obj name = parse_identifier_schema();
|
2185
2207
|
ParserState source_position_of_call = pstate;
|
2186
2208
|
Arguments_Obj args = parse_arguments();
|
2187
2209
|
|
2188
|
-
return SASS_MEMORY_NEW(
|
2210
|
+
return SASS_MEMORY_NEW(Function_Call, source_position_of_call, name, args);
|
2189
2211
|
}
|
2190
2212
|
|
2191
2213
|
Content_Obj Parser::parse_content_directive()
|
2192
2214
|
{
|
2193
|
-
|
2215
|
+
ParserState call_pos = pstate;
|
2216
|
+
Arguments_Obj args = parse_arguments();
|
2217
|
+
|
2218
|
+
return SASS_MEMORY_NEW(Content, call_pos, args);
|
2194
2219
|
}
|
2195
2220
|
|
2196
2221
|
If_Obj Parser::parse_if_directive(bool else_if)
|
@@ -2200,7 +2225,7 @@ namespace Sass {
|
|
2200
2225
|
bool root = block_stack.back()->is_root();
|
2201
2226
|
Expression_Obj predicate = parse_list();
|
2202
2227
|
Block_Obj block = parse_block(root);
|
2203
|
-
Block_Obj alternative
|
2228
|
+
Block_Obj alternative;
|
2204
2229
|
|
2205
2230
|
// only throw away comment if we parse a case
|
2206
2231
|
// we want all other comments to be parsed
|
@@ -2285,7 +2310,7 @@ namespace Sass {
|
|
2285
2310
|
stack.push_back(Scope::Control);
|
2286
2311
|
bool root = block_stack.back()->is_root();
|
2287
2312
|
// create the initial while call object
|
2288
|
-
While_Obj call = SASS_MEMORY_NEW(While, pstate,
|
2313
|
+
While_Obj call = SASS_MEMORY_NEW(While, pstate, {}, {});
|
2289
2314
|
// parse mandatory predicate
|
2290
2315
|
Expression_Obj predicate = parse_list();
|
2291
2316
|
List_Obj l = Cast<List>(predicate);
|
@@ -2305,7 +2330,7 @@ namespace Sass {
|
|
2305
2330
|
Media_Block_Obj Parser::parse_media_block()
|
2306
2331
|
{
|
2307
2332
|
stack.push_back(Scope::Media);
|
2308
|
-
Media_Block_Obj media_block = SASS_MEMORY_NEW(Media_Block, pstate,
|
2333
|
+
Media_Block_Obj media_block = SASS_MEMORY_NEW(Media_Block, pstate, {}, {});
|
2309
2334
|
|
2310
2335
|
media_block->media_queries(parse_media_queries());
|
2311
2336
|
|
@@ -2327,7 +2352,7 @@ namespace Sass {
|
|
2327
2352
|
return queries.detach();
|
2328
2353
|
}
|
2329
2354
|
|
2330
|
-
//
|
2355
|
+
// Expression* Parser::parse_media_query()
|
2331
2356
|
Media_Query_Obj Parser::parse_media_query()
|
2332
2357
|
{
|
2333
2358
|
advanceToNextToken();
|
@@ -2341,7 +2366,7 @@ namespace Sass {
|
|
2341
2366
|
|
2342
2367
|
while (lex_css < kwd_and >()) media_query->append(parse_media_expression());
|
2343
2368
|
if (lex < identifier_schema >()) {
|
2344
|
-
|
2369
|
+
String_Schema* schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
2345
2370
|
schema->append(media_query->media_type());
|
2346
2371
|
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, " "));
|
2347
2372
|
schema->append(parse_identifier_schema());
|
@@ -2358,7 +2383,7 @@ namespace Sass {
|
|
2358
2383
|
{
|
2359
2384
|
if (lex < identifier_schema >()) {
|
2360
2385
|
String_Obj ss = parse_identifier_schema();
|
2361
|
-
return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss,
|
2386
|
+
return SASS_MEMORY_NEW(Media_Query_Expression, pstate, ss, {}, true);
|
2362
2387
|
}
|
2363
2388
|
if (!lex_css< exactly<'('> >()) {
|
2364
2389
|
error("media query expression must begin with '('");
|
@@ -2368,7 +2393,7 @@ namespace Sass {
|
|
2368
2393
|
error("media feature required in media query expression");
|
2369
2394
|
}
|
2370
2395
|
feature = parse_expression();
|
2371
|
-
Expression_Obj expression
|
2396
|
+
Expression_Obj expression;
|
2372
2397
|
if (lex_css< exactly<':'> >()) {
|
2373
2398
|
expression = parse_list(DELAYED);
|
2374
2399
|
}
|
@@ -2382,10 +2407,7 @@ namespace Sass {
|
|
2382
2407
|
// these are very similar to media blocks
|
2383
2408
|
Supports_Block_Obj Parser::parse_supports_directive()
|
2384
2409
|
{
|
2385
|
-
Supports_Condition_Obj cond = parse_supports_condition();
|
2386
|
-
if (!cond) {
|
2387
|
-
css_error("Invalid CSS", " after ", ": expected @supports condition (e.g. (display: flexbox)), was ", false);
|
2388
|
-
}
|
2410
|
+
Supports_Condition_Obj cond = parse_supports_condition(/*top_level=*/true);
|
2389
2411
|
// create the ast node object for the support queries
|
2390
2412
|
Supports_Block_Obj query = SASS_MEMORY_NEW(Supports_Block, pstate, cond);
|
2391
2413
|
// additional block is mandatory
|
@@ -2397,27 +2419,27 @@ namespace Sass {
|
|
2397
2419
|
|
2398
2420
|
// parse one query operation
|
2399
2421
|
// may encounter nested queries
|
2400
|
-
Supports_Condition_Obj Parser::parse_supports_condition()
|
2422
|
+
Supports_Condition_Obj Parser::parse_supports_condition(bool top_level)
|
2401
2423
|
{
|
2402
2424
|
lex < css_whitespace >();
|
2403
2425
|
Supports_Condition_Obj cond;
|
2404
2426
|
if ((cond = parse_supports_negation())) return cond;
|
2405
|
-
if ((cond = parse_supports_operator())) return cond;
|
2427
|
+
if ((cond = parse_supports_operator(top_level))) return cond;
|
2406
2428
|
if ((cond = parse_supports_interpolation())) return cond;
|
2407
2429
|
return cond;
|
2408
2430
|
}
|
2409
2431
|
|
2410
2432
|
Supports_Condition_Obj Parser::parse_supports_negation()
|
2411
2433
|
{
|
2412
|
-
if (!lex < kwd_not >()) return
|
2413
|
-
Supports_Condition_Obj cond = parse_supports_condition_in_parens();
|
2434
|
+
if (!lex < kwd_not >()) return {};
|
2435
|
+
Supports_Condition_Obj cond = parse_supports_condition_in_parens(/*parens_required=*/true);
|
2414
2436
|
return SASS_MEMORY_NEW(Supports_Negation, pstate, cond);
|
2415
2437
|
}
|
2416
2438
|
|
2417
|
-
Supports_Condition_Obj Parser::parse_supports_operator()
|
2439
|
+
Supports_Condition_Obj Parser::parse_supports_operator(bool top_level)
|
2418
2440
|
{
|
2419
|
-
Supports_Condition_Obj cond = parse_supports_condition_in_parens();
|
2420
|
-
if (cond.isNull()) return
|
2441
|
+
Supports_Condition_Obj cond = parse_supports_condition_in_parens(/*parens_required=*/top_level);
|
2442
|
+
if (cond.isNull()) return {};
|
2421
2443
|
|
2422
2444
|
while (true) {
|
2423
2445
|
Supports_Operator::Operand op = Supports_Operator::OR;
|
@@ -2425,9 +2447,9 @@ namespace Sass {
|
|
2425
2447
|
else if(!lex < kwd_or >()) { break; }
|
2426
2448
|
|
2427
2449
|
lex < css_whitespace >();
|
2428
|
-
Supports_Condition_Obj right = parse_supports_condition_in_parens();
|
2450
|
+
Supports_Condition_Obj right = parse_supports_condition_in_parens(/*parens_required=*/true);
|
2429
2451
|
|
2430
|
-
//
|
2452
|
+
// Supports_Condition* cc = SASS_MEMORY_NEW(Supports_Condition, *static_cast<Supports_Condition*>(cond));
|
2431
2453
|
cond = SASS_MEMORY_NEW(Supports_Operator, pstate, cond, right, op);
|
2432
2454
|
}
|
2433
2455
|
return cond;
|
@@ -2435,10 +2457,10 @@ namespace Sass {
|
|
2435
2457
|
|
2436
2458
|
Supports_Condition_Obj Parser::parse_supports_interpolation()
|
2437
2459
|
{
|
2438
|
-
if (!lex < interpolant >()) return
|
2460
|
+
if (!lex < interpolant >()) return {};
|
2439
2461
|
|
2440
2462
|
String_Obj interp = parse_interpolated_chunk(lexed);
|
2441
|
-
if (!interp) return
|
2463
|
+
if (!interp) return {};
|
2442
2464
|
|
2443
2465
|
return SASS_MEMORY_NEW(Supports_Interpolation, pstate, interp);
|
2444
2466
|
}
|
@@ -2447,10 +2469,10 @@ namespace Sass {
|
|
2447
2469
|
// look like declarations their semantics differ significantly
|
2448
2470
|
Supports_Condition_Obj Parser::parse_supports_declaration()
|
2449
2471
|
{
|
2450
|
-
|
2472
|
+
Supports_Condition* cond;
|
2451
2473
|
// parse something declaration like
|
2452
2474
|
Expression_Obj feature = parse_expression();
|
2453
|
-
Expression_Obj expression
|
2475
|
+
Expression_Obj expression;
|
2454
2476
|
if (lex_css< exactly<':'> >()) {
|
2455
2477
|
expression = parse_list(DELAYED);
|
2456
2478
|
}
|
@@ -2463,21 +2485,24 @@ namespace Sass {
|
|
2463
2485
|
return cond;
|
2464
2486
|
}
|
2465
2487
|
|
2466
|
-
Supports_Condition_Obj Parser::parse_supports_condition_in_parens()
|
2488
|
+
Supports_Condition_Obj Parser::parse_supports_condition_in_parens(bool parens_required)
|
2467
2489
|
{
|
2468
2490
|
Supports_Condition_Obj interp = parse_supports_interpolation();
|
2469
2491
|
if (interp != 0) return interp;
|
2470
2492
|
|
2471
|
-
if (!lex < exactly <'('> >())
|
2493
|
+
if (!lex < exactly <'('> >()) {
|
2494
|
+
if (parens_required) {
|
2495
|
+
css_error("Invalid CSS", " after ", ": expected @supports condition (e.g. (display: flexbox)), was ", /*trim=*/false);
|
2496
|
+
} else {
|
2497
|
+
return {};
|
2498
|
+
}
|
2499
|
+
}
|
2472
2500
|
lex < css_whitespace >();
|
2473
2501
|
|
2474
|
-
Supports_Condition_Obj cond = parse_supports_condition();
|
2475
|
-
if (cond
|
2476
|
-
|
2477
|
-
|
2478
|
-
cond = parse_supports_declaration();
|
2479
|
-
if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration");
|
2480
|
-
}
|
2502
|
+
Supports_Condition_Obj cond = parse_supports_condition(/*top_level=*/false);
|
2503
|
+
if (cond.isNull()) cond = parse_supports_declaration();
|
2504
|
+
if (!lex < exactly <')'> >()) error("unclosed parenthesis in @supports declaration");
|
2505
|
+
|
2481
2506
|
lex < css_whitespace >();
|
2482
2507
|
return cond;
|
2483
2508
|
}
|
@@ -2486,7 +2511,7 @@ namespace Sass {
|
|
2486
2511
|
{
|
2487
2512
|
stack.push_back(Scope::AtRoot);
|
2488
2513
|
ParserState at_source_position = pstate;
|
2489
|
-
Block_Obj body
|
2514
|
+
Block_Obj body;
|
2490
2515
|
At_Root_Query_Obj expr;
|
2491
2516
|
Lookahead lookahead_result;
|
2492
2517
|
if (lex_css< exactly<'('> >()) {
|
@@ -2541,7 +2566,7 @@ namespace Sass {
|
|
2541
2566
|
|
2542
2567
|
// this whole branch is never hit via spec tests
|
2543
2568
|
|
2544
|
-
|
2569
|
+
Directive* at_rule = SASS_MEMORY_NEW(Directive, pstate, kwd);
|
2545
2570
|
Lookahead lookahead = lookahead_for_include(position);
|
2546
2571
|
if (lookahead.found && !lookahead.has_interpolants) {
|
2547
2572
|
at_rule->selector(parse_selector_list(false));
|
@@ -2612,7 +2637,7 @@ namespace Sass {
|
|
2612
2637
|
if (lex < interpolant >(true) != NULL) {
|
2613
2638
|
return parse_interpolated_chunk(lexed, true);
|
2614
2639
|
}
|
2615
|
-
return
|
2640
|
+
return {};
|
2616
2641
|
}
|
2617
2642
|
|
2618
2643
|
Expression_Obj Parser::lex_interp_uri()
|
@@ -2678,30 +2703,32 @@ namespace Sass {
|
|
2678
2703
|
if (match) {
|
2679
2704
|
return SASS_MEMORY_NEW(String_Constant, pstate, lexed);
|
2680
2705
|
}
|
2681
|
-
return
|
2706
|
+
return {};
|
2682
2707
|
}
|
2683
2708
|
|
2684
2709
|
Expression_Obj Parser::lex_almost_any_value_token()
|
2685
2710
|
{
|
2686
2711
|
Expression_Obj rv;
|
2687
|
-
if (*position == 0) return
|
2712
|
+
if (*position == 0) return {};
|
2688
2713
|
if ((rv = lex_almost_any_value_chars())) return rv;
|
2689
2714
|
// if ((rv = lex_block_comment())) return rv;
|
2690
2715
|
// if ((rv = lex_single_line_comment())) return rv;
|
2691
2716
|
if ((rv = lex_interp_string())) return rv;
|
2692
2717
|
if ((rv = lex_interp_uri())) return rv;
|
2693
2718
|
if ((rv = lex_interpolation())) return rv;
|
2694
|
-
|
2719
|
+
if (lex< alternatives< hex, hex0 > >())
|
2720
|
+
{ return lexed_hex_color(lexed); }
|
2721
|
+
return rv;
|
2695
2722
|
}
|
2696
2723
|
|
2697
2724
|
String_Schema_Obj Parser::parse_almost_any_value()
|
2698
2725
|
{
|
2699
2726
|
|
2700
2727
|
String_Schema_Obj schema = SASS_MEMORY_NEW(String_Schema, pstate);
|
2701
|
-
if (*position == 0) return
|
2728
|
+
if (*position == 0) return {};
|
2702
2729
|
lex < spaces >(false);
|
2703
2730
|
Expression_Obj token = lex_almost_any_value_token();
|
2704
|
-
if (!token) return
|
2731
|
+
if (!token) return {};
|
2705
2732
|
schema->append(token);
|
2706
2733
|
if (*position == 0) {
|
2707
2734
|
schema->rtrim();
|
@@ -2777,6 +2804,7 @@ namespace Sass {
|
|
2777
2804
|
>(p)
|
2778
2805
|
) {
|
2779
2806
|
bool could_be_property = peek< sequence< exactly<'-'>, exactly<'-'> > >(p) != 0;
|
2807
|
+
bool could_be_escaped = false;
|
2780
2808
|
while (p < q) {
|
2781
2809
|
// did we have interpolations?
|
2782
2810
|
if (*p == '#' && *(p+1) == '{') {
|
@@ -2785,9 +2813,10 @@ namespace Sass {
|
|
2785
2813
|
}
|
2786
2814
|
// A property that's ambiguous with a nested selector is interpreted as a
|
2787
2815
|
// custom property.
|
2788
|
-
if (*p == ':') {
|
2816
|
+
if (*p == ':' && !could_be_escaped) {
|
2789
2817
|
rv.is_custom_property = could_be_property || p+1 == q || peek< space >(p+1);
|
2790
2818
|
}
|
2819
|
+
could_be_escaped = *p == '\\';
|
2791
2820
|
++ p;
|
2792
2821
|
}
|
2793
2822
|
// store anyway }
|
@@ -2981,7 +3010,7 @@ namespace Sass {
|
|
2981
3010
|
|
2982
3011
|
Expression_Obj Parser::fold_operands(Expression_Obj base, std::vector<Expression_Obj>& operands, std::vector<Operand>& ops, size_t i)
|
2983
3012
|
{
|
2984
|
-
if (
|
3013
|
+
if (String_Schema* schema = Cast<String_Schema>(base)) {
|
2985
3014
|
// return schema;
|
2986
3015
|
if (schema->has_interpolants()) {
|
2987
3016
|
if (i + 1 < operands.size() && (
|
@@ -3004,7 +3033,7 @@ namespace Sass {
|
|
3004
3033
|
}
|
3005
3034
|
|
3006
3035
|
for (size_t S = operands.size(); i < S; ++i) {
|
3007
|
-
if (
|
3036
|
+
if (String_Schema* schema = Cast<String_Schema>(operands[i])) {
|
3008
3037
|
if (schema->has_interpolants()) {
|
3009
3038
|
if (i + 1 < S) {
|
3010
3039
|
// this whole branch is never hit via spec tests
|
@@ -3021,13 +3050,13 @@ namespace Sass {
|
|
3021
3050
|
} else {
|
3022
3051
|
base = SASS_MEMORY_NEW(Binary_Expression, base->pstate(), ops[i], base, operands[i]);
|
3023
3052
|
}
|
3024
|
-
|
3053
|
+
Binary_Expression* b = Cast<Binary_Expression>(base.ptr());
|
3025
3054
|
if (b && ops[i].operand == Sass_OP::DIV && b->left()->is_delayed() && b->right()->is_delayed()) {
|
3026
3055
|
base->is_delayed(true);
|
3027
3056
|
}
|
3028
3057
|
}
|
3029
3058
|
// nested binary expression are never to be delayed
|
3030
|
-
if (
|
3059
|
+
if (Binary_Expression* b = Cast<Binary_Expression>(base)) {
|
3031
3060
|
if (Cast<Binary_Expression>(b->left())) base->set_delayed(false);
|
3032
3061
|
if (Cast<Binary_Expression>(b->right())) base->set_delayed(false);
|
3033
3062
|
}
|
@@ -3038,8 +3067,11 @@ namespace Sass {
|
|
3038
3067
|
{
|
3039
3068
|
Position p(pos.line ? pos : before_token);
|
3040
3069
|
ParserState pstate(path, source, p, Offset(0, 0));
|
3070
|
+
// `pstate.src` may not outlive stack unwind so we must copy it.
|
3071
|
+
char *src_copy = sass_copy_c_string(pstate.src);
|
3072
|
+
pstate.src = src_copy;
|
3041
3073
|
traces.push_back(Backtrace(pstate));
|
3042
|
-
throw Exception::InvalidSass(pstate, traces, msg);
|
3074
|
+
throw Exception::InvalidSass(pstate, traces, msg, src_copy);
|
3043
3075
|
}
|
3044
3076
|
|
3045
3077
|
void Parser::error(std::string msg)
|