sassc 2.2.1 → 2.3.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/.travis.yml +1 -0
- data/CHANGELOG.md +13 -0
- data/Rakefile +1 -3
- data/ext/extconf.rb +13 -5
- data/ext/libsass/VERSION +1 -1
- data/ext/libsass/include/sass/base.h +2 -1
- data/ext/libsass/include/sass/context.h +1 -0
- data/ext/libsass/src/ast.cpp +49 -59
- data/ext/libsass/src/ast.hpp +263 -102
- data/ext/libsass/src/ast_def_macros.hpp +8 -0
- data/ext/libsass/src/ast_fwd_decl.cpp +2 -1
- data/ext/libsass/src/ast_fwd_decl.hpp +40 -116
- data/ext/libsass/src/ast_helpers.hpp +292 -0
- data/ext/libsass/src/ast_sel_cmp.cpp +209 -722
- data/ext/libsass/src/ast_sel_super.cpp +539 -0
- data/ext/libsass/src/ast_sel_unify.cpp +207 -212
- data/ext/libsass/src/ast_sel_weave.cpp +616 -0
- data/ext/libsass/src/ast_selectors.cpp +559 -1001
- data/ext/libsass/src/ast_selectors.hpp +311 -367
- data/ext/libsass/src/ast_supports.cpp +1 -17
- data/ext/libsass/src/ast_values.cpp +216 -29
- data/ext/libsass/src/ast_values.hpp +42 -33
- data/ext/libsass/src/bind.cpp +1 -1
- data/ext/libsass/src/cencode.c +4 -6
- data/ext/libsass/src/check_nesting.cpp +5 -6
- data/ext/libsass/src/check_nesting.hpp +4 -0
- data/ext/libsass/src/color_maps.cpp +11 -10
- data/ext/libsass/src/color_maps.hpp +0 -8
- data/ext/libsass/src/constants.cpp +5 -0
- data/ext/libsass/src/constants.hpp +6 -0
- data/ext/libsass/src/context.cpp +30 -60
- data/ext/libsass/src/context.hpp +8 -20
- data/ext/libsass/src/cssize.cpp +36 -120
- data/ext/libsass/src/cssize.hpp +4 -10
- data/ext/libsass/src/dart_helpers.hpp +199 -0
- data/ext/libsass/src/debugger.hpp +364 -207
- data/ext/libsass/src/emitter.cpp +3 -4
- data/ext/libsass/src/emitter.hpp +0 -2
- data/ext/libsass/src/environment.hpp +5 -0
- data/ext/libsass/src/error_handling.cpp +21 -0
- data/ext/libsass/src/error_handling.hpp +25 -3
- data/ext/libsass/src/eval.cpp +33 -153
- data/ext/libsass/src/eval.hpp +11 -13
- data/ext/libsass/src/eval_selectors.cpp +75 -0
- data/ext/libsass/src/expand.cpp +214 -167
- data/ext/libsass/src/expand.hpp +26 -6
- data/ext/libsass/src/extender.cpp +1186 -0
- data/ext/libsass/src/extender.hpp +399 -0
- data/ext/libsass/src/extension.cpp +43 -0
- data/ext/libsass/src/extension.hpp +89 -0
- data/ext/libsass/src/file.cpp +15 -14
- data/ext/libsass/src/file.hpp +5 -12
- data/ext/libsass/src/fn_colors.cpp +12 -10
- data/ext/libsass/src/fn_lists.cpp +12 -11
- data/ext/libsass/src/fn_miscs.cpp +22 -34
- data/ext/libsass/src/fn_numbers.cpp +13 -6
- data/ext/libsass/src/fn_selectors.cpp +94 -124
- data/ext/libsass/src/fn_strings.cpp +16 -14
- data/ext/libsass/src/fn_utils.cpp +5 -6
- data/ext/libsass/src/fn_utils.hpp +9 -3
- data/ext/libsass/src/inspect.cpp +154 -117
- data/ext/libsass/src/inspect.hpp +10 -8
- data/ext/libsass/src/lexer.cpp +17 -81
- data/ext/libsass/src/lexer.hpp +5 -16
- data/ext/libsass/src/listize.cpp +22 -36
- data/ext/libsass/src/listize.hpp +8 -9
- data/ext/libsass/src/memory/SharedPtr.hpp +39 -5
- data/ext/libsass/src/operation.hpp +27 -17
- data/ext/libsass/src/operators.cpp +1 -0
- data/ext/libsass/src/ordered_map.hpp +112 -0
- data/ext/libsass/src/output.cpp +30 -49
- data/ext/libsass/src/output.hpp +1 -1
- data/ext/libsass/src/parser.cpp +211 -381
- data/ext/libsass/src/parser.hpp +17 -15
- data/ext/libsass/src/parser_selectors.cpp +189 -0
- data/ext/libsass/src/permutate.hpp +140 -0
- data/ext/libsass/src/position.hpp +1 -1
- data/ext/libsass/src/prelexer.cpp +6 -6
- data/ext/libsass/src/remove_placeholders.cpp +55 -56
- data/ext/libsass/src/remove_placeholders.hpp +21 -18
- data/ext/libsass/src/sass.hpp +1 -0
- data/ext/libsass/src/sass2scss.cpp +4 -4
- data/ext/libsass/src/sass_context.cpp +42 -91
- data/ext/libsass/src/sass_context.hpp +2 -2
- data/ext/libsass/src/sass_functions.cpp +1 -1
- data/ext/libsass/src/sass_values.cpp +0 -1
- data/ext/libsass/src/stylesheet.cpp +22 -0
- data/ext/libsass/src/stylesheet.hpp +57 -0
- data/ext/libsass/src/to_value.cpp +2 -2
- data/ext/libsass/src/to_value.hpp +1 -1
- data/ext/libsass/src/units.cpp +5 -3
- data/ext/libsass/src/util.cpp +10 -12
- data/ext/libsass/src/util.hpp +2 -3
- data/ext/libsass/src/util_string.cpp +111 -61
- data/ext/libsass/src/util_string.hpp +61 -8
- data/lib/sassc/engine.rb +5 -3
- data/lib/sassc/functions_handler.rb +8 -8
- data/lib/sassc/native.rb +1 -1
- data/lib/sassc/script.rb +4 -4
- data/lib/sassc/version.rb +1 -1
- data/test/functions_test.rb +18 -1
- data/test/native_test.rb +1 -1
- metadata +17 -12
- data/ext/libsass/src/extend.cpp +0 -2132
- data/ext/libsass/src/extend.hpp +0 -86
- data/ext/libsass/src/node.cpp +0 -322
- data/ext/libsass/src/node.hpp +0 -118
- data/ext/libsass/src/paths.hpp +0 -71
- data/ext/libsass/src/sass_util.cpp +0 -152
- data/ext/libsass/src/sass_util.hpp +0 -256
- data/ext/libsass/src/subset_map.cpp +0 -58
- data/ext/libsass/src/subset_map.hpp +0 -76
data/ext/libsass/src/file.cpp
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
#else
|
|
14
14
|
# include <unistd.h>
|
|
15
15
|
#endif
|
|
16
|
-
#include <cctype>
|
|
17
16
|
#include <cstdio>
|
|
18
17
|
#include <vector>
|
|
19
18
|
#include <algorithm>
|
|
@@ -25,6 +24,7 @@
|
|
|
25
24
|
#include "sass_functions.hpp"
|
|
26
25
|
#include "error_handling.hpp"
|
|
27
26
|
#include "util.hpp"
|
|
27
|
+
#include "util_string.hpp"
|
|
28
28
|
#include "sass2scss.h"
|
|
29
29
|
|
|
30
30
|
#ifdef _WIN32
|
|
@@ -106,19 +106,19 @@ namespace Sass {
|
|
|
106
106
|
bool is_absolute_path(const std::string& path)
|
|
107
107
|
{
|
|
108
108
|
#ifdef _WIN32
|
|
109
|
-
if (path.length() >= 2 &&
|
|
109
|
+
if (path.length() >= 2 && Util::ascii_isalpha(path[0]) && path[1] == ':') return true;
|
|
110
110
|
#endif
|
|
111
111
|
size_t i = 0;
|
|
112
112
|
// check if we have a protocol
|
|
113
|
-
if (path[i] &&
|
|
113
|
+
if (path[i] && Util::ascii_isalpha(static_cast<unsigned char>(path[i]))) {
|
|
114
114
|
// skip over all alphanumeric characters
|
|
115
|
-
while (path[i] &&
|
|
115
|
+
while (path[i] && Util::ascii_isalnum(static_cast<unsigned char>(path[i]))) ++i;
|
|
116
116
|
i = i && path[i] == ':' ? i + 1 : 0;
|
|
117
117
|
}
|
|
118
118
|
return path[i] == '/';
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
// helper function to find the last directory
|
|
121
|
+
// helper function to find the last directory separator
|
|
122
122
|
inline size_t find_last_folder_separator(const std::string& path, size_t limit = std::string::npos)
|
|
123
123
|
{
|
|
124
124
|
size_t pos;
|
|
@@ -173,15 +173,15 @@ namespace Sass {
|
|
|
173
173
|
while((pos = path.find("/./", pos)) != std::string::npos) path.erase(pos, 2);
|
|
174
174
|
|
|
175
175
|
// remove all leading and trailing self references
|
|
176
|
-
while(path.
|
|
177
|
-
while((pos = path.length()) > 1 && path
|
|
176
|
+
while(path.size() >= 2 && path[0] == '.' && path[1] == '/') path.erase(0, 2);
|
|
177
|
+
while((pos = path.length()) > 1 && path[pos - 2] == '/' && path[pos - 1] == '.') path.erase(pos - 2);
|
|
178
178
|
|
|
179
179
|
|
|
180
180
|
size_t proto = 0;
|
|
181
181
|
// check if we have a protocol
|
|
182
|
-
if (path[proto] &&
|
|
182
|
+
if (path[proto] && Util::ascii_isalpha(static_cast<unsigned char>(path[proto]))) {
|
|
183
183
|
// skip over all alphanumeric characters
|
|
184
|
-
while (path[proto] &&
|
|
184
|
+
while (path[proto] && Util::ascii_isalnum(static_cast<unsigned char>(path[proto++]))) {}
|
|
185
185
|
// then skip over the mandatory colon
|
|
186
186
|
if (proto && path[proto] == ':') ++ proto;
|
|
187
187
|
}
|
|
@@ -260,9 +260,9 @@ namespace Sass {
|
|
|
260
260
|
|
|
261
261
|
size_t proto = 0;
|
|
262
262
|
// check if we have a protocol
|
|
263
|
-
if (path[proto] &&
|
|
263
|
+
if (path[proto] && Util::ascii_isalpha(static_cast<unsigned char>(path[proto]))) {
|
|
264
264
|
// skip over all alphanumeric characters
|
|
265
|
-
while (path[proto] &&
|
|
265
|
+
while (path[proto] && Util::ascii_isalnum(static_cast<unsigned char>(path[proto++]))) {}
|
|
266
266
|
// then skip over the mandatory colon
|
|
267
267
|
if (proto && path[proto] == ':') ++ proto;
|
|
268
268
|
}
|
|
@@ -288,7 +288,8 @@ namespace Sass {
|
|
|
288
288
|
#else
|
|
289
289
|
// compare the charactes in a case insensitive manner
|
|
290
290
|
// windows fs is only case insensitive in ascii ranges
|
|
291
|
-
if (
|
|
291
|
+
if (Util::ascii_tolower(static_cast<unsigned char>(abs_path[i])) !=
|
|
292
|
+
Util::ascii_tolower(static_cast<unsigned char>(abs_base[i]))) break;
|
|
292
293
|
#endif
|
|
293
294
|
if (abs_path[i] == '/') index = i + 1;
|
|
294
295
|
}
|
|
@@ -474,6 +475,7 @@ namespace Sass {
|
|
|
474
475
|
char* contents = static_cast<char*>(malloc(st.st_size + 2 * sizeof(char)));
|
|
475
476
|
if (std::fread(static_cast<void*>(contents), 1, size, fd) != size) {
|
|
476
477
|
free(contents);
|
|
478
|
+
std::fclose(fd);
|
|
477
479
|
return nullptr;
|
|
478
480
|
}
|
|
479
481
|
if (std::fclose(fd) != 0) {
|
|
@@ -487,8 +489,7 @@ namespace Sass {
|
|
|
487
489
|
if (path.length() > 5) {
|
|
488
490
|
extension = path.substr(path.length() - 5, 5);
|
|
489
491
|
}
|
|
490
|
-
|
|
491
|
-
extension[i] = tolower(extension[i]);
|
|
492
|
+
Util::ascii_str_tolower(&extension);
|
|
492
493
|
if (extension == ".sass" && contents != 0) {
|
|
493
494
|
char * converted = sass2scss(contents, SASS2SCSS_PRETTIFY_1 | SASS2SCSS_KEEP_COMMENT);
|
|
494
495
|
free(contents); // free the indented contents
|
data/ext/libsass/src/file.hpp
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
#ifndef SASS_FILE_H
|
|
2
2
|
#define SASS_FILE_H
|
|
3
3
|
|
|
4
|
+
// sass.hpp must go before all system headers to get the
|
|
5
|
+
// __EXTENSIONS__ fix on Solaris.
|
|
6
|
+
#include "sass.hpp"
|
|
7
|
+
|
|
4
8
|
#include <string>
|
|
5
9
|
#include <vector>
|
|
6
10
|
|
|
@@ -100,7 +104,7 @@ namespace Sass {
|
|
|
100
104
|
public:
|
|
101
105
|
// the file contents
|
|
102
106
|
char* contents;
|
|
103
|
-
//
|
|
107
|
+
// connected sourcemap
|
|
104
108
|
char* srcmap;
|
|
105
109
|
public:
|
|
106
110
|
Resource(char* contents, char* srcmap)
|
|
@@ -108,17 +112,6 @@ namespace Sass {
|
|
|
108
112
|
{ }
|
|
109
113
|
};
|
|
110
114
|
|
|
111
|
-
// parsed stylesheet from loaded resource
|
|
112
|
-
class StyleSheet : public Resource {
|
|
113
|
-
public:
|
|
114
|
-
// parsed root block
|
|
115
|
-
Block_Obj root;
|
|
116
|
-
public:
|
|
117
|
-
StyleSheet(const Resource& res, Block_Obj root)
|
|
118
|
-
: Resource(res), root(root)
|
|
119
|
-
{ }
|
|
120
|
-
};
|
|
121
|
-
|
|
122
115
|
namespace File {
|
|
123
116
|
|
|
124
117
|
static std::vector<std::string> defaultExtensions = { ".scss", ".sass", ".css" };
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// __EXTENSIONS__ fix on Solaris.
|
|
3
3
|
#include "sass.hpp"
|
|
4
4
|
|
|
5
|
-
#include <cctype>
|
|
6
5
|
#include <iomanip>
|
|
7
6
|
#include "ast.hpp"
|
|
8
7
|
#include "fn_utils.hpp"
|
|
9
8
|
#include "fn_colors.hpp"
|
|
10
9
|
#include "util.hpp"
|
|
10
|
+
#include "util_string.hpp"
|
|
11
11
|
|
|
12
12
|
namespace Sass {
|
|
13
13
|
|
|
@@ -163,11 +163,11 @@ namespace Sass {
|
|
|
163
163
|
c1->a()*p + c2->a()*(1-p));
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
Signature mix_sig = "mix($
|
|
166
|
+
Signature mix_sig = "mix($color1, $color2, $weight: 50%)";
|
|
167
167
|
BUILT_IN(mix)
|
|
168
168
|
{
|
|
169
|
-
Color_Obj color1 = ARG("$
|
|
170
|
-
Color_Obj color2 = ARG("$
|
|
169
|
+
Color_Obj color1 = ARG("$color1", Color);
|
|
170
|
+
Color_Obj color2 = ARG("$color2", Color);
|
|
171
171
|
double weight = DARG_U_PRCT("$weight");
|
|
172
172
|
return colormix(ctx, pstate, color1, color2, weight);
|
|
173
173
|
|
|
@@ -361,12 +361,16 @@ namespace Sass {
|
|
|
361
361
|
{
|
|
362
362
|
// CSS3 filter function overload: pass literal through directly
|
|
363
363
|
Number* amount = Cast<Number>(env["$color"]);
|
|
364
|
+
double weight = DARG_U_PRCT("$weight");
|
|
364
365
|
if (amount) {
|
|
366
|
+
// TODO: does not throw on 100% manually passed as value
|
|
367
|
+
if (weight < 100.0) {
|
|
368
|
+
error("Only one argument may be passed to the plain-CSS invert() function.", pstate, traces);
|
|
369
|
+
}
|
|
365
370
|
return SASS_MEMORY_NEW(String_Quoted, pstate, "invert(" + amount->to_string(ctx.c_options) + ")");
|
|
366
371
|
}
|
|
367
372
|
|
|
368
373
|
Color* col = ARG("$color", Color);
|
|
369
|
-
double weight = DARG_U_PRCT("$weight");
|
|
370
374
|
Color_RGBA_Obj inv = col->copyAsRGBA();
|
|
371
375
|
inv->r(clip(255.0 - inv->r(), 0.0, 255.0));
|
|
372
376
|
inv->g(clip(255.0 - inv->g(), 0.0, 255.0));
|
|
@@ -504,7 +508,7 @@ namespace Sass {
|
|
|
504
508
|
double lscale = (l ? DARG_R_PRCT("$lightness") : 0.0) / 100.0;
|
|
505
509
|
double ascale = (a ? DARG_R_PRCT("$alpha") : 0.0) / 100.0;
|
|
506
510
|
if (hscale) c->h(c->h() + hscale * (hscale > 0.0 ? 360.0 - c->h() : c->h()));
|
|
507
|
-
if (sscale) c->s(c->s() + sscale * (sscale > 0.0 ? 100.0 - c->
|
|
511
|
+
if (sscale) c->s(c->s() + sscale * (sscale > 0.0 ? 100.0 - c->s() : c->s()));
|
|
508
512
|
if (lscale) c->l(c->l() + lscale * (lscale > 0.0 ? 100.0 - c->l() : c->l()));
|
|
509
513
|
if (ascale) c->a(c->a() + ascale * (ascale > 0.0 ? 1.0 - c->a() : c->a()));
|
|
510
514
|
return c.detach();
|
|
@@ -582,10 +586,8 @@ namespace Sass {
|
|
|
582
586
|
ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(g, ctx.c_options.precision));
|
|
583
587
|
ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(b, ctx.c_options.precision));
|
|
584
588
|
|
|
585
|
-
std::string result
|
|
586
|
-
|
|
587
|
-
result[i] = std::toupper(result[i]);
|
|
588
|
-
}
|
|
589
|
+
std::string result = ss.str();
|
|
590
|
+
Util::ascii_str_toupper(&result);
|
|
589
591
|
return SASS_MEMORY_NEW(String_Quoted, pstate, result);
|
|
590
592
|
}
|
|
591
593
|
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// sass.hpp must go before all system headers to get the
|
|
2
|
+
// __EXTENSIONS__ fix on Solaris.
|
|
3
|
+
#include "sass.hpp"
|
|
4
|
+
|
|
1
5
|
#include "listize.hpp"
|
|
2
6
|
#include "operators.hpp"
|
|
3
7
|
#include "fn_utils.hpp"
|
|
@@ -31,8 +35,8 @@ namespace Sass {
|
|
|
31
35
|
Signature length_sig = "length($list)";
|
|
32
36
|
BUILT_IN(length)
|
|
33
37
|
{
|
|
34
|
-
if (
|
|
35
|
-
return SASS_MEMORY_NEW(Number, pstate, (double)sl->length());
|
|
38
|
+
if (SelectorList * sl = Cast<SelectorList>(env["$list"])) {
|
|
39
|
+
return SASS_MEMORY_NEW(Number, pstate, (double) sl->length());
|
|
36
40
|
}
|
|
37
41
|
Expression* v = ARG("$list", Expression);
|
|
38
42
|
if (v->concrete_type() == Expression::MAP) {
|
|
@@ -40,9 +44,9 @@ namespace Sass {
|
|
|
40
44
|
return SASS_MEMORY_NEW(Number, pstate, (double)(map ? map->length() : 1));
|
|
41
45
|
}
|
|
42
46
|
if (v->concrete_type() == Expression::SELECTOR) {
|
|
43
|
-
if (
|
|
47
|
+
if (CompoundSelector * h = Cast<CompoundSelector>(v)) {
|
|
44
48
|
return SASS_MEMORY_NEW(Number, pstate, (double)h->length());
|
|
45
|
-
} else if (
|
|
49
|
+
} else if (SelectorList * ls = Cast<SelectorList>(v)) {
|
|
46
50
|
return SASS_MEMORY_NEW(Number, pstate, (double)ls->length());
|
|
47
51
|
} else {
|
|
48
52
|
return SASS_MEMORY_NEW(Number, pstate, 1);
|
|
@@ -60,15 +64,13 @@ namespace Sass {
|
|
|
60
64
|
{
|
|
61
65
|
double nr = ARGVAL("$n");
|
|
62
66
|
Map* m = Cast<Map>(env["$list"]);
|
|
63
|
-
if (
|
|
67
|
+
if (SelectorList * sl = Cast<SelectorList>(env["$list"])) {
|
|
64
68
|
size_t len = m ? m->length() : sl->length();
|
|
65
69
|
bool empty = m ? m->empty() : sl->empty();
|
|
66
70
|
if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces);
|
|
67
71
|
double index = std::floor(nr < 0 ? len + nr : nr - 1);
|
|
68
72
|
if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate, traces);
|
|
69
|
-
|
|
70
|
-
Listize listize;
|
|
71
|
-
return Cast<Value>((*sl)[static_cast<int>(index)]->perform(&listize));
|
|
73
|
+
return Cast<Value>(Listize::perform(sl->get(static_cast<int>(index))));
|
|
72
74
|
}
|
|
73
75
|
List_Obj l = Cast<List>(env["$list"]);
|
|
74
76
|
if (nr == 0) error("argument `$n` of `" + std::string(sig) + "` must be non-zero", pstate, traces);
|
|
@@ -189,9 +191,8 @@ namespace Sass {
|
|
|
189
191
|
Map_Obj m = Cast<Map>(env["$list"]);
|
|
190
192
|
List_Obj l = Cast<List>(env["$list"]);
|
|
191
193
|
Expression_Obj v = ARG("$val", Expression);
|
|
192
|
-
if (
|
|
193
|
-
Listize
|
|
194
|
-
l = Cast<List>(sl->perform(&listize));
|
|
194
|
+
if (SelectorList * sl = Cast<SelectorList>(env["$list"])) {
|
|
195
|
+
l = Cast<List>(Listize::perform(sl));
|
|
195
196
|
}
|
|
196
197
|
String_Constant_Obj sep = ARG("$separator", String_Constant);
|
|
197
198
|
if (!l) {
|
|
@@ -8,15 +8,6 @@ namespace Sass {
|
|
|
8
8
|
|
|
9
9
|
namespace Functions {
|
|
10
10
|
|
|
11
|
-
// features
|
|
12
|
-
static std::set<std::string> features {
|
|
13
|
-
"global-variable-shadowing",
|
|
14
|
-
"extend-selector-pseudoclass",
|
|
15
|
-
"at-error",
|
|
16
|
-
"units-level-3",
|
|
17
|
-
"custom-property"
|
|
18
|
-
};
|
|
19
|
-
|
|
20
11
|
//////////////////////////
|
|
21
12
|
// INTROSPECTION FUNCTIONS
|
|
22
13
|
//////////////////////////
|
|
@@ -85,34 +76,36 @@ namespace Sass {
|
|
|
85
76
|
}
|
|
86
77
|
}
|
|
87
78
|
|
|
88
|
-
Signature feature_exists_sig = "feature-exists($
|
|
79
|
+
Signature feature_exists_sig = "feature-exists($feature)";
|
|
89
80
|
BUILT_IN(feature_exists)
|
|
90
81
|
{
|
|
91
|
-
std::string s = unquote(ARG("$
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
82
|
+
std::string s = unquote(ARG("$feature", String_Constant)->value());
|
|
83
|
+
|
|
84
|
+
static const auto *const features = new std::unordered_set<std::string> {
|
|
85
|
+
"global-variable-shadowing",
|
|
86
|
+
"extend-selector-pseudoclass",
|
|
87
|
+
"at-error",
|
|
88
|
+
"units-level-3",
|
|
89
|
+
"custom-property"
|
|
90
|
+
};
|
|
91
|
+
return SASS_MEMORY_NEW(Boolean, pstate, features->find(s) != features->end());
|
|
99
92
|
}
|
|
100
93
|
|
|
101
|
-
Signature call_sig = "call($
|
|
94
|
+
Signature call_sig = "call($function, $args...)";
|
|
102
95
|
BUILT_IN(call)
|
|
103
96
|
{
|
|
104
|
-
std::string
|
|
105
|
-
Function* ff = Cast<Function>(env["$
|
|
106
|
-
String_Constant* ss = Cast<String_Constant>(env["$
|
|
97
|
+
std::string function;
|
|
98
|
+
Function* ff = Cast<Function>(env["$function"]);
|
|
99
|
+
String_Constant* ss = Cast<String_Constant>(env["$function"]);
|
|
107
100
|
|
|
108
101
|
if (ss) {
|
|
109
|
-
|
|
102
|
+
function = Util::normalize_underscores(unquote(ss->value()));
|
|
110
103
|
std::cerr << "DEPRECATION WARNING: ";
|
|
111
104
|
std::cerr << "Passing a string to call() is deprecated and will be illegal" << std::endl;
|
|
112
|
-
std::cerr << "in Sass 4.0. Use call(get-function(" + quote(
|
|
105
|
+
std::cerr << "in Sass 4.0. Use call(get-function(" + quote(function) + ")) instead." << std::endl;
|
|
113
106
|
std::cerr << std::endl;
|
|
114
107
|
} else if (ff) {
|
|
115
|
-
|
|
108
|
+
function = ff->name();
|
|
116
109
|
}
|
|
117
110
|
|
|
118
111
|
List_Obj arglist = SASS_MEMORY_COPY(ARG("$args", List));
|
|
@@ -142,8 +135,9 @@ namespace Sass {
|
|
|
142
135
|
args->append(SASS_MEMORY_NEW(Argument, pstate, expr));
|
|
143
136
|
}
|
|
144
137
|
}
|
|
145
|
-
Function_Call_Obj func = SASS_MEMORY_NEW(Function_Call, pstate,
|
|
146
|
-
|
|
138
|
+
Function_Call_Obj func = SASS_MEMORY_NEW(Function_Call, pstate, function, args);
|
|
139
|
+
|
|
140
|
+
Expand expand(ctx, &d_env, &selector_stack, &original_stack);
|
|
147
141
|
func->via_call(true); // calc invoke is allowed
|
|
148
142
|
if (ff) func->func(ff);
|
|
149
143
|
return Cast<PreValue>(func->perform(&expand.eval));
|
|
@@ -160,11 +154,9 @@ namespace Sass {
|
|
|
160
154
|
}
|
|
161
155
|
|
|
162
156
|
Signature if_sig = "if($condition, $if-true, $if-false)";
|
|
163
|
-
// BUILT_IN(sass_if)
|
|
164
|
-
// { return ARG("$condition", Expression)->is_false() ? ARG("$if-false", Expression) : ARG("$if-true", Expression); }
|
|
165
157
|
BUILT_IN(sass_if)
|
|
166
158
|
{
|
|
167
|
-
Expand expand(ctx, &d_env, &selector_stack);
|
|
159
|
+
Expand expand(ctx, &d_env, &selector_stack, &original_stack);
|
|
168
160
|
Expression_Obj cond = ARG("$condition", Expression)->perform(&expand.eval);
|
|
169
161
|
bool is_true = !cond->is_false();
|
|
170
162
|
Expression_Obj res = ARG(is_true ? "$if-true" : "$if-false", Expression);
|
|
@@ -178,9 +170,6 @@ namespace Sass {
|
|
|
178
170
|
// MISCELLANEOUS FUNCTIONS
|
|
179
171
|
//////////////////////////
|
|
180
172
|
|
|
181
|
-
// value.check_deprecated_interp if value.is_a?(Sass::Script::Value::String)
|
|
182
|
-
// unquoted_string(value.to_sass)
|
|
183
|
-
|
|
184
173
|
Signature inspect_sig = "inspect($value)";
|
|
185
174
|
BUILT_IN(inspect)
|
|
186
175
|
{
|
|
@@ -208,7 +197,6 @@ namespace Sass {
|
|
|
208
197
|
ctx.c_options.output_style = old_style;
|
|
209
198
|
return SASS_MEMORY_NEW(String_Quoted, pstate, i.get_buffer());
|
|
210
199
|
}
|
|
211
|
-
// return v;
|
|
212
200
|
}
|
|
213
201
|
|
|
214
202
|
Signature content_exists_sig = "content-exists()";
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
#include <cstdint>
|
|
6
6
|
#include <cstdlib>
|
|
7
7
|
#include <cmath>
|
|
8
|
-
#include <cctype>
|
|
9
8
|
#include <random>
|
|
10
9
|
#include <sstream>
|
|
11
10
|
#include <iomanip>
|
|
@@ -106,7 +105,11 @@ namespace Sass {
|
|
|
106
105
|
{
|
|
107
106
|
List* arglist = ARG("$numbers", List);
|
|
108
107
|
Number_Obj least;
|
|
109
|
-
|
|
108
|
+
size_t L = arglist->length();
|
|
109
|
+
if (L == 0) {
|
|
110
|
+
error("At least one argument must be passed.", pstate, traces);
|
|
111
|
+
}
|
|
112
|
+
for (size_t i = 0; i < L; ++i) {
|
|
110
113
|
Expression_Obj val = arglist->value_at_index(i);
|
|
111
114
|
Number_Obj xi = Cast<Number>(val);
|
|
112
115
|
if (!xi) {
|
|
@@ -124,7 +127,11 @@ namespace Sass {
|
|
|
124
127
|
{
|
|
125
128
|
List* arglist = ARG("$numbers", List);
|
|
126
129
|
Number_Obj greatest;
|
|
127
|
-
|
|
130
|
+
size_t L = arglist->length();
|
|
131
|
+
if (L == 0) {
|
|
132
|
+
error("At least one argument must be passed.", pstate, traces);
|
|
133
|
+
}
|
|
134
|
+
for (size_t i = 0; i < L; ++i) {
|
|
128
135
|
Expression_Obj val = arglist->value_at_index(i);
|
|
129
136
|
Number_Obj xi = Cast<Number>(val);
|
|
130
137
|
if (!xi) {
|
|
@@ -200,11 +207,11 @@ namespace Sass {
|
|
|
200
207
|
return SASS_MEMORY_NEW(Boolean, pstate, unitless);
|
|
201
208
|
}
|
|
202
209
|
|
|
203
|
-
Signature comparable_sig = "comparable($
|
|
210
|
+
Signature comparable_sig = "comparable($number1, $number2)";
|
|
204
211
|
BUILT_IN(comparable)
|
|
205
212
|
{
|
|
206
|
-
Number_Obj n1 = ARGN("$
|
|
207
|
-
Number_Obj n2 = ARGN("$
|
|
213
|
+
Number_Obj n1 = ARGN("$number1");
|
|
214
|
+
Number_Obj n2 = ARGN("$number2");
|
|
208
215
|
if (n1->is_unitless() || n2->is_unitless()) {
|
|
209
216
|
return SASS_MEMORY_NEW(Boolean, pstate, true);
|
|
210
217
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
#include <numeric>
|
|
2
|
+
|
|
1
3
|
#include "parser.hpp"
|
|
2
|
-
#include "
|
|
4
|
+
#include "extender.hpp"
|
|
5
|
+
#include "listize.hpp"
|
|
3
6
|
#include "fn_utils.hpp"
|
|
4
7
|
#include "fn_selectors.hpp"
|
|
5
8
|
|
|
@@ -13,24 +16,27 @@ namespace Sass {
|
|
|
13
16
|
List* arglist = ARG("$selectors", List);
|
|
14
17
|
|
|
15
18
|
// Not enough parameters
|
|
16
|
-
if(
|
|
17
|
-
error(
|
|
19
|
+
if (arglist->length() == 0) {
|
|
20
|
+
error(
|
|
21
|
+
"$selectors: At least one selector must be passed for `selector-nest'",
|
|
22
|
+
pstate, traces);
|
|
23
|
+
}
|
|
18
24
|
|
|
19
25
|
// Parse args into vector of selectors
|
|
20
26
|
SelectorStack parsedSelectors;
|
|
21
27
|
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
|
22
28
|
Expression_Obj exp = Cast<Expression>(arglist->value_at_index(i));
|
|
23
29
|
if (exp->concrete_type() == Expression::NULL_VAL) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
error(
|
|
31
|
+
"$selectors: null is not a valid selector: it must be a string,\n"
|
|
32
|
+
"a list of strings, or a list of lists of strings for 'selector-nest'",
|
|
33
|
+
pstate, traces);
|
|
28
34
|
}
|
|
29
35
|
if (String_Constant_Obj str = Cast<String_Constant>(exp)) {
|
|
30
36
|
str->quote_mark(0);
|
|
31
37
|
}
|
|
32
38
|
std::string exp_src = exp->to_string(ctx.c_options);
|
|
33
|
-
|
|
39
|
+
SelectorListObj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces);
|
|
34
40
|
parsedSelectors.push_back(sel);
|
|
35
41
|
}
|
|
36
42
|
|
|
@@ -39,25 +45,21 @@ namespace Sass {
|
|
|
39
45
|
return SASS_MEMORY_NEW(Null, pstate);
|
|
40
46
|
}
|
|
41
47
|
|
|
42
|
-
// Set the first element as the `result`, keep
|
|
48
|
+
// Set the first element as the `result`, keep
|
|
49
|
+
// appending to as we go down the parsedSelector vector.
|
|
43
50
|
SelectorStack::iterator itr = parsedSelectors.begin();
|
|
44
|
-
|
|
51
|
+
SelectorListObj& result = *itr;
|
|
45
52
|
++itr;
|
|
46
53
|
|
|
47
54
|
for(;itr != parsedSelectors.end(); ++itr) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
for (size_t m = 0, mLen = rv->length(); m < mLen; ++m) {
|
|
54
|
-
exploded.push_back((*rv)[m]);
|
|
55
|
-
}
|
|
56
|
-
result->elements(exploded);
|
|
55
|
+
SelectorListObj& child = *itr;
|
|
56
|
+
original_stack.push_back(result);
|
|
57
|
+
SelectorListObj rv = child->resolve_parent_refs(original_stack, traces);
|
|
58
|
+
result->elements(rv->elements());
|
|
59
|
+
original_stack.pop_back();
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
Listize
|
|
60
|
-
return Cast<Value>(result->perform(&listize));
|
|
62
|
+
return Cast<Value>(Listize::perform(result));
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
Signature selector_append_sig = "selector-append($selectors...)";
|
|
@@ -66,113 +68,96 @@ namespace Sass {
|
|
|
66
68
|
List* arglist = ARG("$selectors", List);
|
|
67
69
|
|
|
68
70
|
// Not enough parameters
|
|
69
|
-
if(
|
|
70
|
-
error(
|
|
71
|
+
if (arglist->empty()) {
|
|
72
|
+
error(
|
|
73
|
+
"$selectors: At least one selector must be "
|
|
74
|
+
"passed for `selector-append'",
|
|
75
|
+
pstate, traces);
|
|
76
|
+
}
|
|
71
77
|
|
|
72
78
|
// Parse args into vector of selectors
|
|
73
79
|
SelectorStack parsedSelectors;
|
|
80
|
+
parsedSelectors.push_back({});
|
|
74
81
|
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
|
75
|
-
|
|
82
|
+
Expression* exp = Cast<Expression>(arglist->value_at_index(i));
|
|
76
83
|
if (exp->concrete_type() == Expression::NULL_VAL) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
error(
|
|
85
|
+
"$selectors: null is not a valid selector: it must be a string,\n"
|
|
86
|
+
"a list of strings, or a list of lists of strings for 'selector-append'",
|
|
87
|
+
pstate, traces);
|
|
81
88
|
}
|
|
82
89
|
if (String_Constant* str = Cast<String_Constant>(exp)) {
|
|
83
90
|
str->quote_mark(0);
|
|
84
91
|
}
|
|
85
92
|
std::string exp_src = exp->to_string();
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
parsedSelectors.push_back(sel);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Nothing to do
|
|
94
|
-
if( parsedSelectors.empty() ) {
|
|
95
|
-
return SASS_MEMORY_NEW(Null, pstate);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Set the first element as the `result`, keep appending to as we go down the parsedSelector vector.
|
|
99
|
-
SelectorStack::iterator itr = parsedSelectors.begin();
|
|
100
|
-
Selector_List_Obj result = *itr;
|
|
101
|
-
++itr;
|
|
102
|
-
|
|
103
|
-
for(;itr != parsedSelectors.end(); ++itr) {
|
|
104
|
-
Selector_List_Obj child = *itr;
|
|
105
|
-
std::vector<Complex_Selector_Obj> newElements;
|
|
106
|
-
|
|
107
|
-
// For every COMPLEX_SELECTOR in `result`
|
|
108
|
-
// For every COMPLEX_SELECTOR in `child`
|
|
109
|
-
// let parentSeqClone equal a copy of result->elements[i]
|
|
110
|
-
// let childSeq equal child->elements[j]
|
|
111
|
-
// Append all of childSeq head elements into parentSeqClone
|
|
112
|
-
// Set the innermost tail of parentSeqClone, to childSeq's tail
|
|
113
|
-
// Replace result->elements with newElements
|
|
114
|
-
for (size_t i = 0, resultLen = result->length(); i < resultLen; ++i) {
|
|
115
|
-
for (size_t j = 0, childLen = child->length(); j < childLen; ++j) {
|
|
116
|
-
Complex_Selector_Obj parentSeqClone = SASS_MEMORY_CLONE((*result)[i]);
|
|
117
|
-
Complex_Selector_Obj childSeq = (*child)[j];
|
|
118
|
-
Complex_Selector_Obj base = childSeq->tail();
|
|
119
|
-
|
|
120
|
-
// Must be a simple sequence
|
|
121
|
-
if( childSeq->combinator() != Complex_Selector::Combinator::ANCESTOR_OF ) {
|
|
122
|
-
error("Can't append \"" + childSeq->to_string() + "\" to \"" +
|
|
123
|
-
parentSeqClone->to_string() + "\" for `selector-append'", pstate, traces);
|
|
124
|
-
}
|
|
93
|
+
SelectorListObj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces,
|
|
94
|
+
exp->pstate(), pstate.src,
|
|
95
|
+
/*allow_parent=*/true);
|
|
125
96
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
97
|
+
for (auto& complex : sel->elements()) {
|
|
98
|
+
if (complex->empty()) {
|
|
99
|
+
complex->append(SASS_MEMORY_NEW(CompoundSelector, "[phony]"));
|
|
100
|
+
}
|
|
101
|
+
if (CompoundSelector* comp = Cast<CompoundSelector>(complex->first())) {
|
|
102
|
+
comp->hasRealParent(true);
|
|
103
|
+
complex->chroots(true);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
132
106
|
|
|
133
|
-
|
|
107
|
+
if (parsedSelectors.size() > 1) {
|
|
134
108
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
109
|
+
if (!sel->has_real_parent_ref()) {
|
|
110
|
+
auto parent = parsedSelectors.back();
|
|
111
|
+
for (auto& complex : parent->elements()) {
|
|
112
|
+
if (CompoundSelector* comp = Cast<CompoundSelector>(complex->first())) {
|
|
113
|
+
comp->hasRealParent(false);
|
|
114
|
+
}
|
|
139
115
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
newElements.push_back(parentSeqClone);
|
|
116
|
+
error("Can't append \"" + sel->to_string() + "\" to \"" +
|
|
117
|
+
parent->to_string() + "\" for `selector-append'",
|
|
118
|
+
pstate, traces);
|
|
144
119
|
}
|
|
120
|
+
|
|
121
|
+
// Build the resolved stack from the left. It's cheaper to directly
|
|
122
|
+
// calculate and update each resolved selcted from the left, than to
|
|
123
|
+
// recursively calculate them from the right side, as we would need
|
|
124
|
+
// to go through the whole stack depth to build the final results.
|
|
125
|
+
// E.g. 'a', 'b', 'x, y' => 'a' => 'a b' => 'a b x, a b y'
|
|
126
|
+
// vs 'a', 'b', 'x, y' => 'x' => 'b x' => 'a b x', 'y' ...
|
|
127
|
+
parsedSelectors.push_back(sel->resolve_parent_refs(parsedSelectors, traces, true));
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
parsedSelectors.push_back(sel);
|
|
145
131
|
}
|
|
132
|
+
}
|
|
146
133
|
|
|
147
|
-
|
|
134
|
+
// Nothing to do
|
|
135
|
+
if( parsedSelectors.empty() ) {
|
|
136
|
+
return SASS_MEMORY_NEW(Null, pstate);
|
|
148
137
|
}
|
|
149
138
|
|
|
150
|
-
Listize
|
|
151
|
-
return Cast<Value>(result->perform(&listize));
|
|
139
|
+
return Cast<Value>(Listize::perform(parsedSelectors.back()));
|
|
152
140
|
}
|
|
153
141
|
|
|
154
142
|
Signature selector_unify_sig = "selector-unify($selector1, $selector2)";
|
|
155
143
|
BUILT_IN(selector_unify)
|
|
156
144
|
{
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
Listize listize;
|
|
162
|
-
return Cast<Value>(result->perform(&listize));
|
|
145
|
+
SelectorListObj selector1 = ARGSELS("$selector1");
|
|
146
|
+
SelectorListObj selector2 = ARGSELS("$selector2");
|
|
147
|
+
SelectorListObj result = selector1->unifyWith(selector2);
|
|
148
|
+
return Cast<Value>(Listize::perform(result));
|
|
163
149
|
}
|
|
164
150
|
|
|
165
151
|
Signature simple_selectors_sig = "simple-selectors($selector)";
|
|
166
152
|
BUILT_IN(simple_selectors)
|
|
167
153
|
{
|
|
168
|
-
|
|
154
|
+
CompoundSelectorObj sel = ARGSEL("$selector");
|
|
169
155
|
|
|
170
156
|
List* l = SASS_MEMORY_NEW(List, sel->pstate(), sel->length(), SASS_COMMA);
|
|
171
157
|
|
|
172
158
|
for (size_t i = 0, L = sel->length(); i < L; ++i) {
|
|
173
|
-
|
|
159
|
+
const SimpleSelectorObj& ss = sel->get(i);
|
|
174
160
|
std::string ss_string = ss->to_string() ;
|
|
175
|
-
|
|
176
161
|
l->append(SASS_MEMORY_NEW(String_Quoted, ss->pstate(), ss_string));
|
|
177
162
|
}
|
|
178
163
|
|
|
@@ -182,51 +167,36 @@ namespace Sass {
|
|
|
182
167
|
Signature selector_extend_sig = "selector-extend($selector, $extendee, $extender)";
|
|
183
168
|
BUILT_IN(selector_extend)
|
|
184
169
|
{
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
extender->populate_extends(extendee, subset_map);
|
|
191
|
-
Extend extend(subset_map);
|
|
192
|
-
|
|
193
|
-
Selector_List_Obj result = extend.extendSelectorList(selector, false);
|
|
194
|
-
|
|
195
|
-
Listize listize;
|
|
196
|
-
return Cast<Value>(result->perform(&listize));
|
|
170
|
+
SelectorListObj selector = ARGSELS("$selector");
|
|
171
|
+
SelectorListObj target = ARGSELS("$extendee");
|
|
172
|
+
SelectorListObj source = ARGSELS("$extender");
|
|
173
|
+
SelectorListObj result = Extender::extend(selector, source, target, traces);
|
|
174
|
+
return Cast<Value>(Listize::perform(result));
|
|
197
175
|
}
|
|
198
176
|
|
|
199
177
|
Signature selector_replace_sig = "selector-replace($selector, $original, $replacement)";
|
|
200
178
|
BUILT_IN(selector_replace)
|
|
201
179
|
{
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
Extend extend(subset_map);
|
|
208
|
-
|
|
209
|
-
Selector_List_Obj result = extend.extendSelectorList(selector, true);
|
|
210
|
-
|
|
211
|
-
Listize listize;
|
|
212
|
-
return Cast<Value>(result->perform(&listize));
|
|
180
|
+
SelectorListObj selector = ARGSELS("$selector");
|
|
181
|
+
SelectorListObj target = ARGSELS("$original");
|
|
182
|
+
SelectorListObj source = ARGSELS("$replacement");
|
|
183
|
+
SelectorListObj result = Extender::replace(selector, source, target, traces);
|
|
184
|
+
return Cast<Value>(Listize::perform(result));
|
|
213
185
|
}
|
|
214
186
|
|
|
215
187
|
Signature selector_parse_sig = "selector-parse($selector)";
|
|
216
188
|
BUILT_IN(selector_parse)
|
|
217
189
|
{
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
Listize listize;
|
|
221
|
-
return Cast<Value>(sel->perform(&listize));
|
|
190
|
+
SelectorListObj selector = ARGSELS("$selector");
|
|
191
|
+
return Cast<Value>(Listize::perform(selector));
|
|
222
192
|
}
|
|
223
193
|
|
|
224
194
|
Signature is_superselector_sig = "is-superselector($super, $sub)";
|
|
225
195
|
BUILT_IN(is_superselector)
|
|
226
196
|
{
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
bool result = sel_sup->
|
|
197
|
+
SelectorListObj sel_sup = ARGSELS("$super");
|
|
198
|
+
SelectorListObj sel_sub = ARGSELS("$sub");
|
|
199
|
+
bool result = sel_sup->isSuperselectorOf(sel_sub);
|
|
230
200
|
return SASS_MEMORY_NEW(Boolean, pstate, result);
|
|
231
201
|
}
|
|
232
202
|
|