sassc 1.11.4 → 1.12.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|