sassc 1.11.4 → 1.12.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 +5 -5
- data/.travis.yml +2 -2
- data/CODE_OF_CONDUCT.md +10 -0
- data/README.md +4 -1
- data/ext/libsass/.editorconfig +1 -1
- data/ext/libsass/.github/CONTRIBUTING.md +7 -7
- data/ext/libsass/.github/ISSUE_TEMPLATE.md +31 -6
- data/ext/libsass/.gitignore +3 -0
- data/ext/libsass/.travis.yml +37 -18
- data/ext/libsass/GNUmakefile.am +23 -37
- data/ext/libsass/Makefile +10 -6
- data/ext/libsass/Makefile.conf +3 -0
- data/ext/libsass/Readme.md +68 -63
- data/ext/libsass/appveyor.yml +7 -3
- data/ext/libsass/configure.ac +10 -14
- data/ext/libsass/docs/api-context-internal.md +29 -21
- data/ext/libsass/docs/api-context.md +26 -6
- data/ext/libsass/docs/api-doc.md +49 -16
- data/ext/libsass/docs/api-function-example.md +1 -1
- data/ext/libsass/docs/api-function.md +31 -7
- data/ext/libsass/docs/api-importer.md +19 -19
- data/ext/libsass/docs/api-value.md +4 -2
- data/ext/libsass/docs/build-on-windows.md +4 -4
- data/ext/libsass/docs/build-with-mingw.md +3 -3
- data/ext/libsass/docs/build.md +9 -9
- data/ext/libsass/docs/custom-functions-internal.md +10 -8
- data/ext/libsass/docs/implementations.md +20 -8
- data/ext/libsass/docs/unicode.md +16 -10
- data/ext/libsass/include/sass/base.h +0 -3
- data/ext/libsass/include/sass/context.h +20 -2
- data/ext/libsass/include/sass/functions.h +31 -0
- data/ext/libsass/include/sass/values.h +3 -1
- data/ext/libsass/include/sass/version.h +1 -1
- data/ext/libsass/include/sass/version.h.in +1 -1
- data/ext/libsass/include/sass2scss.h +1 -1
- data/ext/libsass/res/resource.rc +6 -6
- data/ext/libsass/script/ci-build-libsass +10 -5
- data/ext/libsass/script/ci-build-plugin +62 -0
- data/ext/libsass/script/ci-install-compiler +1 -1
- data/ext/libsass/script/ci-install-deps +4 -7
- data/ext/libsass/script/ci-report-coverage +13 -3
- data/ext/libsass/script/tap-driver +1 -1
- data/ext/libsass/script/tap-runner +1 -1
- data/ext/libsass/src/GNUmakefile.am +1 -1
- data/ext/libsass/src/ast.cpp +537 -762
- data/ext/libsass/src/ast.hpp +377 -419
- data/ext/libsass/src/ast_def_macros.hpp +26 -1
- data/ext/libsass/src/ast_fwd_decl.cpp +29 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +94 -21
- data/ext/libsass/src/b64/encode.h +3 -1
- data/ext/libsass/src/backtrace.cpp +46 -0
- data/ext/libsass/src/backtrace.hpp +7 -54
- data/ext/libsass/src/bind.cpp +72 -50
- data/ext/libsass/src/bind.hpp +0 -1
- data/ext/libsass/src/cencode.c +6 -0
- data/ext/libsass/src/check_nesting.cpp +157 -135
- data/ext/libsass/src/check_nesting.hpp +11 -10
- data/ext/libsass/src/color_maps.cpp +10 -6
- data/ext/libsass/src/color_maps.hpp +6 -8
- data/ext/libsass/src/constants.cpp +4 -3
- data/ext/libsass/src/constants.hpp +4 -3
- data/ext/libsass/src/context.cpp +110 -47
- data/ext/libsass/src/context.hpp +11 -1
- data/ext/libsass/src/cssize.cpp +105 -94
- data/ext/libsass/src/cssize.hpp +4 -5
- data/ext/libsass/src/debugger.hpp +247 -244
- data/ext/libsass/src/emitter.cpp +30 -6
- data/ext/libsass/src/emitter.hpp +7 -0
- data/ext/libsass/src/environment.cpp +67 -16
- data/ext/libsass/src/environment.hpp +28 -7
- data/ext/libsass/src/error_handling.cpp +92 -64
- data/ext/libsass/src/error_handling.hpp +64 -43
- data/ext/libsass/src/eval.cpp +494 -544
- data/ext/libsass/src/eval.hpp +17 -23
- data/ext/libsass/src/expand.cpp +182 -154
- data/ext/libsass/src/expand.hpp +4 -5
- data/ext/libsass/src/extend.cpp +299 -291
- data/ext/libsass/src/extend.hpp +46 -11
- data/ext/libsass/src/file.cpp +103 -36
- data/ext/libsass/src/file.hpp +21 -4
- data/ext/libsass/src/functions.cpp +561 -312
- data/ext/libsass/src/functions.hpp +8 -5
- data/ext/libsass/src/inspect.cpp +108 -53
- data/ext/libsass/src/inspect.hpp +5 -2
- data/ext/libsass/src/lexer.cpp +15 -7
- data/ext/libsass/src/lexer.hpp +13 -4
- data/ext/libsass/src/listize.cpp +3 -2
- data/ext/libsass/src/listize.hpp +0 -1
- data/ext/libsass/src/memory/SharedPtr.cpp +16 -18
- data/ext/libsass/src/memory/SharedPtr.hpp +47 -43
- data/ext/libsass/src/node.cpp +34 -38
- data/ext/libsass/src/node.hpp +6 -8
- data/ext/libsass/src/operation.hpp +2 -2
- data/ext/libsass/src/operators.cpp +240 -0
- data/ext/libsass/src/operators.hpp +30 -0
- data/ext/libsass/src/output.cpp +22 -20
- data/ext/libsass/src/parser.cpp +719 -358
- data/ext/libsass/src/parser.hpp +57 -22
- data/ext/libsass/src/plugins.cpp +28 -10
- data/ext/libsass/src/position.cpp +21 -3
- data/ext/libsass/src/position.hpp +2 -1
- data/ext/libsass/src/prelexer.cpp +104 -19
- data/ext/libsass/src/prelexer.hpp +10 -3
- data/ext/libsass/src/remove_placeholders.cpp +9 -10
- data/ext/libsass/src/remove_placeholders.hpp +1 -5
- data/ext/libsass/src/sass.cpp +62 -4
- data/ext/libsass/src/sass.hpp +5 -2
- data/ext/libsass/src/sass_context.cpp +96 -58
- data/ext/libsass/src/sass_context.hpp +7 -5
- data/ext/libsass/src/sass_functions.cpp +63 -1
- data/ext/libsass/src/sass_functions.hpp +19 -1
- data/ext/libsass/src/sass_util.cpp +3 -3
- data/ext/libsass/src/sass_util.hpp +4 -4
- data/ext/libsass/src/sass_values.cpp +42 -39
- data/ext/libsass/src/sass_values.hpp +2 -1
- data/ext/libsass/src/source_map.cpp +16 -18
- data/ext/libsass/src/subset_map.cpp +6 -8
- data/ext/libsass/src/subset_map.hpp +6 -6
- data/ext/libsass/src/to_c.cpp +2 -2
- data/ext/libsass/src/to_value.cpp +8 -3
- data/ext/libsass/src/to_value.hpp +1 -0
- data/ext/libsass/src/units.cpp +349 -45
- data/ext/libsass/src/units.hpp +39 -22
- data/ext/libsass/src/utf8/checked.h +7 -0
- data/ext/libsass/src/utf8/unchecked.h +7 -0
- data/ext/libsass/src/utf8_string.cpp +1 -1
- data/ext/libsass/src/util.cpp +139 -45
- data/ext/libsass/src/util.hpp +4 -7
- data/ext/libsass/src/values.cpp +15 -23
- data/ext/libsass/win/libsass.sln +13 -2
- data/ext/libsass/win/libsass.sln.DotSettings +9 -0
- data/ext/libsass/win/libsass.targets +3 -0
- data/ext/libsass/win/libsass.vcxproj.filters +9 -0
- data/lib/sassc/version.rb +1 -1
- data/sassc.gemspec +1 -1
- data/test/native_test.rb +1 -1
- metadata +11 -4
data/ext/libsass/src/extend.hpp
CHANGED
|
@@ -5,35 +5,70 @@
|
|
|
5
5
|
#include <set>
|
|
6
6
|
|
|
7
7
|
#include "ast.hpp"
|
|
8
|
+
#include "node.hpp"
|
|
9
|
+
#include "eval.hpp"
|
|
8
10
|
#include "operation.hpp"
|
|
9
11
|
#include "subset_map.hpp"
|
|
12
|
+
#include "ast_fwd_decl.hpp"
|
|
10
13
|
|
|
11
14
|
namespace Sass {
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
class Node;
|
|
16
|
+
Node subweave(Node& one, Node& two);
|
|
15
17
|
|
|
16
18
|
class Extend : public Operation_CRTP<void, Extend> {
|
|
17
19
|
|
|
18
|
-
Context& ctx;
|
|
19
20
|
Subset_Map& subset_map;
|
|
21
|
+
Eval* eval;
|
|
20
22
|
|
|
21
23
|
void fallback_impl(AST_Node_Ptr n) { }
|
|
22
24
|
|
|
25
|
+
private:
|
|
26
|
+
|
|
27
|
+
std::unordered_map<
|
|
28
|
+
Selector_List_Obj, // key
|
|
29
|
+
Selector_List_Obj, // value
|
|
30
|
+
HashNodes, // hasher
|
|
31
|
+
CompareNodes // compare
|
|
32
|
+
> memoizeList;
|
|
33
|
+
|
|
34
|
+
std::unordered_map<
|
|
35
|
+
Complex_Selector_Obj, // key
|
|
36
|
+
Node, // value
|
|
37
|
+
HashNodes, // hasher
|
|
38
|
+
CompareNodes // compare
|
|
39
|
+
> memoizeComplex;
|
|
40
|
+
|
|
41
|
+
/* this turned out to be too much overhead
|
|
42
|
+
re-evaluate once we store an ast selector
|
|
43
|
+
std::unordered_map<
|
|
44
|
+
Compound_Selector_Obj, // key
|
|
45
|
+
Node, // value
|
|
46
|
+
HashNodes, // hasher
|
|
47
|
+
CompareNodes // compare
|
|
48
|
+
> memoizeCompound;
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
void extendObjectWithSelectorAndBlock(Ruleset_Ptr pObject);
|
|
52
|
+
Node extendComplexSelector(Complex_Selector_Ptr sel, CompoundSelectorSet& seen, bool isReplace, bool isOriginal);
|
|
53
|
+
Node extendCompoundSelector(Compound_Selector_Ptr sel, CompoundSelectorSet& seen, bool isReplace);
|
|
54
|
+
bool complexSelectorHasExtension(Complex_Selector_Ptr selector, CompoundSelectorSet& seen);
|
|
55
|
+
Node trim(Node& seqses, bool isReplace);
|
|
56
|
+
Node weave(Node& path);
|
|
57
|
+
|
|
23
58
|
public:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
static Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, Context& ctx, Subset_Map& subset_map, bool isReplace = false) {
|
|
59
|
+
void setEval(Eval& eval);
|
|
60
|
+
Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace, bool& extendedSomething, CompoundSelectorSet& seen);
|
|
61
|
+
Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, bool isReplace = false) {
|
|
28
62
|
bool extendedSomething = false;
|
|
29
|
-
|
|
63
|
+
CompoundSelectorSet seen;
|
|
64
|
+
return extendSelectorList(pSelectorList, isReplace, extendedSomething, seen);
|
|
30
65
|
}
|
|
31
|
-
|
|
66
|
+
Selector_List_Ptr extendSelectorList(Selector_List_Obj pSelectorList, CompoundSelectorSet& seen) {
|
|
32
67
|
bool isReplace = false;
|
|
33
68
|
bool extendedSomething = false;
|
|
34
|
-
return extendSelectorList(pSelectorList,
|
|
69
|
+
return extendSelectorList(pSelectorList, isReplace, extendedSomething, seen);
|
|
35
70
|
}
|
|
36
|
-
Extend(
|
|
71
|
+
Extend(Subset_Map&);
|
|
37
72
|
~Extend() { }
|
|
38
73
|
|
|
39
74
|
void operator()(Block_Ptr);
|
data/ext/libsass/src/file.cpp
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#include "sass.hpp"
|
|
1
2
|
#ifdef _WIN32
|
|
2
3
|
# ifdef __MINGW32__
|
|
3
4
|
# ifndef off64_t
|
|
@@ -9,7 +10,6 @@
|
|
|
9
10
|
#else
|
|
10
11
|
# include <unistd.h>
|
|
11
12
|
#endif
|
|
12
|
-
#include "sass.hpp"
|
|
13
13
|
#include <iostream>
|
|
14
14
|
#include <fstream>
|
|
15
15
|
#include <cctype>
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
#include "context.hpp"
|
|
21
21
|
#include "prelexer.hpp"
|
|
22
22
|
#include "utf8_string.hpp"
|
|
23
|
+
#include "sass_functions.hpp"
|
|
23
24
|
#include "sass2scss.h"
|
|
24
25
|
|
|
25
26
|
#ifdef _WIN32
|
|
@@ -48,15 +49,22 @@ namespace Sass {
|
|
|
48
49
|
|
|
49
50
|
// return the current directory
|
|
50
51
|
// always with forward slashes
|
|
52
|
+
// always with trailing slash
|
|
51
53
|
std::string get_cwd()
|
|
52
54
|
{
|
|
53
|
-
const size_t wd_len =
|
|
55
|
+
const size_t wd_len = 4096;
|
|
54
56
|
#ifndef _WIN32
|
|
55
57
|
char wd[wd_len];
|
|
56
|
-
|
|
58
|
+
char* pwd = getcwd(wd, wd_len);
|
|
59
|
+
// we should check error for more detailed info (e.g. ENOENT)
|
|
60
|
+
// http://man7.org/linux/man-pages/man2/getcwd.2.html#ERRORS
|
|
61
|
+
if (pwd == NULL) throw Exception::OperationError("cwd gone missing");
|
|
62
|
+
std::string cwd = pwd;
|
|
57
63
|
#else
|
|
58
64
|
wchar_t wd[wd_len];
|
|
59
|
-
|
|
65
|
+
wchar_t* pwd = _wgetcwd(wd, wd_len);
|
|
66
|
+
if (pwd == NULL) throw Exception::OperationError("cwd gone missing");
|
|
67
|
+
std::string cwd = wstring_to_string(pwd);
|
|
60
68
|
//convert backslashes to forward slashes
|
|
61
69
|
replace(cwd.begin(), cwd.end(), '\\', '/');
|
|
62
70
|
#endif
|
|
@@ -68,8 +76,15 @@ namespace Sass {
|
|
|
68
76
|
bool file_exists(const std::string& path)
|
|
69
77
|
{
|
|
70
78
|
#ifdef _WIN32
|
|
71
|
-
|
|
72
|
-
|
|
79
|
+
wchar_t resolved[32768];
|
|
80
|
+
// windows unicode filepaths are encoded in utf16
|
|
81
|
+
std::string abspath(join_paths(get_cwd(), path));
|
|
82
|
+
std::wstring wpath(UTF_8::convert_to_utf16("\\\\?\\" + abspath));
|
|
83
|
+
std::replace(wpath.begin(), wpath.end(), '/', '\\');
|
|
84
|
+
DWORD rv = GetFullPathNameW(wpath.c_str(), 32767, resolved, NULL);
|
|
85
|
+
if (rv > 32767) throw Exception::OperationError("Path is too long");
|
|
86
|
+
if (rv == 0) throw Exception::OperationError("Path could not be resolved");
|
|
87
|
+
DWORD dwAttrib = GetFileAttributesW(resolved);
|
|
73
88
|
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
|
|
74
89
|
(!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)));
|
|
75
90
|
#else
|
|
@@ -99,7 +114,7 @@ namespace Sass {
|
|
|
99
114
|
// helper function to find the last directory seperator
|
|
100
115
|
inline size_t find_last_folder_separator(const std::string& path, size_t limit = std::string::npos)
|
|
101
116
|
{
|
|
102
|
-
size_t pos
|
|
117
|
+
size_t pos;
|
|
103
118
|
size_t pos_p = path.find_last_of('/', limit);
|
|
104
119
|
#ifdef _WIN32
|
|
105
120
|
size_t pos_w = path.find_last_of('\\', limit);
|
|
@@ -150,7 +165,7 @@ namespace Sass {
|
|
|
150
165
|
pos = 0; // remove all self references inside the path string
|
|
151
166
|
while((pos = path.find("/./", pos)) != std::string::npos) path.erase(pos, 2);
|
|
152
167
|
|
|
153
|
-
|
|
168
|
+
// remove all leading and trailing self references
|
|
154
169
|
while(path.length() > 1 && path.substr(0, 2) == "./") path.erase(0, 2);
|
|
155
170
|
while((pos = path.length()) > 1 && path.substr(pos - 2) == "/.") path.erase(pos - 2);
|
|
156
171
|
|
|
@@ -191,6 +206,13 @@ namespace Sass {
|
|
|
191
206
|
if (is_absolute_path(r)) return r;
|
|
192
207
|
if (l[l.length()-1] != '/') l += '/';
|
|
193
208
|
|
|
209
|
+
// this does a logical cleanup of the right hand path
|
|
210
|
+
// Note that this does collapse x/../y sections into y.
|
|
211
|
+
// This is by design. If /foo on your system is a symlink
|
|
212
|
+
// to /bar/baz, then /foo/../cd is actually /bar/cd,
|
|
213
|
+
// not /cd as a naive ../ removal would give you.
|
|
214
|
+
// will only work on leading double dot dirs on rhs
|
|
215
|
+
// therefore it is safe if lhs is already resolved cwd
|
|
194
216
|
while ((r.length() > 3) && ((r.substr(0, 3) == "../") || (r.substr(0, 3)) == "..\\")) {
|
|
195
217
|
size_t L = l.length(), pos = find_last_folder_separator(l, L - 2);
|
|
196
218
|
bool is_slash = pos + 2 == L && (l[pos+1] == '/' || l[pos+1] == '\\');
|
|
@@ -301,13 +323,9 @@ namespace Sass {
|
|
|
301
323
|
// (2) underscore + given
|
|
302
324
|
// (3) underscore + given + extension
|
|
303
325
|
// (4) given + extension
|
|
304
|
-
std::vector<Include> resolve_includes(const std::string& root, const std::string& file)
|
|
326
|
+
std::vector<Include> resolve_includes(const std::string& root, const std::string& file, const std::vector<std::string>& exts)
|
|
305
327
|
{
|
|
306
328
|
std::string filename = join_paths(root, file);
|
|
307
|
-
// supported extensions
|
|
308
|
-
const std::vector<std::string> exts = {
|
|
309
|
-
".scss", ".sass", ".css"
|
|
310
|
-
};
|
|
311
329
|
// split the filename
|
|
312
330
|
std::string base(dir_name(file));
|
|
313
331
|
std::string name(base_name(file));
|
|
@@ -324,20 +342,53 @@ namespace Sass {
|
|
|
324
342
|
for(auto ext : exts) {
|
|
325
343
|
rel_path = join_paths(base, "_" + name + ext);
|
|
326
344
|
abs_path = join_paths(root, rel_path);
|
|
327
|
-
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
|
|
345
|
+
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path, ext == ".css" });
|
|
328
346
|
}
|
|
329
347
|
// next test plain name with exts
|
|
330
348
|
for(auto ext : exts) {
|
|
331
349
|
rel_path = join_paths(base, name + ext);
|
|
332
350
|
abs_path = join_paths(root, rel_path);
|
|
333
|
-
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
|
|
351
|
+
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path, ext == ".css" });
|
|
334
352
|
}
|
|
335
353
|
// nothing found
|
|
336
354
|
return includes;
|
|
337
355
|
}
|
|
338
356
|
|
|
339
|
-
|
|
357
|
+
std::vector<std::string> find_files(const std::string& file, const std::vector<std::string> paths)
|
|
358
|
+
{
|
|
359
|
+
std::vector<std::string> includes;
|
|
360
|
+
for (std::string path : paths) {
|
|
361
|
+
std::string abs_path(join_paths(path, file));
|
|
362
|
+
if (file_exists(abs_path)) includes.push_back(abs_path);
|
|
363
|
+
}
|
|
364
|
+
return includes;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
std::vector<std::string> find_files(const std::string& file, struct Sass_Compiler* compiler)
|
|
368
|
+
{
|
|
369
|
+
// get the last import entry to get current base directory
|
|
370
|
+
// struct Sass_Options* options = sass_compiler_get_options(compiler);
|
|
371
|
+
Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
|
|
372
|
+
const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
|
|
373
|
+
// create the vector with paths to lookup
|
|
374
|
+
std::vector<std::string> paths(1 + incs.size());
|
|
375
|
+
paths.push_back(dir_name(import->abs_path));
|
|
376
|
+
paths.insert(paths.end(), incs.begin(), incs.end());
|
|
377
|
+
// dispatch to find files in paths
|
|
378
|
+
return find_files(file, paths);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// helper function to search one file in all include paths
|
|
382
|
+
// this is normally not used internally by libsass (C-API sugar)
|
|
340
383
|
std::string find_file(const std::string& file, const std::vector<std::string> paths)
|
|
384
|
+
{
|
|
385
|
+
if (file.empty()) return file;
|
|
386
|
+
auto res = find_files(file, paths);
|
|
387
|
+
return res.empty() ? "" : res.front();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// helper function to resolve a filename
|
|
391
|
+
std::string find_include(const std::string& file, const std::vector<std::string> paths)
|
|
341
392
|
{
|
|
342
393
|
// search in every include path for a match
|
|
343
394
|
for (size_t i = 0, S = paths.size(); i < S; ++i)
|
|
@@ -349,20 +400,6 @@ namespace Sass {
|
|
|
349
400
|
return std::string("");
|
|
350
401
|
}
|
|
351
402
|
|
|
352
|
-
// inc paths can be directly passed from C code
|
|
353
|
-
std::string find_file(const std::string& file, const char* paths[])
|
|
354
|
-
{
|
|
355
|
-
if (paths == 0) return std::string("");
|
|
356
|
-
std::vector<std::string> includes(0);
|
|
357
|
-
// includes.push_back(".");
|
|
358
|
-
const char** it = paths;
|
|
359
|
-
while (it && *it) {
|
|
360
|
-
includes.push_back(*it);
|
|
361
|
-
++it;
|
|
362
|
-
}
|
|
363
|
-
return find_file(file, includes);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
403
|
// try to load the given filename
|
|
367
404
|
// returned memory must be freed
|
|
368
405
|
// will auto convert .sass files
|
|
@@ -371,16 +408,24 @@ namespace Sass {
|
|
|
371
408
|
#ifdef _WIN32
|
|
372
409
|
BYTE* pBuffer;
|
|
373
410
|
DWORD dwBytes;
|
|
411
|
+
wchar_t resolved[32768];
|
|
374
412
|
// windows unicode filepaths are encoded in utf16
|
|
375
|
-
std::
|
|
376
|
-
|
|
413
|
+
std::string abspath(join_paths(get_cwd(), path));
|
|
414
|
+
std::wstring wpath(UTF_8::convert_to_utf16("\\\\?\\" + abspath));
|
|
415
|
+
std::replace(wpath.begin(), wpath.end(), '/', '\\');
|
|
416
|
+
DWORD rv = GetFullPathNameW(wpath.c_str(), 32767, resolved, NULL);
|
|
417
|
+
if (rv > 32767) throw Exception::OperationError("Path is too long");
|
|
418
|
+
if (rv == 0) throw Exception::OperationError("Path could not be resolved");
|
|
419
|
+
HANDLE hFile = CreateFileW(resolved, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
|
377
420
|
if (hFile == INVALID_HANDLE_VALUE) return 0;
|
|
378
421
|
DWORD dwFileLength = GetFileSize(hFile, NULL);
|
|
379
422
|
if (dwFileLength == INVALID_FILE_SIZE) return 0;
|
|
380
423
|
// allocate an extra byte for the null char
|
|
381
|
-
|
|
424
|
+
// and another one for edge-cases in lexer
|
|
425
|
+
pBuffer = (BYTE*)malloc((dwFileLength+2)*sizeof(BYTE));
|
|
382
426
|
ReadFile(hFile, pBuffer, dwFileLength, &dwBytes, NULL);
|
|
383
|
-
pBuffer[dwFileLength] = '\0';
|
|
427
|
+
pBuffer[dwFileLength+0] = '\0';
|
|
428
|
+
pBuffer[dwFileLength+1] = '\0';
|
|
384
429
|
CloseHandle(hFile);
|
|
385
430
|
// just convert from unsigned char*
|
|
386
431
|
char* contents = (char*) pBuffer;
|
|
@@ -392,10 +437,12 @@ namespace Sass {
|
|
|
392
437
|
if (file.is_open()) {
|
|
393
438
|
size_t size = file.tellg();
|
|
394
439
|
// allocate an extra byte for the null char
|
|
395
|
-
|
|
440
|
+
// and another one for edge-cases in lexer
|
|
441
|
+
contents = (char*) malloc((size+2)*sizeof(char));
|
|
396
442
|
file.seekg(0, std::ios::beg);
|
|
397
443
|
file.read(contents, size);
|
|
398
|
-
contents[size] = '\0';
|
|
444
|
+
contents[size+0] = '\0';
|
|
445
|
+
contents[size+1] = '\0';
|
|
399
446
|
file.close();
|
|
400
447
|
}
|
|
401
448
|
#endif
|
|
@@ -414,5 +461,25 @@ namespace Sass {
|
|
|
414
461
|
}
|
|
415
462
|
}
|
|
416
463
|
|
|
464
|
+
// split a path string delimited by semicolons or colons (OS dependent)
|
|
465
|
+
std::vector<std::string> split_path_list(const char* str)
|
|
466
|
+
{
|
|
467
|
+
std::vector<std::string> paths;
|
|
468
|
+
if (str == NULL) return paths;
|
|
469
|
+
// find delimiter via prelexer (return zero at end)
|
|
470
|
+
const char* end = Prelexer::find_first<PATH_SEP>(str);
|
|
471
|
+
// search until null delimiter
|
|
472
|
+
while (end) {
|
|
473
|
+
// add path from current position to delimiter
|
|
474
|
+
paths.push_back(std::string(str, end - str));
|
|
475
|
+
str = end + 1; // skip delimiter
|
|
476
|
+
end = Prelexer::find_first<PATH_SEP>(str);
|
|
477
|
+
}
|
|
478
|
+
// add path from current position to end
|
|
479
|
+
paths.push_back(std::string(str));
|
|
480
|
+
// return back
|
|
481
|
+
return paths;
|
|
482
|
+
}
|
|
483
|
+
|
|
417
484
|
}
|
|
418
485
|
}
|
data/ext/libsass/src/file.hpp
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include <string>
|
|
5
5
|
#include <vector>
|
|
6
6
|
|
|
7
|
+
#include "sass/context.h"
|
|
7
8
|
#include "ast_fwd_decl.hpp"
|
|
8
9
|
|
|
9
10
|
namespace Sass {
|
|
@@ -47,9 +48,16 @@ namespace Sass {
|
|
|
47
48
|
std::string abs2rel(const std::string& path, const std::string& base = ".", const std::string& cwd = get_cwd());
|
|
48
49
|
|
|
49
50
|
// helper function to resolve a filename
|
|
51
|
+
// searching without variations in all paths
|
|
52
|
+
std::string find_file(const std::string& file, struct Sass_Compiler* options);
|
|
50
53
|
std::string find_file(const std::string& file, const std::vector<std::string> paths);
|
|
51
|
-
|
|
52
|
-
|
|
54
|
+
|
|
55
|
+
// helper function to resolve a include filename
|
|
56
|
+
// this has the original resolve logic for sass include
|
|
57
|
+
std::string find_include(const std::string& file, const std::vector<std::string> paths);
|
|
58
|
+
|
|
59
|
+
// split a path string delimited by semicolons or colons (OS dependent)
|
|
60
|
+
std::vector<std::string> split_path_list(const char* paths);
|
|
53
61
|
|
|
54
62
|
// try to load the given filename
|
|
55
63
|
// returned memory must be freed
|
|
@@ -81,9 +89,14 @@ namespace Sass {
|
|
|
81
89
|
public:
|
|
82
90
|
// resolved absolute path
|
|
83
91
|
std::string abs_path;
|
|
92
|
+
// is a deprecated file type
|
|
93
|
+
bool deprecated;
|
|
84
94
|
public:
|
|
95
|
+
Include(const Importer& imp, std::string abs_path, bool deprecated)
|
|
96
|
+
: Importer(imp), abs_path(abs_path), deprecated(deprecated)
|
|
97
|
+
{ }
|
|
85
98
|
Include(const Importer& imp, std::string abs_path)
|
|
86
|
-
: Importer(imp), abs_path(abs_path)
|
|
99
|
+
: Importer(imp), abs_path(abs_path), deprecated(false)
|
|
87
100
|
{ }
|
|
88
101
|
};
|
|
89
102
|
|
|
@@ -113,7 +126,11 @@ namespace Sass {
|
|
|
113
126
|
|
|
114
127
|
namespace File {
|
|
115
128
|
|
|
116
|
-
std::vector<
|
|
129
|
+
static std::vector<std::string> defaultExtensions = { ".scss", ".sass" };
|
|
130
|
+
|
|
131
|
+
std::vector<Include> resolve_includes(const std::string& root, const std::string& file,
|
|
132
|
+
const std::vector<std::string>& exts = defaultExtensions);
|
|
133
|
+
|
|
117
134
|
|
|
118
135
|
}
|
|
119
136
|
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#include "eval.hpp"
|
|
11
11
|
#include "util.hpp"
|
|
12
12
|
#include "expand.hpp"
|
|
13
|
+
#include "operators.hpp"
|
|
13
14
|
#include "utf8_string.hpp"
|
|
14
15
|
#include "sass/base.h"
|
|
15
16
|
#include "utf8.h"
|
|
@@ -30,9 +31,26 @@
|
|
|
30
31
|
#include "wincrypt.h"
|
|
31
32
|
#endif
|
|
32
33
|
|
|
33
|
-
#define ARG(argname, argtype) get_arg<argtype>(argname, env, sig, pstate,
|
|
34
|
-
#define
|
|
35
|
-
|
|
34
|
+
#define ARG(argname, argtype) get_arg<argtype>(argname, env, sig, pstate, traces)
|
|
35
|
+
#define ARGM(argname, argtype, ctx) get_arg_m(argname, env, sig, pstate, traces, ctx)
|
|
36
|
+
|
|
37
|
+
// return a number object (copied since we want to have reduced units)
|
|
38
|
+
#define ARGN(argname) get_arg_n(argname, env, sig, pstate, traces) // Number copy
|
|
39
|
+
|
|
40
|
+
// special function for weird hsla percent (10px == 10% == 10 != 0.1)
|
|
41
|
+
#define ARGVAL(argname) get_arg_val(argname, env, sig, pstate, traces) // double
|
|
42
|
+
|
|
43
|
+
// macros for common ranges (u mean unsigned or upper, r for full range)
|
|
44
|
+
#define DARG_U_FACT(argname) get_arg_r(argname, env, sig, pstate, traces, - 0.0, 1.0) // double
|
|
45
|
+
#define DARG_R_FACT(argname) get_arg_r(argname, env, sig, pstate, traces, - 1.0, 1.0) // double
|
|
46
|
+
#define DARG_U_BYTE(argname) get_arg_r(argname, env, sig, pstate, traces, - 0.0, 255.0) // double
|
|
47
|
+
#define DARG_R_BYTE(argname) get_arg_r(argname, env, sig, pstate, traces, - 255.0, 255.0) // double
|
|
48
|
+
#define DARG_U_PRCT(argname) get_arg_r(argname, env, sig, pstate, traces, - 0.0, 100.0) // double
|
|
49
|
+
#define DARG_R_PRCT(argname) get_arg_r(argname, env, sig, pstate, traces, - 100.0, 100.0) // double
|
|
50
|
+
|
|
51
|
+
// macros for color related inputs (rbg and alpha/opacity values)
|
|
52
|
+
#define COLOR_NUM(argname) color_num(argname, env, sig, pstate, traces) // double
|
|
53
|
+
#define ALPHA_NUM(argname) alpha_num(argname, env, sig, pstate, traces) // double
|
|
36
54
|
|
|
37
55
|
namespace Sass {
|
|
38
56
|
using std::stringstream;
|
|
@@ -40,7 +58,7 @@ namespace Sass {
|
|
|
40
58
|
|
|
41
59
|
Definition_Ptr make_native_function(Signature sig, Native_Function func, Context& ctx)
|
|
42
60
|
{
|
|
43
|
-
Parser sig_parser = Parser::from_c_str(sig, ctx, ParserState("[built-in function]"));
|
|
61
|
+
Parser sig_parser = Parser::from_c_str(sig, ctx, ctx.traces, ParserState("[built-in function]"));
|
|
44
62
|
sig_parser.lex<Prelexer::identifier>();
|
|
45
63
|
std::string name(Util::normalize_underscores(sig_parser.lexed));
|
|
46
64
|
Parameters_Obj params = sig_parser.parse_parameters();
|
|
@@ -58,7 +76,7 @@ namespace Sass {
|
|
|
58
76
|
using namespace Prelexer;
|
|
59
77
|
|
|
60
78
|
const char* sig = sass_function_get_signature(c_func);
|
|
61
|
-
Parser sig_parser = Parser::from_c_str(sig, ctx, ParserState("[c function]"));
|
|
79
|
+
Parser sig_parser = Parser::from_c_str(sig, ctx, ctx.traces, ParserState("[c function]"));
|
|
62
80
|
// allow to overload generic callback plus @warn, @error and @debug with custom functions
|
|
63
81
|
sig_parser.lex < alternatives < identifier, exactly <'*'>,
|
|
64
82
|
exactly < Constants::warn_kwd >,
|
|
@@ -84,31 +102,31 @@ namespace Sass {
|
|
|
84
102
|
|
|
85
103
|
namespace Functions {
|
|
86
104
|
|
|
87
|
-
inline void handle_utf8_error (const ParserState& pstate,
|
|
105
|
+
inline void handle_utf8_error (const ParserState& pstate, Backtraces traces)
|
|
88
106
|
{
|
|
89
107
|
try {
|
|
90
108
|
throw;
|
|
91
109
|
}
|
|
92
110
|
catch (utf8::invalid_code_point) {
|
|
93
111
|
std::string msg("utf8::invalid_code_point");
|
|
94
|
-
error(msg, pstate,
|
|
112
|
+
error(msg, pstate, traces);
|
|
95
113
|
}
|
|
96
114
|
catch (utf8::not_enough_room) {
|
|
97
115
|
std::string msg("utf8::not_enough_room");
|
|
98
|
-
error(msg, pstate,
|
|
116
|
+
error(msg, pstate, traces);
|
|
99
117
|
}
|
|
100
118
|
catch (utf8::invalid_utf8) {
|
|
101
119
|
std::string msg("utf8::invalid_utf8");
|
|
102
|
-
error(msg, pstate,
|
|
120
|
+
error(msg, pstate, traces);
|
|
103
121
|
}
|
|
104
122
|
catch (...) { throw; }
|
|
105
123
|
}
|
|
106
124
|
|
|
107
125
|
template <typename T>
|
|
108
|
-
T* get_arg(const std::string& argname, Env& env, Signature sig, ParserState pstate,
|
|
126
|
+
T* get_arg(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
|
|
109
127
|
{
|
|
110
128
|
// Minimal error handling -- the expectation is that built-ins will be written correctly!
|
|
111
|
-
T* val =
|
|
129
|
+
T* val = Cast<T>(env[argname]);
|
|
112
130
|
if (!val) {
|
|
113
131
|
std::string msg("argument `");
|
|
114
132
|
msg += argname;
|
|
@@ -116,74 +134,138 @@ namespace Sass {
|
|
|
116
134
|
msg += sig;
|
|
117
135
|
msg += "` must be a ";
|
|
118
136
|
msg += T::type_name();
|
|
119
|
-
error(msg, pstate,
|
|
137
|
+
error(msg, pstate, traces);
|
|
120
138
|
}
|
|
121
139
|
return val;
|
|
122
140
|
}
|
|
123
141
|
|
|
124
|
-
Map_Ptr get_arg_m(const std::string& argname, Env& env, Signature sig, ParserState pstate,
|
|
142
|
+
Map_Ptr get_arg_m(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx)
|
|
125
143
|
{
|
|
126
144
|
// Minimal error handling -- the expectation is that built-ins will be written correctly!
|
|
127
|
-
Map_Ptr val =
|
|
145
|
+
Map_Ptr val = Cast<Map>(env[argname]);
|
|
128
146
|
if (val) return val;
|
|
129
147
|
|
|
130
|
-
List_Ptr lval =
|
|
148
|
+
List_Ptr lval = Cast<List>(env[argname]);
|
|
131
149
|
if (lval && lval->length() == 0) return SASS_MEMORY_NEW(Map, pstate, 0);
|
|
132
150
|
|
|
133
151
|
// fallback on get_arg for error handling
|
|
134
|
-
val = get_arg<Map>(argname, env, sig, pstate,
|
|
152
|
+
val = get_arg<Map>(argname, env, sig, pstate, traces);
|
|
135
153
|
return val;
|
|
136
154
|
}
|
|
137
155
|
|
|
138
|
-
|
|
156
|
+
double get_arg_r(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, double lo, double hi)
|
|
139
157
|
{
|
|
140
158
|
// Minimal error handling -- the expectation is that built-ins will be written correctly!
|
|
141
|
-
Number_Ptr val = get_arg<Number>(argname, env, sig, pstate,
|
|
142
|
-
|
|
159
|
+
Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
|
|
160
|
+
Number tmpnr(val);
|
|
161
|
+
tmpnr.reduce();
|
|
162
|
+
double v = tmpnr.value();
|
|
143
163
|
if (!(lo <= v && v <= hi)) {
|
|
144
164
|
std::stringstream msg;
|
|
145
165
|
msg << "argument `" << argname << "` of `" << sig << "` must be between ";
|
|
146
166
|
msg << lo << " and " << hi;
|
|
147
|
-
error(msg.str(), pstate,
|
|
167
|
+
error(msg.str(), pstate, traces);
|
|
148
168
|
}
|
|
169
|
+
return v;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
Number_Ptr get_arg_n(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
|
|
173
|
+
{
|
|
174
|
+
// Minimal error handling -- the expectation is that built-ins will be written correctly!
|
|
175
|
+
Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
|
|
176
|
+
val = SASS_MEMORY_COPY(val);
|
|
177
|
+
val->reduce();
|
|
149
178
|
return val;
|
|
150
179
|
}
|
|
151
180
|
|
|
152
|
-
|
|
181
|
+
double get_arg_v(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
|
|
182
|
+
{
|
|
183
|
+
// Minimal error handling -- the expectation is that built-ins will be written correctly!
|
|
184
|
+
Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
|
|
185
|
+
Number tmpnr(val);
|
|
186
|
+
tmpnr.reduce();
|
|
187
|
+
/*
|
|
188
|
+
if (tmpnr.unit() == "%") {
|
|
189
|
+
tmpnr.value(tmpnr.value() / 100);
|
|
190
|
+
tmpnr.numerators.clear();
|
|
191
|
+
} else {
|
|
192
|
+
if (!tmpnr.is_unitless()) error("argument " + argname + " of `" + std::string(sig) + "` must be unitless", pstate);
|
|
193
|
+
}
|
|
194
|
+
*/
|
|
195
|
+
return tmpnr.value();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
double get_arg_val(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
|
|
199
|
+
{
|
|
200
|
+
// Minimal error handling -- the expectation is that built-ins will be written correctly!
|
|
201
|
+
Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
|
|
202
|
+
Number tmpnr(val);
|
|
203
|
+
tmpnr.reduce();
|
|
204
|
+
return tmpnr.value();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
double color_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
|
|
208
|
+
{
|
|
209
|
+
Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
|
|
210
|
+
Number tmpnr(val);
|
|
211
|
+
tmpnr.reduce();
|
|
212
|
+
if (tmpnr.unit() == "%") {
|
|
213
|
+
return std::min(std::max(tmpnr.value() * 255 / 100.0, 0.0), 255.0);
|
|
214
|
+
} else {
|
|
215
|
+
return std::min(std::max(tmpnr.value(), 0.0), 255.0);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
inline double alpha_num(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces) {
|
|
221
|
+
Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
|
|
222
|
+
Number tmpnr(val);
|
|
223
|
+
tmpnr.reduce();
|
|
224
|
+
if (tmpnr.unit() == "%") {
|
|
225
|
+
return std::min(std::max(tmpnr.value(), 0.0), 100.0);
|
|
226
|
+
} else {
|
|
227
|
+
return std::min(std::max(tmpnr.value(), 0.0), 1.0);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
#define ARGSEL(argname, seltype, contextualize) get_arg_sel<seltype>(argname, env, sig, pstate, traces, ctx)
|
|
153
232
|
|
|
154
233
|
template <typename T>
|
|
155
|
-
T get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate,
|
|
234
|
+
T get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx);
|
|
156
235
|
|
|
157
236
|
template <>
|
|
158
|
-
Selector_List_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate,
|
|
237
|
+
Selector_List_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) {
|
|
159
238
|
Expression_Obj exp = ARG(argname, Expression);
|
|
160
239
|
if (exp->concrete_type() == Expression::NULL_VAL) {
|
|
161
240
|
std::stringstream msg;
|
|
162
241
|
msg << argname << ": null is not a valid selector: it must be a string,\n";
|
|
163
242
|
msg << "a list of strings, or a list of lists of strings for `" << function_name(sig) << "'";
|
|
164
|
-
error(msg.str(), pstate);
|
|
243
|
+
error(msg.str(), pstate, traces);
|
|
165
244
|
}
|
|
166
|
-
if (String_Constant_Ptr str =
|
|
245
|
+
if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
|
|
167
246
|
str->quote_mark(0);
|
|
168
247
|
}
|
|
169
|
-
std::string exp_src = exp->to_string(ctx.c_options)
|
|
170
|
-
return Parser::parse_selector(exp_src.c_str(), ctx);
|
|
248
|
+
std::string exp_src = exp->to_string(ctx.c_options);
|
|
249
|
+
return Parser::parse_selector(exp_src.c_str(), ctx, traces);
|
|
171
250
|
}
|
|
172
251
|
|
|
173
252
|
template <>
|
|
174
|
-
Compound_Selector_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate,
|
|
253
|
+
Compound_Selector_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) {
|
|
175
254
|
Expression_Obj exp = ARG(argname, Expression);
|
|
176
255
|
if (exp->concrete_type() == Expression::NULL_VAL) {
|
|
177
256
|
std::stringstream msg;
|
|
178
257
|
msg << argname << ": null is not a string for `" << function_name(sig) << "'";
|
|
179
|
-
error(msg.str(), pstate);
|
|
258
|
+
error(msg.str(), pstate, traces);
|
|
180
259
|
}
|
|
181
|
-
if (String_Constant_Ptr str =
|
|
260
|
+
if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
|
|
182
261
|
str->quote_mark(0);
|
|
183
262
|
}
|
|
184
|
-
std::string exp_src = exp->to_string(ctx.c_options)
|
|
185
|
-
Selector_List_Obj sel_list = Parser::parse_selector(exp_src.c_str(), ctx);
|
|
186
|
-
|
|
263
|
+
std::string exp_src = exp->to_string(ctx.c_options);
|
|
264
|
+
Selector_List_Obj sel_list = Parser::parse_selector(exp_src.c_str(), ctx, traces);
|
|
265
|
+
if (sel_list->length() == 0) return NULL;
|
|
266
|
+
Complex_Selector_Obj first = sel_list->first();
|
|
267
|
+
if (!first->tail()) return first->head();
|
|
268
|
+
return first->tail()->head();
|
|
187
269
|
}
|
|
188
270
|
|
|
189
271
|
#ifdef __MINGW32__
|
|
@@ -219,56 +301,110 @@ namespace Sass {
|
|
|
219
301
|
"global-variable-shadowing",
|
|
220
302
|
"extend-selector-pseudoclass",
|
|
221
303
|
"at-error",
|
|
222
|
-
"units-level-3"
|
|
304
|
+
"units-level-3",
|
|
305
|
+
"custom-property"
|
|
223
306
|
};
|
|
224
307
|
|
|
225
308
|
////////////////
|
|
226
309
|
// RGB FUNCTIONS
|
|
227
310
|
////////////////
|
|
228
311
|
|
|
229
|
-
inline
|
|
230
|
-
if (
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
inline double alpha_num(Number_Ptr n) {
|
|
238
|
-
if (n->unit() == "%") {
|
|
239
|
-
return std::min(std::max(n->value(), 0.0), 100.0);
|
|
240
|
-
} else {
|
|
241
|
-
return std::min(std::max(n->value(), 0.0), 1.0);
|
|
312
|
+
inline bool special_number(String_Constant_Ptr s) {
|
|
313
|
+
if (s) {
|
|
314
|
+
std::string calc("calc(");
|
|
315
|
+
std::string var("var(");
|
|
316
|
+
std::string ss(s->value());
|
|
317
|
+
return std::equal(calc.begin(), calc.end(), ss.begin()) ||
|
|
318
|
+
std::equal(var.begin(), var.end(), ss.begin());
|
|
242
319
|
}
|
|
320
|
+
return false;
|
|
243
321
|
}
|
|
244
322
|
|
|
245
323
|
Signature rgb_sig = "rgb($red, $green, $blue)";
|
|
246
324
|
BUILT_IN(rgb)
|
|
247
325
|
{
|
|
326
|
+
if (
|
|
327
|
+
special_number(Cast<String_Constant>(env["$red"])) ||
|
|
328
|
+
special_number(Cast<String_Constant>(env["$green"])) ||
|
|
329
|
+
special_number(Cast<String_Constant>(env["$blue"]))
|
|
330
|
+
) {
|
|
331
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, "rgb("
|
|
332
|
+
+ env["$red"]->to_string()
|
|
333
|
+
+ ", "
|
|
334
|
+
+ env["$green"]->to_string()
|
|
335
|
+
+ ", "
|
|
336
|
+
+ env["$blue"]->to_string()
|
|
337
|
+
+ ")"
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
|
|
248
341
|
return SASS_MEMORY_NEW(Color,
|
|
249
342
|
pstate,
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
343
|
+
COLOR_NUM("$red"),
|
|
344
|
+
COLOR_NUM("$green"),
|
|
345
|
+
COLOR_NUM("$blue"));
|
|
253
346
|
}
|
|
254
347
|
|
|
255
348
|
Signature rgba_4_sig = "rgba($red, $green, $blue, $alpha)";
|
|
256
349
|
BUILT_IN(rgba_4)
|
|
257
350
|
{
|
|
351
|
+
if (
|
|
352
|
+
special_number(Cast<String_Constant>(env["$red"])) ||
|
|
353
|
+
special_number(Cast<String_Constant>(env["$green"])) ||
|
|
354
|
+
special_number(Cast<String_Constant>(env["$blue"])) ||
|
|
355
|
+
special_number(Cast<String_Constant>(env["$alpha"]))
|
|
356
|
+
) {
|
|
357
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, "rgba("
|
|
358
|
+
+ env["$red"]->to_string()
|
|
359
|
+
+ ", "
|
|
360
|
+
+ env["$green"]->to_string()
|
|
361
|
+
+ ", "
|
|
362
|
+
+ env["$blue"]->to_string()
|
|
363
|
+
+ ", "
|
|
364
|
+
+ env["$alpha"]->to_string()
|
|
365
|
+
+ ")"
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
|
|
258
369
|
return SASS_MEMORY_NEW(Color,
|
|
259
370
|
pstate,
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
371
|
+
COLOR_NUM("$red"),
|
|
372
|
+
COLOR_NUM("$green"),
|
|
373
|
+
COLOR_NUM("$blue"),
|
|
374
|
+
ALPHA_NUM("$alpha"));
|
|
264
375
|
}
|
|
265
376
|
|
|
266
377
|
Signature rgba_2_sig = "rgba($color, $alpha)";
|
|
267
378
|
BUILT_IN(rgba_2)
|
|
268
379
|
{
|
|
380
|
+
if (
|
|
381
|
+
special_number(Cast<String_Constant>(env["$color"]))
|
|
382
|
+
) {
|
|
383
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, "rgba("
|
|
384
|
+
+ env["$color"]->to_string()
|
|
385
|
+
+ ", "
|
|
386
|
+
+ env["$alpha"]->to_string()
|
|
387
|
+
+ ")"
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
269
391
|
Color_Ptr c_arg = ARG("$color", Color);
|
|
392
|
+
|
|
393
|
+
if (
|
|
394
|
+
special_number(Cast<String_Constant>(env["$alpha"]))
|
|
395
|
+
) {
|
|
396
|
+
std::stringstream strm;
|
|
397
|
+
strm << "rgba("
|
|
398
|
+
<< (int)c_arg->r() << ", "
|
|
399
|
+
<< (int)c_arg->g() << ", "
|
|
400
|
+
<< (int)c_arg->b() << ", "
|
|
401
|
+
<< env["$alpha"]->to_string()
|
|
402
|
+
<< ")";
|
|
403
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, strm.str());
|
|
404
|
+
}
|
|
405
|
+
|
|
270
406
|
Color_Ptr new_c = SASS_MEMORY_COPY(c_arg);
|
|
271
|
-
new_c->a(
|
|
407
|
+
new_c->a(ALPHA_NUM("$alpha"));
|
|
272
408
|
new_c->disp("");
|
|
273
409
|
return new_c;
|
|
274
410
|
}
|
|
@@ -285,14 +421,8 @@ namespace Sass {
|
|
|
285
421
|
BUILT_IN(blue)
|
|
286
422
|
{ return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->b()); }
|
|
287
423
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
{
|
|
291
|
-
Color_Ptr color1 = ARG("$color-1", Color);
|
|
292
|
-
Color_Ptr color2 = ARG("$color-2", Color);
|
|
293
|
-
Number_Ptr weight = ARGR("$weight", Number, 0, 100);
|
|
294
|
-
|
|
295
|
-
double p = weight->value()/100;
|
|
424
|
+
Color* colormix(Context& ctx, ParserState& pstate, Color* color1, Color* color2, double weight) {
|
|
425
|
+
double p = weight/100;
|
|
296
426
|
double w = 2*p - 1;
|
|
297
427
|
double a = color1->a() - color2->a();
|
|
298
428
|
|
|
@@ -307,6 +437,16 @@ namespace Sass {
|
|
|
307
437
|
color1->a()*p + color2->a()*(1-p));
|
|
308
438
|
}
|
|
309
439
|
|
|
440
|
+
Signature mix_sig = "mix($color-1, $color-2, $weight: 50%)";
|
|
441
|
+
BUILT_IN(mix)
|
|
442
|
+
{
|
|
443
|
+
Color_Obj color1 = ARG("$color-1", Color);
|
|
444
|
+
Color_Obj color2 = ARG("$color-2", Color);
|
|
445
|
+
double weight = DARG_U_PRCT("$weight");
|
|
446
|
+
return colormix(ctx, pstate, color1, color2, weight);
|
|
447
|
+
|
|
448
|
+
}
|
|
449
|
+
|
|
310
450
|
////////////////
|
|
311
451
|
// HSL FUNCTIONS
|
|
312
452
|
////////////////
|
|
@@ -323,9 +463,11 @@ namespace Sass {
|
|
|
323
463
|
double min = std::min(r, std::min(g, b));
|
|
324
464
|
double delta = max - min;
|
|
325
465
|
|
|
326
|
-
double h = 0
|
|
466
|
+
double h = 0;
|
|
467
|
+
double s;
|
|
468
|
+
double l = (max + min) / 2.0;
|
|
327
469
|
|
|
328
|
-
if (max
|
|
470
|
+
if (NEAR_EQUAL(max, min)) {
|
|
329
471
|
h = s = 0; // achromatic
|
|
330
472
|
}
|
|
331
473
|
else {
|
|
@@ -390,9 +532,24 @@ namespace Sass {
|
|
|
390
532
|
Signature hsl_sig = "hsl($hue, $saturation, $lightness)";
|
|
391
533
|
BUILT_IN(hsl)
|
|
392
534
|
{
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
535
|
+
if (
|
|
536
|
+
special_number(Cast<String_Constant>(env["$hue"])) ||
|
|
537
|
+
special_number(Cast<String_Constant>(env["$saturation"])) ||
|
|
538
|
+
special_number(Cast<String_Constant>(env["$lightness"]))
|
|
539
|
+
) {
|
|
540
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, "hsl("
|
|
541
|
+
+ env["$hue"]->to_string()
|
|
542
|
+
+ ", "
|
|
543
|
+
+ env["$saturation"]->to_string()
|
|
544
|
+
+ ", "
|
|
545
|
+
+ env["$lightness"]->to_string()
|
|
546
|
+
+ ")"
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
return hsla_impl(ARGVAL("$hue"),
|
|
551
|
+
ARGVAL("$saturation"),
|
|
552
|
+
ARGVAL("$lightness"),
|
|
396
553
|
1.0,
|
|
397
554
|
ctx,
|
|
398
555
|
pstate);
|
|
@@ -401,10 +558,28 @@ namespace Sass {
|
|
|
401
558
|
Signature hsla_sig = "hsla($hue, $saturation, $lightness, $alpha)";
|
|
402
559
|
BUILT_IN(hsla)
|
|
403
560
|
{
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
561
|
+
if (
|
|
562
|
+
special_number(Cast<String_Constant>(env["$hue"])) ||
|
|
563
|
+
special_number(Cast<String_Constant>(env["$saturation"])) ||
|
|
564
|
+
special_number(Cast<String_Constant>(env["$lightness"])) ||
|
|
565
|
+
special_number(Cast<String_Constant>(env["$alpha"]))
|
|
566
|
+
) {
|
|
567
|
+
return SASS_MEMORY_NEW(String_Constant, pstate, "hsla("
|
|
568
|
+
+ env["$hue"]->to_string()
|
|
569
|
+
+ ", "
|
|
570
|
+
+ env["$saturation"]->to_string()
|
|
571
|
+
+ ", "
|
|
572
|
+
+ env["$lightness"]->to_string()
|
|
573
|
+
+ ", "
|
|
574
|
+
+ env["$alpha"]->to_string()
|
|
575
|
+
+ ")"
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
return hsla_impl(ARGVAL("$hue"),
|
|
580
|
+
ARGVAL("$saturation"),
|
|
581
|
+
ARGVAL("$lightness"),
|
|
582
|
+
ARGVAL("$alpha"),
|
|
408
583
|
ctx,
|
|
409
584
|
pstate);
|
|
410
585
|
}
|
|
@@ -443,11 +618,11 @@ namespace Sass {
|
|
|
443
618
|
BUILT_IN(adjust_hue)
|
|
444
619
|
{
|
|
445
620
|
Color_Ptr rgb_color = ARG("$color", Color);
|
|
446
|
-
|
|
621
|
+
double degrees = ARGVAL("$degrees");
|
|
447
622
|
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
|
448
623
|
rgb_color->g(),
|
|
449
624
|
rgb_color->b());
|
|
450
|
-
return hsla_impl(hsl_color.h + degrees
|
|
625
|
+
return hsla_impl(hsl_color.h + degrees,
|
|
451
626
|
hsl_color.s,
|
|
452
627
|
hsl_color.l,
|
|
453
628
|
rgb_color->a(),
|
|
@@ -459,7 +634,7 @@ namespace Sass {
|
|
|
459
634
|
BUILT_IN(lighten)
|
|
460
635
|
{
|
|
461
636
|
Color_Ptr rgb_color = ARG("$color", Color);
|
|
462
|
-
|
|
637
|
+
double amount = DARG_U_PRCT("$amount");
|
|
463
638
|
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
|
464
639
|
rgb_color->g(),
|
|
465
640
|
rgb_color->b());
|
|
@@ -471,7 +646,7 @@ namespace Sass {
|
|
|
471
646
|
|
|
472
647
|
return hsla_impl(hsl_color.h,
|
|
473
648
|
hsl_color.s,
|
|
474
|
-
hslcolorL + amount
|
|
649
|
+
hslcolorL + amount,
|
|
475
650
|
rgb_color->a(),
|
|
476
651
|
ctx,
|
|
477
652
|
pstate);
|
|
@@ -481,7 +656,7 @@ namespace Sass {
|
|
|
481
656
|
BUILT_IN(darken)
|
|
482
657
|
{
|
|
483
658
|
Color_Ptr rgb_color = ARG("$color", Color);
|
|
484
|
-
|
|
659
|
+
double amount = DARG_U_PRCT("$amount");
|
|
485
660
|
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
|
486
661
|
rgb_color->g(),
|
|
487
662
|
rgb_color->b());
|
|
@@ -494,7 +669,7 @@ namespace Sass {
|
|
|
494
669
|
|
|
495
670
|
return hsla_impl(hsl_color.h,
|
|
496
671
|
hsl_color.s,
|
|
497
|
-
hslcolorL - amount
|
|
672
|
+
hslcolorL - amount,
|
|
498
673
|
rgb_color->a(),
|
|
499
674
|
ctx,
|
|
500
675
|
pstate);
|
|
@@ -504,18 +679,17 @@ namespace Sass {
|
|
|
504
679
|
BUILT_IN(saturate)
|
|
505
680
|
{
|
|
506
681
|
// CSS3 filter function overload: pass literal through directly
|
|
507
|
-
|
|
508
|
-
if (!amount) {
|
|
682
|
+
if (!Cast<Number>(env["$amount"])) {
|
|
509
683
|
return SASS_MEMORY_NEW(String_Quoted, pstate, "saturate(" + env["$color"]->to_string(ctx.c_options) + ")");
|
|
510
684
|
}
|
|
511
685
|
|
|
512
|
-
|
|
686
|
+
double amount = DARG_U_PRCT("$amount");
|
|
513
687
|
Color_Ptr rgb_color = ARG("$color", Color);
|
|
514
688
|
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
|
515
689
|
rgb_color->g(),
|
|
516
690
|
rgb_color->b());
|
|
517
691
|
|
|
518
|
-
double hslcolorS = hsl_color.s + amount
|
|
692
|
+
double hslcolorS = hsl_color.s + amount;
|
|
519
693
|
|
|
520
694
|
// Saturation cannot be below 0 or above 100
|
|
521
695
|
if (hslcolorS < 0) {
|
|
@@ -537,12 +711,12 @@ namespace Sass {
|
|
|
537
711
|
BUILT_IN(desaturate)
|
|
538
712
|
{
|
|
539
713
|
Color_Ptr rgb_color = ARG("$color", Color);
|
|
540
|
-
|
|
714
|
+
double amount = DARG_U_PRCT("$amount");
|
|
541
715
|
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
|
542
716
|
rgb_color->g(),
|
|
543
717
|
rgb_color->b());
|
|
544
718
|
|
|
545
|
-
double hslcolorS = hsl_color.s - amount
|
|
719
|
+
double hslcolorS = hsl_color.s - amount;
|
|
546
720
|
|
|
547
721
|
// Saturation cannot be below 0 or above 100
|
|
548
722
|
if (hslcolorS <= 0) {
|
|
@@ -564,7 +738,7 @@ namespace Sass {
|
|
|
564
738
|
BUILT_IN(grayscale)
|
|
565
739
|
{
|
|
566
740
|
// CSS3 filter function overload: pass literal through directly
|
|
567
|
-
Number_Ptr amount =
|
|
741
|
+
Number_Ptr amount = Cast<Number>(env["$color"]);
|
|
568
742
|
if (amount) {
|
|
569
743
|
return SASS_MEMORY_NEW(String_Quoted, pstate, "grayscale(" + amount->to_string(ctx.c_options) + ")");
|
|
570
744
|
}
|
|
@@ -596,22 +770,24 @@ namespace Sass {
|
|
|
596
770
|
pstate);
|
|
597
771
|
}
|
|
598
772
|
|
|
599
|
-
Signature invert_sig = "invert($color)";
|
|
773
|
+
Signature invert_sig = "invert($color, $weight: 100%)";
|
|
600
774
|
BUILT_IN(invert)
|
|
601
775
|
{
|
|
602
776
|
// CSS3 filter function overload: pass literal through directly
|
|
603
|
-
Number_Ptr amount =
|
|
777
|
+
Number_Ptr amount = Cast<Number>(env["$color"]);
|
|
604
778
|
if (amount) {
|
|
605
779
|
return SASS_MEMORY_NEW(String_Quoted, pstate, "invert(" + amount->to_string(ctx.c_options) + ")");
|
|
606
780
|
}
|
|
607
781
|
|
|
782
|
+
double weight = DARG_U_PRCT("$weight");
|
|
608
783
|
Color_Ptr rgb_color = ARG("$color", Color);
|
|
609
|
-
|
|
784
|
+
Color_Obj inv = SASS_MEMORY_NEW(Color,
|
|
610
785
|
pstate,
|
|
611
786
|
255 - rgb_color->r(),
|
|
612
787
|
255 - rgb_color->g(),
|
|
613
788
|
255 - rgb_color->b(),
|
|
614
789
|
rgb_color->a());
|
|
790
|
+
return colormix(ctx, pstate, inv, rgb_color, weight);
|
|
615
791
|
}
|
|
616
792
|
|
|
617
793
|
////////////////////
|
|
@@ -621,13 +797,13 @@ namespace Sass {
|
|
|
621
797
|
Signature opacity_sig = "opacity($color)";
|
|
622
798
|
BUILT_IN(alpha)
|
|
623
799
|
{
|
|
624
|
-
String_Constant_Ptr ie_kwd =
|
|
800
|
+
String_Constant_Ptr ie_kwd = Cast<String_Constant>(env["$color"]);
|
|
625
801
|
if (ie_kwd) {
|
|
626
802
|
return SASS_MEMORY_NEW(String_Quoted, pstate, "alpha(" + ie_kwd->value() + ")");
|
|
627
803
|
}
|
|
628
804
|
|
|
629
805
|
// CSS3 filter function overload: pass literal through directly
|
|
630
|
-
Number_Ptr amount =
|
|
806
|
+
Number_Ptr amount = Cast<Number>(env["$color"]);
|
|
631
807
|
if (amount) {
|
|
632
808
|
return SASS_MEMORY_NEW(String_Quoted, pstate, "opacity(" + amount->to_string(ctx.c_options) + ")");
|
|
633
809
|
}
|
|
@@ -640,7 +816,7 @@ namespace Sass {
|
|
|
640
816
|
BUILT_IN(opacify)
|
|
641
817
|
{
|
|
642
818
|
Color_Ptr color = ARG("$color", Color);
|
|
643
|
-
double amount =
|
|
819
|
+
double amount = DARG_U_FACT("$amount");
|
|
644
820
|
double alpha = std::min(color->a() + amount, 1.0);
|
|
645
821
|
return SASS_MEMORY_NEW(Color,
|
|
646
822
|
pstate,
|
|
@@ -655,7 +831,7 @@ namespace Sass {
|
|
|
655
831
|
BUILT_IN(transparentize)
|
|
656
832
|
{
|
|
657
833
|
Color_Ptr color = ARG("$color", Color);
|
|
658
|
-
double amount =
|
|
834
|
+
double amount = DARG_U_FACT("$amount");
|
|
659
835
|
double alpha = std::max(color->a() - amount, 0.0);
|
|
660
836
|
return SASS_MEMORY_NEW(Color,
|
|
661
837
|
pstate,
|
|
@@ -673,25 +849,25 @@ namespace Sass {
|
|
|
673
849
|
BUILT_IN(adjust_color)
|
|
674
850
|
{
|
|
675
851
|
Color_Ptr color = ARG("$color", Color);
|
|
676
|
-
Number_Ptr r =
|
|
677
|
-
Number_Ptr g =
|
|
678
|
-
Number_Ptr b =
|
|
679
|
-
Number_Ptr h =
|
|
680
|
-
Number_Ptr s =
|
|
681
|
-
Number_Ptr l =
|
|
682
|
-
Number_Ptr a =
|
|
852
|
+
Number_Ptr r = Cast<Number>(env["$red"]);
|
|
853
|
+
Number_Ptr g = Cast<Number>(env["$green"]);
|
|
854
|
+
Number_Ptr b = Cast<Number>(env["$blue"]);
|
|
855
|
+
Number_Ptr h = Cast<Number>(env["$hue"]);
|
|
856
|
+
Number_Ptr s = Cast<Number>(env["$saturation"]);
|
|
857
|
+
Number_Ptr l = Cast<Number>(env["$lightness"]);
|
|
858
|
+
Number_Ptr a = Cast<Number>(env["$alpha"]);
|
|
683
859
|
|
|
684
860
|
bool rgb = r || g || b;
|
|
685
861
|
bool hsl = h || s || l;
|
|
686
862
|
|
|
687
863
|
if (rgb && hsl) {
|
|
688
|
-
error("Cannot specify HSL and RGB values for a color at the same time for `adjust-color'", pstate);
|
|
864
|
+
error("Cannot specify HSL and RGB values for a color at the same time for `adjust-color'", pstate, traces);
|
|
689
865
|
}
|
|
690
866
|
if (rgb) {
|
|
691
|
-
double rr = r ?
|
|
692
|
-
double gg = g ?
|
|
693
|
-
double bb = b ?
|
|
694
|
-
double aa = a ?
|
|
867
|
+
double rr = r ? DARG_R_BYTE("$red") : 0;
|
|
868
|
+
double gg = g ? DARG_R_BYTE("$green") : 0;
|
|
869
|
+
double bb = b ? DARG_R_BYTE("$blue") : 0;
|
|
870
|
+
double aa = a ? DARG_R_FACT("$alpha") : 0;
|
|
695
871
|
return SASS_MEMORY_NEW(Color,
|
|
696
872
|
pstate,
|
|
697
873
|
color->r() + rr,
|
|
@@ -701,9 +877,9 @@ namespace Sass {
|
|
|
701
877
|
}
|
|
702
878
|
if (hsl) {
|
|
703
879
|
HSL hsl_struct = rgb_to_hsl(color->r(), color->g(), color->b());
|
|
704
|
-
double ss = s ?
|
|
705
|
-
double ll = l ?
|
|
706
|
-
double aa = a ?
|
|
880
|
+
double ss = s ? DARG_R_PRCT("$saturation") : 0;
|
|
881
|
+
double ll = l ? DARG_R_PRCT("$lightness") : 0;
|
|
882
|
+
double aa = a ? DARG_R_FACT("$alpha") : 0;
|
|
707
883
|
return hsla_impl(hsl_struct.h + (h ? h->value() : 0),
|
|
708
884
|
hsl_struct.s + ss,
|
|
709
885
|
hsl_struct.l + ll,
|
|
@@ -719,7 +895,7 @@ namespace Sass {
|
|
|
719
895
|
color->b(),
|
|
720
896
|
color->a() + (a ? a->value() : 0));
|
|
721
897
|
}
|
|
722
|
-
error("not enough arguments for `adjust-color'", pstate);
|
|
898
|
+
error("not enough arguments for `adjust-color'", pstate, traces);
|
|
723
899
|
// unreachable
|
|
724
900
|
return color;
|
|
725
901
|
}
|
|
@@ -728,25 +904,25 @@ namespace Sass {
|
|
|
728
904
|
BUILT_IN(scale_color)
|
|
729
905
|
{
|
|
730
906
|
Color_Ptr color = ARG("$color", Color);
|
|
731
|
-
Number_Ptr r =
|
|
732
|
-
Number_Ptr g =
|
|
733
|
-
Number_Ptr b =
|
|
734
|
-
Number_Ptr h =
|
|
735
|
-
Number_Ptr s =
|
|
736
|
-
Number_Ptr l =
|
|
737
|
-
Number_Ptr a =
|
|
907
|
+
Number_Ptr r = Cast<Number>(env["$red"]);
|
|
908
|
+
Number_Ptr g = Cast<Number>(env["$green"]);
|
|
909
|
+
Number_Ptr b = Cast<Number>(env["$blue"]);
|
|
910
|
+
Number_Ptr h = Cast<Number>(env["$hue"]);
|
|
911
|
+
Number_Ptr s = Cast<Number>(env["$saturation"]);
|
|
912
|
+
Number_Ptr l = Cast<Number>(env["$lightness"]);
|
|
913
|
+
Number_Ptr a = Cast<Number>(env["$alpha"]);
|
|
738
914
|
|
|
739
915
|
bool rgb = r || g || b;
|
|
740
916
|
bool hsl = h || s || l;
|
|
741
917
|
|
|
742
918
|
if (rgb && hsl) {
|
|
743
|
-
error("Cannot specify HSL and RGB values for a color at the same time for `scale-color'", pstate);
|
|
919
|
+
error("Cannot specify HSL and RGB values for a color at the same time for `scale-color'", pstate, traces);
|
|
744
920
|
}
|
|
745
921
|
if (rgb) {
|
|
746
|
-
double rscale = (r ?
|
|
747
|
-
double gscale = (g ?
|
|
748
|
-
double bscale = (b ?
|
|
749
|
-
double ascale = (a ?
|
|
922
|
+
double rscale = (r ? DARG_R_PRCT("$red") : 0.0) / 100.0;
|
|
923
|
+
double gscale = (g ? DARG_R_PRCT("$green") : 0.0) / 100.0;
|
|
924
|
+
double bscale = (b ? DARG_R_PRCT("$blue") : 0.0) / 100.0;
|
|
925
|
+
double ascale = (a ? DARG_R_PRCT("$alpha") : 0.0) / 100.0;
|
|
750
926
|
return SASS_MEMORY_NEW(Color,
|
|
751
927
|
pstate,
|
|
752
928
|
color->r() + rscale * (rscale > 0.0 ? 255 - color->r() : color->r()),
|
|
@@ -755,10 +931,10 @@ namespace Sass {
|
|
|
755
931
|
color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->a()));
|
|
756
932
|
}
|
|
757
933
|
if (hsl) {
|
|
758
|
-
double hscale = (h ?
|
|
759
|
-
double sscale = (s ?
|
|
760
|
-
double lscale = (l ?
|
|
761
|
-
double ascale = (a ?
|
|
934
|
+
double hscale = (h ? DARG_R_PRCT("$hue") : 0.0) / 100.0;
|
|
935
|
+
double sscale = (s ? DARG_R_PRCT("$saturation") : 0.0) / 100.0;
|
|
936
|
+
double lscale = (l ? DARG_R_PRCT("$lightness") : 0.0) / 100.0;
|
|
937
|
+
double ascale = (a ? DARG_R_PRCT("$alpha") : 0.0) / 100.0;
|
|
762
938
|
HSL hsl_struct = rgb_to_hsl(color->r(), color->g(), color->b());
|
|
763
939
|
hsl_struct.h += hscale * (hscale > 0.0 ? 360.0 - hsl_struct.h : hsl_struct.h);
|
|
764
940
|
hsl_struct.s += sscale * (sscale > 0.0 ? 100.0 - hsl_struct.s : hsl_struct.s);
|
|
@@ -767,7 +943,7 @@ namespace Sass {
|
|
|
767
943
|
return hsla_impl(hsl_struct.h, hsl_struct.s, hsl_struct.l, alpha, ctx, pstate);
|
|
768
944
|
}
|
|
769
945
|
if (a) {
|
|
770
|
-
double ascale = (
|
|
946
|
+
double ascale = (DARG_R_PRCT("$alpha")) / 100.0;
|
|
771
947
|
return SASS_MEMORY_NEW(Color,
|
|
772
948
|
pstate,
|
|
773
949
|
color->r(),
|
|
@@ -775,7 +951,7 @@ namespace Sass {
|
|
|
775
951
|
color->b(),
|
|
776
952
|
color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->a()));
|
|
777
953
|
}
|
|
778
|
-
error("not enough arguments for `scale-color'", pstate);
|
|
954
|
+
error("not enough arguments for `scale-color'", pstate, traces);
|
|
779
955
|
// unreachable
|
|
780
956
|
return color;
|
|
781
957
|
}
|
|
@@ -784,38 +960,38 @@ namespace Sass {
|
|
|
784
960
|
BUILT_IN(change_color)
|
|
785
961
|
{
|
|
786
962
|
Color_Ptr color = ARG("$color", Color);
|
|
787
|
-
Number_Ptr r =
|
|
788
|
-
Number_Ptr g =
|
|
789
|
-
Number_Ptr b =
|
|
790
|
-
Number_Ptr h =
|
|
791
|
-
Number_Ptr s =
|
|
792
|
-
Number_Ptr l =
|
|
793
|
-
Number_Ptr a =
|
|
963
|
+
Number_Ptr r = Cast<Number>(env["$red"]);
|
|
964
|
+
Number_Ptr g = Cast<Number>(env["$green"]);
|
|
965
|
+
Number_Ptr b = Cast<Number>(env["$blue"]);
|
|
966
|
+
Number_Ptr h = Cast<Number>(env["$hue"]);
|
|
967
|
+
Number_Ptr s = Cast<Number>(env["$saturation"]);
|
|
968
|
+
Number_Ptr l = Cast<Number>(env["$lightness"]);
|
|
969
|
+
Number_Ptr a = Cast<Number>(env["$alpha"]);
|
|
794
970
|
|
|
795
971
|
bool rgb = r || g || b;
|
|
796
972
|
bool hsl = h || s || l;
|
|
797
973
|
|
|
798
974
|
if (rgb && hsl) {
|
|
799
|
-
error("Cannot specify HSL and RGB values for a color at the same time for `change-color'", pstate);
|
|
975
|
+
error("Cannot specify HSL and RGB values for a color at the same time for `change-color'", pstate, traces);
|
|
800
976
|
}
|
|
801
977
|
if (rgb) {
|
|
802
978
|
return SASS_MEMORY_NEW(Color,
|
|
803
979
|
pstate,
|
|
804
|
-
r ?
|
|
805
|
-
g ?
|
|
806
|
-
b ?
|
|
807
|
-
a ?
|
|
980
|
+
r ? DARG_U_BYTE("$red") : color->r(),
|
|
981
|
+
g ? DARG_U_BYTE("$green") : color->g(),
|
|
982
|
+
b ? DARG_U_BYTE("$blue") : color->b(),
|
|
983
|
+
a ? DARG_U_BYTE("$alpha") : color->a());
|
|
808
984
|
}
|
|
809
985
|
if (hsl) {
|
|
810
986
|
HSL hsl_struct = rgb_to_hsl(color->r(), color->g(), color->b());
|
|
811
987
|
if (h) hsl_struct.h = std::fmod(h->value(), 360.0);
|
|
812
|
-
if (s) hsl_struct.s =
|
|
813
|
-
if (l) hsl_struct.l =
|
|
814
|
-
double alpha = a ?
|
|
988
|
+
if (s) hsl_struct.s = DARG_U_PRCT("$saturation");
|
|
989
|
+
if (l) hsl_struct.l = DARG_U_PRCT("$lightness");
|
|
990
|
+
double alpha = a ? DARG_U_FACT("$alpha") : color->a();
|
|
815
991
|
return hsla_impl(hsl_struct.h, hsl_struct.s, hsl_struct.l, alpha, ctx, pstate);
|
|
816
992
|
}
|
|
817
993
|
if (a) {
|
|
818
|
-
double alpha =
|
|
994
|
+
double alpha = DARG_U_FACT("$alpha");
|
|
819
995
|
return SASS_MEMORY_NEW(Color,
|
|
820
996
|
pstate,
|
|
821
997
|
color->r(),
|
|
@@ -823,7 +999,7 @@ namespace Sass {
|
|
|
823
999
|
color->b(),
|
|
824
1000
|
alpha);
|
|
825
1001
|
}
|
|
826
|
-
error("not enough arguments for `change-color'", pstate);
|
|
1002
|
+
error("not enough arguments for `change-color'", pstate, traces);
|
|
827
1003
|
// unreachable
|
|
828
1004
|
return color;
|
|
829
1005
|
}
|
|
@@ -866,25 +1042,26 @@ namespace Sass {
|
|
|
866
1042
|
BUILT_IN(sass_unquote)
|
|
867
1043
|
{
|
|
868
1044
|
AST_Node_Obj arg = env["$string"];
|
|
869
|
-
if (String_Quoted_Ptr string_quoted =
|
|
1045
|
+
if (String_Quoted_Ptr string_quoted = Cast<String_Quoted>(arg)) {
|
|
870
1046
|
String_Constant_Ptr result = SASS_MEMORY_NEW(String_Constant, pstate, string_quoted->value());
|
|
871
1047
|
// remember if the string was quoted (color tokens)
|
|
872
1048
|
result->is_delayed(true); // delay colors
|
|
873
1049
|
return result;
|
|
874
1050
|
}
|
|
875
|
-
else if (
|
|
876
|
-
return
|
|
1051
|
+
else if (String_Constant_Ptr str = Cast<String_Constant>(arg)) {
|
|
1052
|
+
return str;
|
|
877
1053
|
}
|
|
878
|
-
else {
|
|
1054
|
+
else if (Expression_Ptr ex = Cast<Expression>(arg)) {
|
|
879
1055
|
Sass_Output_Style oldstyle = ctx.c_options.output_style;
|
|
880
1056
|
ctx.c_options.output_style = SASS_STYLE_NESTED;
|
|
881
1057
|
std::string val(arg->to_string(ctx.c_options));
|
|
882
|
-
val =
|
|
1058
|
+
val = Cast<Null>(arg) ? "null" : val;
|
|
883
1059
|
ctx.c_options.output_style = oldstyle;
|
|
884
1060
|
|
|
885
1061
|
deprecated_function("Passing " + val + ", a non-string value, to unquote()", pstate);
|
|
886
|
-
return
|
|
1062
|
+
return ex;
|
|
887
1063
|
}
|
|
1064
|
+
throw std::runtime_error("Invalid Data Type for unquote");
|
|
888
1065
|
}
|
|
889
1066
|
|
|
890
1067
|
Signature quote_sig = "quote($string)";
|
|
@@ -892,7 +1069,7 @@ namespace Sass {
|
|
|
892
1069
|
{
|
|
893
1070
|
AST_Node_Obj arg = env["$string"];
|
|
894
1071
|
// only set quote mark to true if already a string
|
|
895
|
-
if (String_Quoted_Ptr qstr =
|
|
1072
|
+
if (String_Quoted_Ptr qstr = Cast<String_Quoted>(arg)) {
|
|
896
1073
|
qstr->quote_mark('*');
|
|
897
1074
|
return qstr;
|
|
898
1075
|
}
|
|
@@ -915,7 +1092,7 @@ namespace Sass {
|
|
|
915
1092
|
}
|
|
916
1093
|
// handle any invalid utf8 errors
|
|
917
1094
|
// other errors will be re-thrown
|
|
918
|
-
catch (...) { handle_utf8_error(pstate,
|
|
1095
|
+
catch (...) { handle_utf8_error(pstate, traces); }
|
|
919
1096
|
// return something even if we had an error (-1)
|
|
920
1097
|
return SASS_MEMORY_NEW(Number, pstate, (double)len);
|
|
921
1098
|
}
|
|
@@ -931,8 +1108,7 @@ namespace Sass {
|
|
|
931
1108
|
String_Constant_Ptr i = ARG("$insert", String_Constant);
|
|
932
1109
|
std::string ins = i->value();
|
|
933
1110
|
ins = unquote(ins);
|
|
934
|
-
|
|
935
|
-
double index = ind->value();
|
|
1111
|
+
double index = ARGVAL("$index");
|
|
936
1112
|
size_t len = UTF_8::code_point_count(str, 0, str.size());
|
|
937
1113
|
|
|
938
1114
|
if (index > 0 && index <= len) {
|
|
@@ -956,13 +1132,13 @@ namespace Sass {
|
|
|
956
1132
|
str = ins + str;
|
|
957
1133
|
}
|
|
958
1134
|
|
|
959
|
-
if (String_Quoted_Ptr ss =
|
|
1135
|
+
if (String_Quoted_Ptr ss = Cast<String_Quoted>(s)) {
|
|
960
1136
|
if (ss->quote_mark()) str = quote(str);
|
|
961
1137
|
}
|
|
962
1138
|
}
|
|
963
1139
|
// handle any invalid utf8 errors
|
|
964
1140
|
// other errors will be re-thrown
|
|
965
|
-
catch (...) { handle_utf8_error(pstate,
|
|
1141
|
+
catch (...) { handle_utf8_error(pstate, traces); }
|
|
966
1142
|
return SASS_MEMORY_NEW(String_Quoted, pstate, str);
|
|
967
1143
|
}
|
|
968
1144
|
|
|
@@ -986,7 +1162,7 @@ namespace Sass {
|
|
|
986
1162
|
}
|
|
987
1163
|
// handle any invalid utf8 errors
|
|
988
1164
|
// other errors will be re-thrown
|
|
989
|
-
catch (...) { handle_utf8_error(pstate,
|
|
1165
|
+
catch (...) { handle_utf8_error(pstate, traces); }
|
|
990
1166
|
// return something even if we had an error (-1)
|
|
991
1167
|
return SASS_MEMORY_NEW(Number, pstate, (double)index);
|
|
992
1168
|
}
|
|
@@ -997,15 +1173,15 @@ namespace Sass {
|
|
|
997
1173
|
std::string newstr;
|
|
998
1174
|
try {
|
|
999
1175
|
String_Constant_Ptr s = ARG("$string", String_Constant);
|
|
1000
|
-
double start_at =
|
|
1001
|
-
double end_at =
|
|
1002
|
-
String_Quoted_Ptr ss =
|
|
1176
|
+
double start_at = ARGVAL("$start-at");
|
|
1177
|
+
double end_at = ARGVAL("$end-at");
|
|
1178
|
+
String_Quoted_Ptr ss = Cast<String_Quoted>(s);
|
|
1003
1179
|
|
|
1004
1180
|
std::string str = unquote(s->value());
|
|
1005
1181
|
|
|
1006
1182
|
size_t size = utf8::distance(str.begin(), str.end());
|
|
1007
1183
|
|
|
1008
|
-
if (!
|
|
1184
|
+
if (!Cast<Number>(env["$end-at"])) {
|
|
1009
1185
|
end_at = -1;
|
|
1010
1186
|
}
|
|
1011
1187
|
|
|
@@ -1039,7 +1215,7 @@ namespace Sass {
|
|
|
1039
1215
|
}
|
|
1040
1216
|
// handle any invalid utf8 errors
|
|
1041
1217
|
// other errors will be re-thrown
|
|
1042
|
-
catch (...) { handle_utf8_error(pstate,
|
|
1218
|
+
catch (...) { handle_utf8_error(pstate, traces); }
|
|
1043
1219
|
return SASS_MEMORY_NEW(String_Quoted, pstate, newstr);
|
|
1044
1220
|
}
|
|
1045
1221
|
|
|
@@ -1055,7 +1231,7 @@ namespace Sass {
|
|
|
1055
1231
|
}
|
|
1056
1232
|
}
|
|
1057
1233
|
|
|
1058
|
-
if (String_Quoted_Ptr ss =
|
|
1234
|
+
if (String_Quoted_Ptr ss = Cast<String_Quoted>(s)) {
|
|
1059
1235
|
String_Quoted_Ptr cpy = SASS_MEMORY_COPY(ss);
|
|
1060
1236
|
cpy->value(str);
|
|
1061
1237
|
return cpy;
|
|
@@ -1076,7 +1252,7 @@ namespace Sass {
|
|
|
1076
1252
|
}
|
|
1077
1253
|
}
|
|
1078
1254
|
|
|
1079
|
-
if (String_Quoted_Ptr ss =
|
|
1255
|
+
if (String_Quoted_Ptr ss = Cast<String_Quoted>(s)) {
|
|
1080
1256
|
String_Quoted_Ptr cpy = SASS_MEMORY_COPY(ss);
|
|
1081
1257
|
cpy->value(str);
|
|
1082
1258
|
return cpy;
|
|
@@ -1092,49 +1268,45 @@ namespace Sass {
|
|
|
1092
1268
|
Signature percentage_sig = "percentage($number)";
|
|
1093
1269
|
BUILT_IN(percentage)
|
|
1094
1270
|
{
|
|
1095
|
-
|
|
1096
|
-
if (!n->is_unitless()) error("argument $number of `" + std::string(sig) + "` must be unitless", pstate);
|
|
1271
|
+
Number_Obj n = ARGN("$number");
|
|
1272
|
+
if (!n->is_unitless()) error("argument $number of `" + std::string(sig) + "` must be unitless", pstate, traces);
|
|
1097
1273
|
return SASS_MEMORY_NEW(Number, pstate, n->value() * 100, "%");
|
|
1098
1274
|
}
|
|
1099
1275
|
|
|
1100
1276
|
Signature round_sig = "round($number)";
|
|
1101
1277
|
BUILT_IN(round)
|
|
1102
1278
|
{
|
|
1103
|
-
|
|
1104
|
-
Number_Ptr r = SASS_MEMORY_COPY(n);
|
|
1105
|
-
r->pstate(pstate);
|
|
1279
|
+
Number_Obj r = ARGN("$number");
|
|
1106
1280
|
r->value(Sass::round(r->value(), ctx.c_options.precision));
|
|
1107
|
-
|
|
1281
|
+
r->pstate(pstate);
|
|
1282
|
+
return r.detach();
|
|
1108
1283
|
}
|
|
1109
1284
|
|
|
1110
1285
|
Signature ceil_sig = "ceil($number)";
|
|
1111
1286
|
BUILT_IN(ceil)
|
|
1112
1287
|
{
|
|
1113
|
-
|
|
1114
|
-
Number_Ptr r = SASS_MEMORY_COPY(n);
|
|
1115
|
-
r->pstate(pstate);
|
|
1288
|
+
Number_Obj r = ARGN("$number");
|
|
1116
1289
|
r->value(std::ceil(r->value()));
|
|
1117
|
-
|
|
1290
|
+
r->pstate(pstate);
|
|
1291
|
+
return r.detach();
|
|
1118
1292
|
}
|
|
1119
1293
|
|
|
1120
1294
|
Signature floor_sig = "floor($number)";
|
|
1121
1295
|
BUILT_IN(floor)
|
|
1122
1296
|
{
|
|
1123
|
-
|
|
1124
|
-
Number_Ptr r = SASS_MEMORY_COPY(n);
|
|
1125
|
-
r->pstate(pstate);
|
|
1297
|
+
Number_Obj r = ARGN("$number");
|
|
1126
1298
|
r->value(std::floor(r->value()));
|
|
1127
|
-
|
|
1299
|
+
r->pstate(pstate);
|
|
1300
|
+
return r.detach();
|
|
1128
1301
|
}
|
|
1129
1302
|
|
|
1130
1303
|
Signature abs_sig = "abs($number)";
|
|
1131
1304
|
BUILT_IN(abs)
|
|
1132
1305
|
{
|
|
1133
|
-
|
|
1134
|
-
Number_Ptr r = SASS_MEMORY_COPY(n);
|
|
1135
|
-
r->pstate(pstate);
|
|
1306
|
+
Number_Obj r = ARGN("$number");
|
|
1136
1307
|
r->value(std::abs(r->value()));
|
|
1137
|
-
|
|
1308
|
+
r->pstate(pstate);
|
|
1309
|
+
return r.detach();
|
|
1138
1310
|
}
|
|
1139
1311
|
|
|
1140
1312
|
Signature min_sig = "min($numbers...)";
|
|
@@ -1144,9 +1316,9 @@ namespace Sass {
|
|
|
1144
1316
|
Number_Obj least = NULL;
|
|
1145
1317
|
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
|
1146
1318
|
Expression_Obj val = arglist->value_at_index(i);
|
|
1147
|
-
Number_Obj xi =
|
|
1319
|
+
Number_Obj xi = Cast<Number>(val);
|
|
1148
1320
|
if (!xi) {
|
|
1149
|
-
error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `min'", pstate);
|
|
1321
|
+
error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `min'", pstate, traces);
|
|
1150
1322
|
}
|
|
1151
1323
|
if (least) {
|
|
1152
1324
|
if (*xi < *least) least = xi;
|
|
@@ -1162,9 +1334,9 @@ namespace Sass {
|
|
|
1162
1334
|
Number_Obj greatest = NULL;
|
|
1163
1335
|
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
|
1164
1336
|
Expression_Obj val = arglist->value_at_index(i);
|
|
1165
|
-
Number_Obj xi =
|
|
1337
|
+
Number_Obj xi = Cast<Number>(val);
|
|
1166
1338
|
if (!xi) {
|
|
1167
|
-
error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `max'", pstate);
|
|
1339
|
+
error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `max'", pstate, traces);
|
|
1168
1340
|
}
|
|
1169
1341
|
if (greatest) {
|
|
1170
1342
|
if (*greatest < *xi) greatest = xi;
|
|
@@ -1177,23 +1349,23 @@ namespace Sass {
|
|
|
1177
1349
|
BUILT_IN(random)
|
|
1178
1350
|
{
|
|
1179
1351
|
AST_Node_Obj arg = env["$limit"];
|
|
1180
|
-
Value_Ptr v =
|
|
1181
|
-
Number_Ptr l =
|
|
1182
|
-
Boolean_Ptr b =
|
|
1352
|
+
Value_Ptr v = Cast<Value>(arg);
|
|
1353
|
+
Number_Ptr l = Cast<Number>(arg);
|
|
1354
|
+
Boolean_Ptr b = Cast<Boolean>(arg);
|
|
1183
1355
|
if (l) {
|
|
1184
|
-
double
|
|
1185
|
-
if (
|
|
1356
|
+
double lv = l->value();
|
|
1357
|
+
if (lv < 1) {
|
|
1186
1358
|
stringstream err;
|
|
1187
|
-
err << "$limit " <<
|
|
1188
|
-
error(err.str(), pstate);
|
|
1359
|
+
err << "$limit " << lv << " must be greater than or equal to 1 for `random'";
|
|
1360
|
+
error(err.str(), pstate, traces);
|
|
1189
1361
|
}
|
|
1190
|
-
bool eq_int = std::fabs(trunc(
|
|
1362
|
+
bool eq_int = std::fabs(trunc(lv) - lv) < NUMBER_EPSILON;
|
|
1191
1363
|
if (!eq_int) {
|
|
1192
1364
|
stringstream err;
|
|
1193
|
-
err << "Expected $limit to be an integer but got " <<
|
|
1194
|
-
error(err.str(), pstate);
|
|
1365
|
+
err << "Expected $limit to be an integer but got " << lv << " for `random'";
|
|
1366
|
+
error(err.str(), pstate, traces);
|
|
1195
1367
|
}
|
|
1196
|
-
std::uniform_real_distribution<> distributor(1,
|
|
1368
|
+
std::uniform_real_distribution<> distributor(1, lv + 1);
|
|
1197
1369
|
uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
|
|
1198
1370
|
return SASS_MEMORY_NEW(Number, pstate, (double)distributed);
|
|
1199
1371
|
}
|
|
@@ -1202,11 +1374,12 @@ namespace Sass {
|
|
|
1202
1374
|
double distributed = static_cast<double>(distributor(rand));
|
|
1203
1375
|
return SASS_MEMORY_NEW(Number, pstate, distributed);
|
|
1204
1376
|
} else if (v) {
|
|
1205
|
-
|
|
1377
|
+
traces.push_back(Backtrace(pstate));
|
|
1378
|
+
throw Exception::InvalidArgumentType(pstate, traces, "random", "$limit", "number", v);
|
|
1206
1379
|
} else {
|
|
1207
|
-
|
|
1380
|
+
traces.push_back(Backtrace(pstate));
|
|
1381
|
+
throw Exception::InvalidArgumentType(pstate, traces, "random", "$limit", "number");
|
|
1208
1382
|
}
|
|
1209
|
-
return 0;
|
|
1210
1383
|
}
|
|
1211
1384
|
|
|
1212
1385
|
/////////////////
|
|
@@ -1216,25 +1389,25 @@ namespace Sass {
|
|
|
1216
1389
|
Signature length_sig = "length($list)";
|
|
1217
1390
|
BUILT_IN(length)
|
|
1218
1391
|
{
|
|
1219
|
-
if (Selector_List_Ptr sl =
|
|
1392
|
+
if (Selector_List_Ptr sl = Cast<Selector_List>(env["$list"])) {
|
|
1220
1393
|
return SASS_MEMORY_NEW(Number, pstate, (double)sl->length());
|
|
1221
1394
|
}
|
|
1222
1395
|
Expression_Ptr v = ARG("$list", Expression);
|
|
1223
1396
|
if (v->concrete_type() == Expression::MAP) {
|
|
1224
|
-
Map_Ptr map =
|
|
1397
|
+
Map_Ptr map = Cast<Map>(env["$list"]);
|
|
1225
1398
|
return SASS_MEMORY_NEW(Number, pstate, (double)(map ? map->length() : 1));
|
|
1226
1399
|
}
|
|
1227
1400
|
if (v->concrete_type() == Expression::SELECTOR) {
|
|
1228
|
-
if (Compound_Selector_Ptr h =
|
|
1401
|
+
if (Compound_Selector_Ptr h = Cast<Compound_Selector>(v)) {
|
|
1229
1402
|
return SASS_MEMORY_NEW(Number, pstate, (double)h->length());
|
|
1230
|
-
} else if (Selector_List_Ptr ls =
|
|
1403
|
+
} else if (Selector_List_Ptr ls = Cast<Selector_List>(v)) {
|
|
1231
1404
|
return SASS_MEMORY_NEW(Number, pstate, (double)ls->length());
|
|
1232
1405
|
} else {
|
|
1233
1406
|
return SASS_MEMORY_NEW(Number, pstate, 1);
|
|
1234
1407
|
}
|
|
1235
1408
|
}
|
|
1236
1409
|
|
|
1237
|
-
List_Ptr list =
|
|
1410
|
+
List_Ptr list = Cast<List>(env["$list"]);
|
|
1238
1411
|
return SASS_MEMORY_NEW(Number,
|
|
1239
1412
|
pstate,
|
|
1240
1413
|
(double)(list ? list->size() : 1));
|
|
@@ -1243,20 +1416,20 @@ namespace Sass {
|
|
|
1243
1416
|
Signature nth_sig = "nth($list, $n)";
|
|
1244
1417
|
BUILT_IN(nth)
|
|
1245
1418
|
{
|
|
1246
|
-
|
|
1247
|
-
Map_Ptr m =
|
|
1248
|
-
if (Selector_List_Ptr sl =
|
|
1419
|
+
double nr = ARGVAL("$n");
|
|
1420
|
+
Map_Ptr m = Cast<Map>(env["$list"]);
|
|
1421
|
+
if (Selector_List_Ptr sl = Cast<Selector_List>(env["$list"])) {
|
|
1249
1422
|
size_t len = m ? m->length() : sl->length();
|
|
1250
1423
|
bool empty = m ? m->empty() : sl->empty();
|
|
1251
|
-
if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate);
|
|
1252
|
-
double index = std::floor(
|
|
1253
|
-
if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate);
|
|
1424
|
+
if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces);
|
|
1425
|
+
double index = std::floor(nr < 0 ? len + nr : nr - 1);
|
|
1426
|
+
if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate, traces);
|
|
1254
1427
|
// return (*sl)[static_cast<int>(index)];
|
|
1255
1428
|
Listize listize;
|
|
1256
1429
|
return (*sl)[static_cast<int>(index)]->perform(&listize);
|
|
1257
1430
|
}
|
|
1258
|
-
List_Obj l =
|
|
1259
|
-
if (
|
|
1431
|
+
List_Obj l = Cast<List>(env["$list"]);
|
|
1432
|
+
if (nr == 0) error("argument `$n` of `" + std::string(sig) + "` must be non-zero", pstate, traces);
|
|
1260
1433
|
// if the argument isn't a list, then wrap it in a singleton list
|
|
1261
1434
|
if (!m && !l) {
|
|
1262
1435
|
l = SASS_MEMORY_NEW(List, pstate, 1);
|
|
@@ -1264,9 +1437,9 @@ namespace Sass {
|
|
|
1264
1437
|
}
|
|
1265
1438
|
size_t len = m ? m->length() : l->length();
|
|
1266
1439
|
bool empty = m ? m->empty() : l->empty();
|
|
1267
|
-
if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate);
|
|
1268
|
-
double index = std::floor(
|
|
1269
|
-
if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate);
|
|
1440
|
+
if (empty) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces);
|
|
1441
|
+
double index = std::floor(nr < 0 ? len + nr : nr - 1);
|
|
1442
|
+
if (index < 0 || index > len - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate, traces);
|
|
1270
1443
|
|
|
1271
1444
|
if (m) {
|
|
1272
1445
|
l = SASS_MEMORY_NEW(List, pstate, 1);
|
|
@@ -1284,8 +1457,8 @@ namespace Sass {
|
|
|
1284
1457
|
Signature set_nth_sig = "set-nth($list, $n, $value)";
|
|
1285
1458
|
BUILT_IN(set_nth)
|
|
1286
1459
|
{
|
|
1287
|
-
Map_Obj m =
|
|
1288
|
-
List_Obj l =
|
|
1460
|
+
Map_Obj m = Cast<Map>(env["$list"]);
|
|
1461
|
+
List_Obj l = Cast<List>(env["$list"]);
|
|
1289
1462
|
Number_Obj n = ARG("$n", Number);
|
|
1290
1463
|
Expression_Obj v = ARG("$value", Expression);
|
|
1291
1464
|
if (!l) {
|
|
@@ -1293,12 +1466,12 @@ namespace Sass {
|
|
|
1293
1466
|
l->append(ARG("$list", Expression));
|
|
1294
1467
|
}
|
|
1295
1468
|
if (m) {
|
|
1296
|
-
l = m->to_list(
|
|
1469
|
+
l = m->to_list(pstate);
|
|
1297
1470
|
}
|
|
1298
|
-
if (l->empty()) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate);
|
|
1471
|
+
if (l->empty()) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces);
|
|
1299
1472
|
double index = std::floor(n->value() < 0 ? l->length() + n->value() : n->value() - 1);
|
|
1300
|
-
if (index < 0 || index > l->length() - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate);
|
|
1301
|
-
List_Ptr result = SASS_MEMORY_NEW(List, pstate, l->length(), l->separator());
|
|
1473
|
+
if (index < 0 || index > l->length() - 1) error("index out of bounds for `" + std::string(sig) + "`", pstate, traces);
|
|
1474
|
+
List_Ptr result = SASS_MEMORY_NEW(List, pstate, l->length(), l->separator(), false, l->is_bracketed());
|
|
1302
1475
|
for (size_t i = 0, L = l->length(); i < L; ++i) {
|
|
1303
1476
|
result->append(((i == index) ? v : (*l)[i]));
|
|
1304
1477
|
}
|
|
@@ -1308,67 +1481,75 @@ namespace Sass {
|
|
|
1308
1481
|
Signature index_sig = "index($list, $value)";
|
|
1309
1482
|
BUILT_IN(index)
|
|
1310
1483
|
{
|
|
1311
|
-
Map_Obj m =
|
|
1312
|
-
List_Obj l =
|
|
1484
|
+
Map_Obj m = Cast<Map>(env["$list"]);
|
|
1485
|
+
List_Obj l = Cast<List>(env["$list"]);
|
|
1313
1486
|
Expression_Obj v = ARG("$value", Expression);
|
|
1314
1487
|
if (!l) {
|
|
1315
1488
|
l = SASS_MEMORY_NEW(List, pstate, 1);
|
|
1316
1489
|
l->append(ARG("$list", Expression));
|
|
1317
1490
|
}
|
|
1318
1491
|
if (m) {
|
|
1319
|
-
l = m->to_list(
|
|
1492
|
+
l = m->to_list(pstate);
|
|
1320
1493
|
}
|
|
1321
1494
|
for (size_t i = 0, L = l->length(); i < L; ++i) {
|
|
1322
|
-
if (
|
|
1495
|
+
if (Operators::eq(l->value_at_index(i), v)) return SASS_MEMORY_NEW(Number, pstate, (double)(i+1));
|
|
1323
1496
|
}
|
|
1324
1497
|
return SASS_MEMORY_NEW(Null, pstate);
|
|
1325
1498
|
}
|
|
1326
1499
|
|
|
1327
|
-
Signature join_sig = "join($list1, $list2, $separator: auto)";
|
|
1500
|
+
Signature join_sig = "join($list1, $list2, $separator: auto, $bracketed: auto)";
|
|
1328
1501
|
BUILT_IN(join)
|
|
1329
1502
|
{
|
|
1330
|
-
Map_Obj m1 =
|
|
1331
|
-
Map_Obj m2 =
|
|
1332
|
-
List_Obj l1 =
|
|
1333
|
-
List_Obj l2 =
|
|
1503
|
+
Map_Obj m1 = Cast<Map>(env["$list1"]);
|
|
1504
|
+
Map_Obj m2 = Cast<Map>(env["$list2"]);
|
|
1505
|
+
List_Obj l1 = Cast<List>(env["$list1"]);
|
|
1506
|
+
List_Obj l2 = Cast<List>(env["$list2"]);
|
|
1334
1507
|
String_Constant_Obj sep = ARG("$separator", String_Constant);
|
|
1335
1508
|
enum Sass_Separator sep_val = (l1 ? l1->separator() : SASS_SPACE);
|
|
1509
|
+
Value* bracketed = ARG("$bracketed", Value);
|
|
1510
|
+
bool is_bracketed = (l1 ? l1->is_bracketed() : false);
|
|
1336
1511
|
if (!l1) {
|
|
1337
1512
|
l1 = SASS_MEMORY_NEW(List, pstate, 1);
|
|
1338
1513
|
l1->append(ARG("$list1", Expression));
|
|
1339
1514
|
sep_val = (l2 ? l2->separator() : SASS_SPACE);
|
|
1515
|
+
is_bracketed = (l2 ? l2->is_bracketed() : false);
|
|
1340
1516
|
}
|
|
1341
1517
|
if (!l2) {
|
|
1342
1518
|
l2 = SASS_MEMORY_NEW(List, pstate, 1);
|
|
1343
1519
|
l2->append(ARG("$list2", Expression));
|
|
1344
1520
|
}
|
|
1345
1521
|
if (m1) {
|
|
1346
|
-
l1 = m1->to_list(
|
|
1522
|
+
l1 = m1->to_list(pstate);
|
|
1347
1523
|
sep_val = SASS_COMMA;
|
|
1348
1524
|
}
|
|
1349
1525
|
if (m2) {
|
|
1350
|
-
l2 = m2->to_list(
|
|
1526
|
+
l2 = m2->to_list(pstate);
|
|
1351
1527
|
}
|
|
1352
1528
|
size_t len = l1->length() + l2->length();
|
|
1353
1529
|
std::string sep_str = unquote(sep->value());
|
|
1354
1530
|
if (sep_str == "space") sep_val = SASS_SPACE;
|
|
1355
1531
|
else if (sep_str == "comma") sep_val = SASS_COMMA;
|
|
1356
|
-
else if (sep_str != "auto") error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate);
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1532
|
+
else if (sep_str != "auto") error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate, traces);
|
|
1533
|
+
String_Constant_Obj bracketed_as_str = Cast<String_Constant>(bracketed);
|
|
1534
|
+
bool bracketed_is_auto = bracketed_as_str && unquote(bracketed_as_str->value()) == "auto";
|
|
1535
|
+
if (!bracketed_is_auto) {
|
|
1536
|
+
is_bracketed = !bracketed->is_false();
|
|
1537
|
+
}
|
|
1538
|
+
List_Obj result = SASS_MEMORY_NEW(List, pstate, len, sep_val, false, is_bracketed);
|
|
1539
|
+
result->concat(l1);
|
|
1540
|
+
result->concat(l2);
|
|
1360
1541
|
return result.detach();
|
|
1361
1542
|
}
|
|
1362
1543
|
|
|
1363
1544
|
Signature append_sig = "append($list, $val, $separator: auto)";
|
|
1364
1545
|
BUILT_IN(append)
|
|
1365
1546
|
{
|
|
1366
|
-
Map_Obj m =
|
|
1367
|
-
List_Obj l =
|
|
1547
|
+
Map_Obj m = Cast<Map>(env["$list"]);
|
|
1548
|
+
List_Obj l = Cast<List>(env["$list"]);
|
|
1368
1549
|
Expression_Obj v = ARG("$val", Expression);
|
|
1369
|
-
if (Selector_List_Ptr sl =
|
|
1550
|
+
if (Selector_List_Ptr sl = Cast<Selector_List>(env["$list"])) {
|
|
1370
1551
|
Listize listize;
|
|
1371
|
-
l =
|
|
1552
|
+
l = Cast<List>(sl->perform(&listize));
|
|
1372
1553
|
}
|
|
1373
1554
|
String_Constant_Obj sep = ARG("$separator", String_Constant);
|
|
1374
1555
|
if (!l) {
|
|
@@ -1376,14 +1557,14 @@ namespace Sass {
|
|
|
1376
1557
|
l->append(ARG("$list", Expression));
|
|
1377
1558
|
}
|
|
1378
1559
|
if (m) {
|
|
1379
|
-
l = m->to_list(
|
|
1560
|
+
l = m->to_list(pstate);
|
|
1380
1561
|
}
|
|
1381
1562
|
List_Ptr result = SASS_MEMORY_COPY(l);
|
|
1382
1563
|
std::string sep_str(unquote(sep->value()));
|
|
1383
1564
|
if (sep_str != "auto") { // check default first
|
|
1384
1565
|
if (sep_str == "space") result->separator(SASS_SPACE);
|
|
1385
1566
|
else if (sep_str == "comma") result->separator(SASS_COMMA);
|
|
1386
|
-
else error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate);
|
|
1567
|
+
else error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate, traces);
|
|
1387
1568
|
}
|
|
1388
1569
|
if (l->is_arglist()) {
|
|
1389
1570
|
result->append(SASS_MEMORY_NEW(Argument,
|
|
@@ -1405,20 +1586,20 @@ namespace Sass {
|
|
|
1405
1586
|
List_Obj arglist = SASS_MEMORY_COPY(ARG("$lists", List));
|
|
1406
1587
|
size_t shortest = 0;
|
|
1407
1588
|
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
|
1408
|
-
List_Obj ith =
|
|
1409
|
-
Map_Obj mith =
|
|
1589
|
+
List_Obj ith = Cast<List>(arglist->value_at_index(i));
|
|
1590
|
+
Map_Obj mith = Cast<Map>(arglist->value_at_index(i));
|
|
1410
1591
|
if (!ith) {
|
|
1411
1592
|
if (mith) {
|
|
1412
|
-
ith = mith->to_list(
|
|
1593
|
+
ith = mith->to_list(pstate);
|
|
1413
1594
|
} else {
|
|
1414
1595
|
ith = SASS_MEMORY_NEW(List, pstate, 1);
|
|
1415
1596
|
ith->append(arglist->value_at_index(i));
|
|
1416
1597
|
}
|
|
1417
1598
|
if (arglist->is_arglist()) {
|
|
1418
|
-
Argument_Obj arg = (Argument_Ptr)(
|
|
1419
|
-
arg->value(
|
|
1599
|
+
Argument_Obj arg = (Argument_Ptr)(arglist->at(i).ptr()); // XXX
|
|
1600
|
+
arg->value(ith);
|
|
1420
1601
|
} else {
|
|
1421
|
-
(*arglist)[i] =
|
|
1602
|
+
(*arglist)[i] = ith;
|
|
1422
1603
|
}
|
|
1423
1604
|
}
|
|
1424
1605
|
shortest = (i ? std::min(shortest, ith->length()) : ith->length());
|
|
@@ -1428,7 +1609,7 @@ namespace Sass {
|
|
|
1428
1609
|
for (size_t i = 0; i < shortest; ++i) {
|
|
1429
1610
|
List_Ptr zipper = SASS_MEMORY_NEW(List, pstate, L);
|
|
1430
1611
|
for (size_t j = 0; j < L; ++j) {
|
|
1431
|
-
zipper->append(
|
|
1612
|
+
zipper->append(Cast<List>(arglist->value_at_index(j))->at(i));
|
|
1432
1613
|
}
|
|
1433
1614
|
zippers->append(zipper);
|
|
1434
1615
|
}
|
|
@@ -1438,7 +1619,7 @@ namespace Sass {
|
|
|
1438
1619
|
Signature list_separator_sig = "list_separator($list)";
|
|
1439
1620
|
BUILT_IN(list_separator)
|
|
1440
1621
|
{
|
|
1441
|
-
List_Obj l =
|
|
1622
|
+
List_Obj l = Cast<List>(env["$list"]);
|
|
1442
1623
|
if (!l) {
|
|
1443
1624
|
l = SASS_MEMORY_NEW(List, pstate, 1);
|
|
1444
1625
|
l->append(ARG("$list", Expression));
|
|
@@ -1460,8 +1641,10 @@ namespace Sass {
|
|
|
1460
1641
|
Map_Obj m = ARGM("$map", Map, ctx);
|
|
1461
1642
|
Expression_Obj v = ARG("$key", Expression);
|
|
1462
1643
|
try {
|
|
1463
|
-
Expression_Obj val = m->at(v);
|
|
1464
|
-
|
|
1644
|
+
Expression_Obj val = m->at(v);
|
|
1645
|
+
if (!val) return SASS_MEMORY_NEW(Null, pstate);
|
|
1646
|
+
val->set_delayed(false);
|
|
1647
|
+
return val.detach();
|
|
1465
1648
|
} catch (const std::out_of_range&) {
|
|
1466
1649
|
return SASS_MEMORY_NEW(Null, pstate);
|
|
1467
1650
|
}
|
|
@@ -1507,8 +1690,8 @@ namespace Sass {
|
|
|
1507
1690
|
size_t len = m1->length() + m2->length();
|
|
1508
1691
|
Map_Ptr result = SASS_MEMORY_NEW(Map, pstate, len);
|
|
1509
1692
|
// concat not implemented for maps
|
|
1510
|
-
*result +=
|
|
1511
|
-
*result +=
|
|
1693
|
+
*result += m1;
|
|
1694
|
+
*result += m2;
|
|
1512
1695
|
return result;
|
|
1513
1696
|
}
|
|
1514
1697
|
|
|
@@ -1522,7 +1705,7 @@ namespace Sass {
|
|
|
1522
1705
|
for (auto key : m->keys()) {
|
|
1523
1706
|
remove = false;
|
|
1524
1707
|
for (size_t j = 0, K = arglist->length(); j < K && !remove; ++j) {
|
|
1525
|
-
remove =
|
|
1708
|
+
remove = Operators::eq(key, arglist->value_at_index(j));
|
|
1526
1709
|
}
|
|
1527
1710
|
if (!remove) *result << std::make_pair(key, m->at(key));
|
|
1528
1711
|
}
|
|
@@ -1536,7 +1719,7 @@ namespace Sass {
|
|
|
1536
1719
|
Map_Obj result = SASS_MEMORY_NEW(Map, pstate, 1);
|
|
1537
1720
|
for (size_t i = arglist->size(), L = arglist->length(); i < L; ++i) {
|
|
1538
1721
|
Expression_Obj obj = arglist->at(i);
|
|
1539
|
-
Argument_Obj arg = (Argument_Ptr)
|
|
1722
|
+
Argument_Obj arg = (Argument_Ptr) obj.ptr(); // XXX
|
|
1540
1723
|
std::string name = std::string(arg->name());
|
|
1541
1724
|
name = name.erase(0, 1); // sanitize name (remove dollar sign)
|
|
1542
1725
|
*result << std::make_pair(SASS_MEMORY_NEW(String_Quoted,
|
|
@@ -1559,23 +1742,33 @@ namespace Sass {
|
|
|
1559
1742
|
|
|
1560
1743
|
Signature unit_sig = "unit($number)";
|
|
1561
1744
|
BUILT_IN(unit)
|
|
1562
|
-
{
|
|
1745
|
+
{
|
|
1746
|
+
Number_Obj arg = ARGN("$number");
|
|
1747
|
+
std::string str(quote(arg->unit(), '"'));
|
|
1748
|
+
return SASS_MEMORY_NEW(String_Quoted, pstate, str);
|
|
1749
|
+
}
|
|
1563
1750
|
|
|
1564
1751
|
Signature unitless_sig = "unitless($number)";
|
|
1565
1752
|
BUILT_IN(unitless)
|
|
1566
|
-
{
|
|
1753
|
+
{
|
|
1754
|
+
Number_Obj arg = ARGN("$number");
|
|
1755
|
+
bool unitless = arg->is_unitless();
|
|
1756
|
+
return SASS_MEMORY_NEW(Boolean, pstate, unitless);
|
|
1757
|
+
}
|
|
1567
1758
|
|
|
1568
1759
|
Signature comparable_sig = "comparable($number-1, $number-2)";
|
|
1569
1760
|
BUILT_IN(comparable)
|
|
1570
1761
|
{
|
|
1571
|
-
|
|
1572
|
-
|
|
1762
|
+
Number_Obj n1 = ARGN("$number-1");
|
|
1763
|
+
Number_Obj n2 = ARGN("$number-2");
|
|
1573
1764
|
if (n1->is_unitless() || n2->is_unitless()) {
|
|
1574
1765
|
return SASS_MEMORY_NEW(Boolean, pstate, true);
|
|
1575
1766
|
}
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1767
|
+
// normalize into main units
|
|
1768
|
+
n1->normalize(); n2->normalize();
|
|
1769
|
+
Units &lhs_unit = *n1, &rhs_unit = *n2;
|
|
1770
|
+
bool is_comparable = (lhs_unit == rhs_unit);
|
|
1771
|
+
return SASS_MEMORY_NEW(Boolean, pstate, is_comparable);
|
|
1579
1772
|
}
|
|
1580
1773
|
|
|
1581
1774
|
Signature variable_exists_sig = "variable-exists($name)";
|
|
@@ -1607,9 +1800,14 @@ namespace Sass {
|
|
|
1607
1800
|
Signature function_exists_sig = "function-exists($name)";
|
|
1608
1801
|
BUILT_IN(function_exists)
|
|
1609
1802
|
{
|
|
1610
|
-
|
|
1803
|
+
String_Constant_Ptr ss = Cast<String_Constant>(env["$name"]);
|
|
1804
|
+
if (!ss) {
|
|
1805
|
+
error("$name: " + (env["$name"]->to_string()) + " is not a string for `function-exists'", pstate, traces);
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
std::string name = Util::normalize_underscores(unquote(ss->value()));
|
|
1611
1809
|
|
|
1612
|
-
if(d_env.has_global(
|
|
1810
|
+
if(d_env.has_global(name+"[f]")) {
|
|
1613
1811
|
return SASS_MEMORY_NEW(Boolean, pstate, true);
|
|
1614
1812
|
}
|
|
1615
1813
|
else {
|
|
@@ -1646,24 +1844,37 @@ namespace Sass {
|
|
|
1646
1844
|
Signature call_sig = "call($name, $args...)";
|
|
1647
1845
|
BUILT_IN(call)
|
|
1648
1846
|
{
|
|
1649
|
-
std::string name
|
|
1847
|
+
std::string name;
|
|
1848
|
+
Function_Ptr ff = Cast<Function>(env["$name"]);
|
|
1849
|
+
String_Constant_Ptr ss = Cast<String_Constant>(env["$name"]);
|
|
1850
|
+
|
|
1851
|
+
if (ss) {
|
|
1852
|
+
name = Util::normalize_underscores(unquote(ss->value()));
|
|
1853
|
+
std::cerr << "DEPRECATION WARNING: ";
|
|
1854
|
+
std::cerr << "Passing a string to call() is deprecated and will be illegal" << std::endl;
|
|
1855
|
+
std::cerr << "in Sass 4.0. Use call(get-function(" + quote(name) + ")) instead." << std::endl;
|
|
1856
|
+
std::cerr << std::endl;
|
|
1857
|
+
} else if (ff) {
|
|
1858
|
+
name = ff->name();
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1650
1861
|
List_Obj arglist = SASS_MEMORY_COPY(ARG("$args", List));
|
|
1651
1862
|
|
|
1652
1863
|
Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
|
|
1653
1864
|
// std::string full_name(name + "[f]");
|
|
1654
|
-
// Definition_Ptr def = d_env.has(full_name) ?
|
|
1865
|
+
// Definition_Ptr def = d_env.has(full_name) ? Cast<Definition>((d_env)[full_name]) : 0;
|
|
1655
1866
|
// Parameters_Ptr params = def ? def->parameters() : 0;
|
|
1656
1867
|
// size_t param_size = params ? params->length() : 0;
|
|
1657
1868
|
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
|
1658
1869
|
Expression_Obj expr = arglist->value_at_index(i);
|
|
1659
1870
|
// if (params && params->has_rest_parameter()) {
|
|
1660
1871
|
// Parameter_Obj p = param_size > i ? (*params)[i] : 0;
|
|
1661
|
-
// List_Ptr list =
|
|
1872
|
+
// List_Ptr list = Cast<List>(expr);
|
|
1662
1873
|
// if (list && p && !p->is_rest_parameter()) expr = (*list)[0];
|
|
1663
1874
|
// }
|
|
1664
1875
|
if (arglist->is_arglist()) {
|
|
1665
1876
|
Expression_Obj obj = arglist->at(i);
|
|
1666
|
-
Argument_Obj arg = (Argument_Ptr)
|
|
1877
|
+
Argument_Obj arg = (Argument_Ptr) obj.ptr(); // XXX
|
|
1667
1878
|
args->append(SASS_MEMORY_NEW(Argument,
|
|
1668
1879
|
pstate,
|
|
1669
1880
|
expr,
|
|
@@ -1674,11 +1885,11 @@ namespace Sass {
|
|
|
1674
1885
|
args->append(SASS_MEMORY_NEW(Argument, pstate, expr));
|
|
1675
1886
|
}
|
|
1676
1887
|
}
|
|
1677
|
-
Function_Call_Obj func = SASS_MEMORY_NEW(Function_Call, pstate, name,
|
|
1678
|
-
Expand expand(ctx, &d_env,
|
|
1888
|
+
Function_Call_Obj func = SASS_MEMORY_NEW(Function_Call, pstate, name, args);
|
|
1889
|
+
Expand expand(ctx, &d_env, &selector_stack);
|
|
1679
1890
|
func->via_call(true); // calc invoke is allowed
|
|
1891
|
+
if (ff) func->func(ff);
|
|
1680
1892
|
return func->perform(&expand.eval);
|
|
1681
|
-
|
|
1682
1893
|
}
|
|
1683
1894
|
|
|
1684
1895
|
////////////////////
|
|
@@ -1696,24 +1907,13 @@ namespace Sass {
|
|
|
1696
1907
|
// { return ARG("$condition", Expression)->is_false() ? ARG("$if-false", Expression) : ARG("$if-true", Expression); }
|
|
1697
1908
|
BUILT_IN(sass_if)
|
|
1698
1909
|
{
|
|
1699
|
-
Expand expand(ctx, &d_env,
|
|
1910
|
+
Expand expand(ctx, &d_env, &selector_stack);
|
|
1700
1911
|
Expression_Obj cond = ARG("$condition", Expression)->perform(&expand.eval);
|
|
1701
1912
|
bool is_true = !cond->is_false();
|
|
1702
|
-
|
|
1913
|
+
Expression_Obj res = ARG(is_true ? "$if-true" : "$if-false", Expression);
|
|
1703
1914
|
res = res->perform(&expand.eval);
|
|
1704
1915
|
res->set_delayed(false); // clone?
|
|
1705
|
-
return res;
|
|
1706
|
-
}
|
|
1707
|
-
|
|
1708
|
-
////////////////
|
|
1709
|
-
// URL FUNCTIONS
|
|
1710
|
-
////////////////
|
|
1711
|
-
|
|
1712
|
-
Signature image_url_sig = "image-url($path, $only-path: false, $cache-buster: false)";
|
|
1713
|
-
BUILT_IN(image_url)
|
|
1714
|
-
{
|
|
1715
|
-
error("`image_url` has been removed from libsass because it's not part of the Sass spec", pstate);
|
|
1716
|
-
return 0; // suppress warning, error will exit anyway
|
|
1916
|
+
return res.detach();
|
|
1717
1917
|
}
|
|
1718
1918
|
|
|
1719
1919
|
//////////////////////////
|
|
@@ -1754,24 +1954,24 @@ namespace Sass {
|
|
|
1754
1954
|
|
|
1755
1955
|
// Not enough parameters
|
|
1756
1956
|
if( arglist->length() == 0 )
|
|
1757
|
-
error("$selectors: At least one selector must be passed for `selector-nest'", pstate);
|
|
1957
|
+
error("$selectors: At least one selector must be passed for `selector-nest'", pstate, traces);
|
|
1758
1958
|
|
|
1759
1959
|
// Parse args into vector of selectors
|
|
1760
1960
|
std::vector<Selector_List_Obj> parsedSelectors;
|
|
1761
1961
|
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
|
1762
|
-
Expression_Obj exp =
|
|
1962
|
+
Expression_Obj exp = Cast<Expression>(arglist->value_at_index(i));
|
|
1763
1963
|
if (exp->concrete_type() == Expression::NULL_VAL) {
|
|
1764
1964
|
std::stringstream msg;
|
|
1765
1965
|
msg << "$selectors: null is not a valid selector: it must be a string,\n";
|
|
1766
1966
|
msg << "a list of strings, or a list of lists of strings for 'selector-nest'";
|
|
1767
|
-
error(msg.str(), pstate);
|
|
1967
|
+
error(msg.str(), pstate, traces);
|
|
1768
1968
|
}
|
|
1769
|
-
if (String_Constant_Obj str =
|
|
1969
|
+
if (String_Constant_Obj str = Cast<String_Constant>(exp)) {
|
|
1770
1970
|
str->quote_mark(0);
|
|
1771
1971
|
}
|
|
1772
|
-
std::string exp_src = exp->to_string(ctx.c_options)
|
|
1773
|
-
Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx);
|
|
1774
|
-
parsedSelectors.push_back(
|
|
1972
|
+
std::string exp_src = exp->to_string(ctx.c_options);
|
|
1973
|
+
Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces);
|
|
1974
|
+
parsedSelectors.push_back(sel);
|
|
1775
1975
|
}
|
|
1776
1976
|
|
|
1777
1977
|
// Nothing to do
|
|
@@ -1787,8 +1987,8 @@ namespace Sass {
|
|
|
1787
1987
|
for(;itr != parsedSelectors.end(); ++itr) {
|
|
1788
1988
|
Selector_List_Obj child = *itr;
|
|
1789
1989
|
std::vector<Complex_Selector_Obj> exploded;
|
|
1790
|
-
selector_stack.push_back(
|
|
1791
|
-
Selector_List_Obj rv = child->resolve_parent_refs(
|
|
1990
|
+
selector_stack.push_back(result);
|
|
1991
|
+
Selector_List_Obj rv = child->resolve_parent_refs(selector_stack, traces);
|
|
1792
1992
|
selector_stack.pop_back();
|
|
1793
1993
|
for (size_t m = 0, mLen = rv->length(); m < mLen; ++m) {
|
|
1794
1994
|
exploded.push_back((*rv)[m]);
|
|
@@ -1807,24 +2007,24 @@ namespace Sass {
|
|
|
1807
2007
|
|
|
1808
2008
|
// Not enough parameters
|
|
1809
2009
|
if( arglist->length() == 0 )
|
|
1810
|
-
error("$selectors: At least one selector must be passed for `selector-append'", pstate);
|
|
2010
|
+
error("$selectors: At least one selector must be passed for `selector-append'", pstate, traces);
|
|
1811
2011
|
|
|
1812
2012
|
// Parse args into vector of selectors
|
|
1813
2013
|
std::vector<Selector_List_Obj> parsedSelectors;
|
|
1814
2014
|
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
|
1815
|
-
Expression_Obj exp =
|
|
2015
|
+
Expression_Obj exp = Cast<Expression>(arglist->value_at_index(i));
|
|
1816
2016
|
if (exp->concrete_type() == Expression::NULL_VAL) {
|
|
1817
2017
|
std::stringstream msg;
|
|
1818
2018
|
msg << "$selectors: null is not a valid selector: it must be a string,\n";
|
|
1819
2019
|
msg << "a list of strings, or a list of lists of strings for 'selector-append'";
|
|
1820
|
-
error(msg.str(), pstate);
|
|
2020
|
+
error(msg.str(), pstate, traces);
|
|
1821
2021
|
}
|
|
1822
|
-
if (String_Constant_Ptr str =
|
|
2022
|
+
if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
|
|
1823
2023
|
str->quote_mark(0);
|
|
1824
2024
|
}
|
|
1825
|
-
std::string exp_src = exp->to_string()
|
|
1826
|
-
Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx);
|
|
1827
|
-
parsedSelectors.push_back(
|
|
2025
|
+
std::string exp_src = exp->to_string();
|
|
2026
|
+
Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces);
|
|
2027
|
+
parsedSelectors.push_back(sel);
|
|
1828
2028
|
}
|
|
1829
2029
|
|
|
1830
2030
|
// Nothing to do
|
|
@@ -1861,29 +2061,29 @@ namespace Sass {
|
|
|
1861
2061
|
msg += "\" to \"";
|
|
1862
2062
|
msg += parentSeqClone->to_string();
|
|
1863
2063
|
msg += "\" for `selector-append'";
|
|
1864
|
-
error(msg, pstate,
|
|
2064
|
+
error(msg, pstate, traces);
|
|
1865
2065
|
}
|
|
1866
2066
|
|
|
1867
2067
|
// Cannot be a Universal selector
|
|
1868
|
-
Element_Selector_Obj pType =
|
|
2068
|
+
Element_Selector_Obj pType = Cast<Element_Selector>(childSeq->head()->first());
|
|
1869
2069
|
if(pType && pType->name() == "*") {
|
|
1870
2070
|
std::string msg("Can't append \"");
|
|
1871
2071
|
msg += childSeq->to_string();
|
|
1872
2072
|
msg += "\" to \"";
|
|
1873
2073
|
msg += parentSeqClone->to_string();
|
|
1874
2074
|
msg += "\" for `selector-append'";
|
|
1875
|
-
error(msg, pstate,
|
|
2075
|
+
error(msg, pstate, traces);
|
|
1876
2076
|
}
|
|
1877
2077
|
|
|
1878
2078
|
// TODO: Add check for namespace stuff
|
|
1879
2079
|
|
|
1880
2080
|
// append any selectors in childSeq's head
|
|
1881
|
-
parentSeqClone->innermost()->head()->concat(
|
|
2081
|
+
parentSeqClone->innermost()->head()->concat(base->head());
|
|
1882
2082
|
|
|
1883
2083
|
// Set parentSeqClone new tail
|
|
1884
2084
|
parentSeqClone->innermost()->tail( base->tail() );
|
|
1885
2085
|
|
|
1886
|
-
newElements.push_back(
|
|
2086
|
+
newElements.push_back(parentSeqClone);
|
|
1887
2087
|
}
|
|
1888
2088
|
}
|
|
1889
2089
|
|
|
@@ -1900,7 +2100,7 @@ namespace Sass {
|
|
|
1900
2100
|
Selector_List_Obj selector1 = ARGSEL("$selector1", Selector_List_Obj, p_contextualize);
|
|
1901
2101
|
Selector_List_Obj selector2 = ARGSEL("$selector2", Selector_List_Obj, p_contextualize);
|
|
1902
2102
|
|
|
1903
|
-
Selector_List_Obj result = selector1->unify_with(
|
|
2103
|
+
Selector_List_Obj result = selector1->unify_with(selector2);
|
|
1904
2104
|
Listize listize;
|
|
1905
2105
|
return result->perform(&listize);
|
|
1906
2106
|
}
|
|
@@ -1930,9 +2130,10 @@ namespace Sass {
|
|
|
1930
2130
|
Selector_List_Obj extender = ARGSEL("$extender", Selector_List_Obj, p_contextualize);
|
|
1931
2131
|
|
|
1932
2132
|
Subset_Map subset_map;
|
|
1933
|
-
extender->populate_extends(extendee,
|
|
2133
|
+
extender->populate_extends(extendee, subset_map);
|
|
2134
|
+
Extend extend(subset_map);
|
|
1934
2135
|
|
|
1935
|
-
Selector_List_Obj result =
|
|
2136
|
+
Selector_List_Obj result = extend.extendSelectorList(selector, false);
|
|
1936
2137
|
|
|
1937
2138
|
Listize listize;
|
|
1938
2139
|
return result->perform(&listize);
|
|
@@ -1945,9 +2146,10 @@ namespace Sass {
|
|
|
1945
2146
|
Selector_List_Obj original = ARGSEL("$original", Selector_List_Obj, p_contextualize);
|
|
1946
2147
|
Selector_List_Obj replacement = ARGSEL("$replacement", Selector_List_Obj, p_contextualize);
|
|
1947
2148
|
Subset_Map subset_map;
|
|
1948
|
-
replacement->populate_extends(original,
|
|
2149
|
+
replacement->populate_extends(original, subset_map);
|
|
2150
|
+
Extend extend(subset_map);
|
|
1949
2151
|
|
|
1950
|
-
Selector_List_Obj result =
|
|
2152
|
+
Selector_List_Obj result = extend.extendSelectorList(selector, true);
|
|
1951
2153
|
|
|
1952
2154
|
Listize listize;
|
|
1953
2155
|
return result->perform(&listize);
|
|
@@ -1981,5 +2183,52 @@ namespace Sass {
|
|
|
1981
2183
|
return SASS_MEMORY_NEW(String_Quoted, pstate, ss.str());
|
|
1982
2184
|
}
|
|
1983
2185
|
|
|
2186
|
+
Signature is_bracketed_sig = "is-bracketed($list)";
|
|
2187
|
+
BUILT_IN(is_bracketed)
|
|
2188
|
+
{
|
|
2189
|
+
Value_Obj value = ARG("$list", Value);
|
|
2190
|
+
List_Obj list = Cast<List>(value);
|
|
2191
|
+
return SASS_MEMORY_NEW(Boolean, pstate, list && list->is_bracketed());
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
Signature content_exists_sig = "content-exists()";
|
|
2195
|
+
BUILT_IN(content_exists)
|
|
2196
|
+
{
|
|
2197
|
+
if (!d_env.has_global("is_in_mixin")) {
|
|
2198
|
+
error("Cannot call content-exists() except within a mixin.", pstate, traces);
|
|
2199
|
+
}
|
|
2200
|
+
return SASS_MEMORY_NEW(Boolean, pstate, d_env.has_lexical("@content[m]"));
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
Signature get_function_sig = "get-function($name, $css: false)";
|
|
2204
|
+
BUILT_IN(get_function)
|
|
2205
|
+
{
|
|
2206
|
+
String_Constant_Ptr ss = Cast<String_Constant>(env["$name"]);
|
|
2207
|
+
if (!ss) {
|
|
2208
|
+
error("$name: " + (env["$name"]->to_string()) + " is not a string for `get-function'", pstate, traces);
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
std::string name = Util::normalize_underscores(unquote(ss->value()));
|
|
2212
|
+
std::string full_name = name + "[f]";
|
|
2213
|
+
|
|
2214
|
+
Boolean_Obj css = ARG("$css", Boolean);
|
|
2215
|
+
if (!css->is_false()) {
|
|
2216
|
+
Definition_Ptr def = SASS_MEMORY_NEW(Definition,
|
|
2217
|
+
pstate,
|
|
2218
|
+
name,
|
|
2219
|
+
SASS_MEMORY_NEW(Parameters, pstate),
|
|
2220
|
+
SASS_MEMORY_NEW(Block, pstate, 0, false),
|
|
2221
|
+
Definition::FUNCTION);
|
|
2222
|
+
return SASS_MEMORY_NEW(Function, pstate, def, true);
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
|
|
2226
|
+
if (!d_env.has_global(full_name)) {
|
|
2227
|
+
error("Function not found: " + name, pstate, traces);
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
Definition_Ptr def = Cast<Definition>(d_env[full_name]);
|
|
2231
|
+
return SASS_MEMORY_NEW(Function, pstate, def, false);
|
|
2232
|
+
}
|
|
1984
2233
|
}
|
|
1985
2234
|
}
|