sassc 2.0.1 → 2.1.0.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.gitmodules +1 -1
- data/.travis.yml +7 -3
- data/CHANGELOG.md +3 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/README.md +1 -1
- data/Rakefile +23 -8
- data/ext/extconf.rb +39 -0
- data/ext/libsass/.gitignore +1 -0
- data/ext/libsass/GNUmakefile.am +23 -39
- data/ext/libsass/Makefile +56 -91
- data/ext/libsass/Makefile.conf +16 -2
- data/ext/libsass/configure.ac +8 -12
- data/ext/libsass/include/sass/base.h +1 -0
- data/ext/libsass/include/sass/context.h +1 -1
- data/ext/libsass/src/GNUmakefile.am +1 -5
- data/ext/libsass/src/ast.cpp +747 -2010
- data/ext/libsass/src/ast.hpp +239 -2383
- data/ext/libsass/src/{to_c.cpp → ast2c.cpp} +22 -16
- data/ext/libsass/src/ast2c.hpp +39 -0
- data/ext/libsass/src/ast_def_macros.hpp +62 -10
- data/ext/libsass/src/ast_fwd_decl.cpp +1 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +43 -165
- data/ext/libsass/src/ast_sel_cmp.cpp +909 -0
- data/ext/libsass/src/ast_sel_unify.cpp +280 -0
- data/ext/libsass/src/ast_selectors.cpp +1475 -0
- data/ext/libsass/src/ast_selectors.hpp +568 -0
- data/ext/libsass/src/ast_supports.cpp +130 -0
- data/ext/libsass/src/ast_supports.hpp +121 -0
- data/ext/libsass/src/ast_values.cpp +967 -0
- data/ext/libsass/src/ast_values.hpp +489 -0
- data/ext/libsass/src/backtrace.cpp +4 -0
- data/ext/libsass/src/base64vlq.cpp +3 -0
- data/ext/libsass/src/bind.cpp +18 -17
- data/ext/libsass/src/bind.hpp +3 -1
- data/ext/libsass/src/c2ast.cpp +64 -0
- data/ext/libsass/src/c2ast.hpp +14 -0
- data/ext/libsass/src/cencode.c +2 -2
- data/ext/libsass/src/check_nesting.cpp +52 -56
- data/ext/libsass/src/check_nesting.hpp +35 -34
- data/ext/libsass/src/color_maps.cpp +156 -153
- data/ext/libsass/src/color_maps.hpp +152 -152
- data/ext/libsass/src/constants.cpp +15 -0
- data/ext/libsass/src/constants.hpp +13 -0
- data/ext/libsass/src/context.cpp +24 -14
- data/ext/libsass/src/context.hpp +6 -6
- data/ext/libsass/src/cssize.cpp +69 -71
- data/ext/libsass/src/cssize.hpp +50 -50
- data/ext/libsass/src/debugger.hpp +117 -110
- data/ext/libsass/src/emitter.cpp +13 -12
- data/ext/libsass/src/emitter.hpp +13 -9
- data/ext/libsass/src/environment.cpp +15 -1
- data/ext/libsass/src/environment.hpp +6 -0
- data/ext/libsass/src/error_handling.cpp +36 -59
- data/ext/libsass/src/error_handling.hpp +29 -16
- data/ext/libsass/src/eval.cpp +302 -323
- data/ext/libsass/src/eval.hpp +64 -55
- data/ext/libsass/src/expand.cpp +94 -88
- data/ext/libsass/src/expand.hpp +33 -37
- data/ext/libsass/src/extend.cpp +38 -36
- data/ext/libsass/src/extend.hpp +15 -15
- data/ext/libsass/src/file.cpp +34 -2
- data/ext/libsass/src/fn_colors.cpp +594 -0
- data/ext/libsass/src/fn_colors.hpp +85 -0
- data/ext/libsass/src/fn_lists.cpp +284 -0
- data/ext/libsass/src/fn_lists.hpp +34 -0
- data/ext/libsass/src/fn_maps.cpp +94 -0
- data/ext/libsass/src/fn_maps.hpp +30 -0
- data/ext/libsass/src/fn_miscs.cpp +256 -0
- data/ext/libsass/src/fn_miscs.hpp +40 -0
- data/ext/libsass/src/fn_numbers.cpp +220 -0
- data/ext/libsass/src/fn_numbers.hpp +45 -0
- data/ext/libsass/src/fn_selectors.cpp +235 -0
- data/ext/libsass/src/fn_selectors.hpp +35 -0
- data/ext/libsass/src/fn_strings.cpp +254 -0
- data/ext/libsass/src/fn_strings.hpp +34 -0
- data/ext/libsass/src/fn_utils.cpp +156 -0
- data/ext/libsass/src/fn_utils.hpp +56 -0
- data/ext/libsass/src/inspect.cpp +101 -152
- data/ext/libsass/src/inspect.hpp +69 -73
- data/ext/libsass/src/json.cpp +2 -2
- data/ext/libsass/src/lexer.cpp +6 -3
- data/ext/libsass/src/listize.cpp +9 -11
- data/ext/libsass/src/listize.hpp +11 -7
- data/ext/libsass/src/memory/SharedPtr.cpp +2 -83
- data/ext/libsass/src/memory/SharedPtr.hpp +127 -143
- data/ext/libsass/src/node.cpp +13 -10
- data/ext/libsass/src/node.hpp +3 -3
- data/ext/libsass/src/operation.hpp +184 -144
- data/ext/libsass/src/operators.cpp +43 -17
- data/ext/libsass/src/operators.hpp +5 -5
- data/ext/libsass/src/output.cpp +21 -18
- data/ext/libsass/src/output.hpp +14 -21
- data/ext/libsass/src/parser.cpp +215 -183
- data/ext/libsass/src/parser.hpp +28 -24
- data/ext/libsass/src/plugins.cpp +5 -1
- data/ext/libsass/src/position.cpp +3 -0
- data/ext/libsass/src/prelexer.cpp +9 -3
- data/ext/libsass/src/prelexer.hpp +9 -9
- data/ext/libsass/src/remove_placeholders.cpp +14 -11
- data/ext/libsass/src/remove_placeholders.hpp +8 -9
- data/ext/libsass/src/sass.cpp +9 -3
- data/ext/libsass/src/sass.hpp +12 -9
- data/ext/libsass/src/sass2scss.cpp +45 -14
- data/ext/libsass/src/sass_context.cpp +18 -15
- data/ext/libsass/src/sass_functions.cpp +6 -3
- data/ext/libsass/src/sass_functions.hpp +1 -1
- data/ext/libsass/src/sass_util.cpp +3 -0
- data/ext/libsass/src/sass_values.cpp +21 -13
- data/ext/libsass/src/source_map.cpp +5 -2
- data/ext/libsass/src/source_map.hpp +2 -2
- data/ext/libsass/src/subset_map.cpp +4 -1
- data/ext/libsass/src/to_value.cpp +23 -21
- data/ext/libsass/src/to_value.hpp +18 -22
- data/ext/libsass/src/units.cpp +4 -0
- data/ext/libsass/src/units.hpp +1 -0
- data/ext/libsass/src/utf8/checked.h +12 -10
- data/ext/libsass/src/utf8/core.h +3 -0
- data/ext/libsass/src/utf8_string.cpp +3 -0
- data/ext/libsass/src/util.cpp +67 -75
- data/ext/libsass/src/util.hpp +64 -19
- data/ext/libsass/src/util_string.cpp +75 -0
- data/ext/libsass/src/util_string.hpp +19 -0
- data/ext/libsass/src/values.cpp +22 -13
- data/ext/libsass/src/values.hpp +2 -2
- data/ext/libsass/win/libsass.targets +30 -4
- data/ext/libsass/win/libsass.vcxproj.filters +82 -4
- data/lib/sassc.rb +24 -0
- data/lib/sassc/engine.rb +2 -2
- data/lib/sassc/native.rb +8 -1
- data/lib/sassc/version.rb +1 -1
- data/sassc.gemspec +19 -11
- data/test/engine_test.rb +26 -1
- data/test/native_test.rb +1 -1
- metadata +66 -72
- data/ext/Rakefile +0 -3
- data/ext/libsass/.github/CONTRIBUTING.md +0 -65
- data/ext/libsass/.github/ISSUE_TEMPLATE.md +0 -54
- data/ext/libsass/.travis.yml +0 -64
- data/ext/libsass/Readme.md +0 -104
- data/ext/libsass/SECURITY.md +0 -10
- data/ext/libsass/appveyor.yml +0 -91
- data/ext/libsass/docs/README.md +0 -20
- data/ext/libsass/docs/api-context-example.md +0 -45
- data/ext/libsass/docs/api-context-internal.md +0 -163
- data/ext/libsass/docs/api-context.md +0 -295
- data/ext/libsass/docs/api-doc.md +0 -215
- data/ext/libsass/docs/api-function-example.md +0 -67
- data/ext/libsass/docs/api-function-internal.md +0 -8
- data/ext/libsass/docs/api-function.md +0 -74
- data/ext/libsass/docs/api-importer-example.md +0 -112
- data/ext/libsass/docs/api-importer-internal.md +0 -20
- data/ext/libsass/docs/api-importer.md +0 -86
- data/ext/libsass/docs/api-value-example.md +0 -55
- data/ext/libsass/docs/api-value-internal.md +0 -76
- data/ext/libsass/docs/api-value.md +0 -154
- data/ext/libsass/docs/build-on-darwin.md +0 -27
- data/ext/libsass/docs/build-on-gentoo.md +0 -55
- data/ext/libsass/docs/build-on-windows.md +0 -139
- data/ext/libsass/docs/build-shared-library.md +0 -35
- data/ext/libsass/docs/build-with-autotools.md +0 -78
- data/ext/libsass/docs/build-with-makefiles.md +0 -68
- data/ext/libsass/docs/build-with-mingw.md +0 -107
- data/ext/libsass/docs/build-with-visual-studio.md +0 -90
- data/ext/libsass/docs/build.md +0 -97
- data/ext/libsass/docs/compatibility-plan.md +0 -48
- data/ext/libsass/docs/contributing.md +0 -17
- data/ext/libsass/docs/custom-functions-internal.md +0 -122
- data/ext/libsass/docs/dev-ast-memory.md +0 -223
- data/ext/libsass/docs/implementations.md +0 -56
- data/ext/libsass/docs/plugins.md +0 -47
- data/ext/libsass/docs/setup-environment.md +0 -68
- data/ext/libsass/docs/source-map-internals.md +0 -51
- data/ext/libsass/docs/trace.md +0 -26
- data/ext/libsass/docs/triage.md +0 -17
- data/ext/libsass/docs/unicode.md +0 -39
- data/ext/libsass/extconf.rb +0 -6
- data/ext/libsass/script/bootstrap +0 -13
- data/ext/libsass/script/branding +0 -10
- data/ext/libsass/script/ci-build-libsass +0 -134
- data/ext/libsass/script/ci-build-plugin +0 -62
- data/ext/libsass/script/ci-install-compiler +0 -6
- data/ext/libsass/script/ci-install-deps +0 -20
- data/ext/libsass/script/ci-report-coverage +0 -42
- data/ext/libsass/script/spec +0 -5
- data/ext/libsass/script/tap-driver +0 -652
- data/ext/libsass/script/tap-runner +0 -1
- data/ext/libsass/script/test-leaks.pl +0 -103
- data/ext/libsass/src/functions.cpp +0 -2234
- data/ext/libsass/src/functions.hpp +0 -198
- data/ext/libsass/src/to_c.hpp +0 -39
- data/ext/libsass/test/test_node.cpp +0 -94
- data/ext/libsass/test/test_paths.cpp +0 -28
- data/ext/libsass/test/test_selector_difference.cpp +0 -25
- data/ext/libsass/test/test_specificity.cpp +0 -25
- data/ext/libsass/test/test_subset_map.cpp +0 -472
- data/ext/libsass/test/test_superselector.cpp +0 -69
- data/ext/libsass/test/test_unification.cpp +0 -31
- data/lib/tasks/libsass.rb +0 -33
@@ -1 +0,0 @@
|
|
1
|
-
$@ | tapout tap
|
@@ -1,103 +0,0 @@
|
|
1
|
-
#!/usr/bin/perl
|
2
|
-
############################################################
|
3
|
-
# this perl script is meant for developers only!
|
4
|
-
# it will run all spec-tests (without verifying the
|
5
|
-
# results) via valgrind to detect possible leaks.
|
6
|
-
# expect that it takes 1h or more to finish!
|
7
|
-
############################################################
|
8
|
-
# Prerequisite install: `cpan Parallel::Runner`
|
9
|
-
# You may also need to install `cpan File::Find`
|
10
|
-
# You may also need to install `cpan IPC::Run3`
|
11
|
-
############################################################
|
12
|
-
# usage: `perl test-leaks.pl [threads]`
|
13
|
-
# example: `time perl test-leaks.pl 4`
|
14
|
-
############################################################
|
15
|
-
# leaks will be reported in "mem-leaks.log"
|
16
|
-
############################################################
|
17
|
-
|
18
|
-
use strict;
|
19
|
-
use warnings;
|
20
|
-
|
21
|
-
############################################################
|
22
|
-
# configurations (you may adjust)
|
23
|
-
############################################################
|
24
|
-
|
25
|
-
# number of threads to use
|
26
|
-
my $threads = $ARGV[0] || 8;
|
27
|
-
|
28
|
-
# the github repositories to checkout
|
29
|
-
# if you need other branch, clone manually!
|
30
|
-
my $sassc = "https://www.github.com/sass/sassc";
|
31
|
-
my $specs = "https://www.github.com/sass/sass-spec";
|
32
|
-
|
33
|
-
############################################################
|
34
|
-
# load modules
|
35
|
-
############################################################
|
36
|
-
|
37
|
-
use IPC::Run3;
|
38
|
-
use IO::Handle;
|
39
|
-
use Fcntl qw(:flock);
|
40
|
-
use File::Find::Rule;
|
41
|
-
use Parallel::Runner;
|
42
|
-
use List::Util qw(shuffle);
|
43
|
-
|
44
|
-
############################################################
|
45
|
-
# check prerequisites
|
46
|
-
############################################################
|
47
|
-
|
48
|
-
unless (-d "../sassc") {
|
49
|
-
warn "sassc folder not found\n";
|
50
|
-
warn "trying to checkout via git\n";
|
51
|
-
system("git", "clone", $sassc, "../sassc");
|
52
|
-
die "git command did not exit gracefully" if $?;
|
53
|
-
}
|
54
|
-
|
55
|
-
unless (-d "../sass-spec") {
|
56
|
-
warn "sass-spec folder not found\n";
|
57
|
-
warn "trying to checkout via git\n";
|
58
|
-
system("git", "clone", $specs, "../sass-spec");
|
59
|
-
die "git command did not exit gracefully" if $?;
|
60
|
-
}
|
61
|
-
|
62
|
-
unless (-f "../sassc/bin/sassc") {
|
63
|
-
warn "sassc executable not found\n";
|
64
|
-
warn "trying to compile via make\n";
|
65
|
-
system("make", "-C", "../sassc", "-j", $threads);
|
66
|
-
die "make command did not exit gracefully" if $?;
|
67
|
-
}
|
68
|
-
|
69
|
-
############################################################
|
70
|
-
# main runner code
|
71
|
-
############################################################
|
72
|
-
|
73
|
-
my $root = "../sass-spec/spec";
|
74
|
-
my @files = File::Find::Rule->file()
|
75
|
-
->name('input.scss')->in($root);
|
76
|
-
|
77
|
-
open(my $leaks, ">", "mem-leaks.log");
|
78
|
-
die "Cannot open log" unless $leaks;
|
79
|
-
my $runner = Parallel::Runner->new($threads);
|
80
|
-
die "Cannot start runner" unless $runner;
|
81
|
-
|
82
|
-
print "##########################\n";
|
83
|
-
print "Testing $#files spec files\n";
|
84
|
-
print "##########################\n";
|
85
|
-
|
86
|
-
foreach my $file (shuffle @files) {
|
87
|
-
$runner->run(sub {
|
88
|
-
$| = 1; select STDOUT;
|
89
|
-
my $cmd = sprintf('../sassc/bin/sassc %s', $file);
|
90
|
-
my $check = sprintf('valgrind --leak-check=yes %s', $cmd);
|
91
|
-
run3($check, undef, \ my $out, \ my $err);
|
92
|
-
if ($err =~ m/in use at exit: 0 bytes in 0 blocks/) {
|
93
|
-
print "."; # print success indicator
|
94
|
-
} else {
|
95
|
-
print "F"; # print error indicator
|
96
|
-
flock($leaks, LOCK_EX) or die "Cannot lock log";
|
97
|
-
$leaks->printflush("#" x 80, "\n", $err, "\n");
|
98
|
-
flock($leaks, LOCK_UN) or die "Cannot unlock log";
|
99
|
-
}
|
100
|
-
});
|
101
|
-
}
|
102
|
-
|
103
|
-
$runner->finish;
|
@@ -1,2234 +0,0 @@
|
|
1
|
-
#include "sass.hpp"
|
2
|
-
#include "functions.hpp"
|
3
|
-
#include "ast.hpp"
|
4
|
-
#include "context.hpp"
|
5
|
-
#include "backtrace.hpp"
|
6
|
-
#include "parser.hpp"
|
7
|
-
#include "constants.hpp"
|
8
|
-
#include "inspect.hpp"
|
9
|
-
#include "extend.hpp"
|
10
|
-
#include "eval.hpp"
|
11
|
-
#include "util.hpp"
|
12
|
-
#include "expand.hpp"
|
13
|
-
#include "operators.hpp"
|
14
|
-
#include "utf8_string.hpp"
|
15
|
-
#include "sass/base.h"
|
16
|
-
#include "utf8.h"
|
17
|
-
|
18
|
-
#include <cstdint>
|
19
|
-
#include <cstdlib>
|
20
|
-
#include <cmath>
|
21
|
-
#include <cctype>
|
22
|
-
#include <sstream>
|
23
|
-
#include <string>
|
24
|
-
#include <iomanip>
|
25
|
-
#include <iostream>
|
26
|
-
#include <random>
|
27
|
-
#include <set>
|
28
|
-
|
29
|
-
#ifdef __MINGW32__
|
30
|
-
#include "windows.h"
|
31
|
-
#include "wincrypt.h"
|
32
|
-
#endif
|
33
|
-
|
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
|
54
|
-
|
55
|
-
namespace Sass {
|
56
|
-
using std::stringstream;
|
57
|
-
using std::endl;
|
58
|
-
|
59
|
-
Definition_Ptr make_native_function(Signature sig, Native_Function func, Context& ctx)
|
60
|
-
{
|
61
|
-
Parser sig_parser = Parser::from_c_str(sig, ctx, ctx.traces, ParserState("[built-in function]"));
|
62
|
-
sig_parser.lex<Prelexer::identifier>();
|
63
|
-
std::string name(Util::normalize_underscores(sig_parser.lexed));
|
64
|
-
Parameters_Obj params = sig_parser.parse_parameters();
|
65
|
-
return SASS_MEMORY_NEW(Definition,
|
66
|
-
ParserState("[built-in function]"),
|
67
|
-
sig,
|
68
|
-
name,
|
69
|
-
params,
|
70
|
-
func,
|
71
|
-
false);
|
72
|
-
}
|
73
|
-
|
74
|
-
Definition_Ptr make_c_function(Sass_Function_Entry c_func, Context& ctx)
|
75
|
-
{
|
76
|
-
using namespace Prelexer;
|
77
|
-
|
78
|
-
const char* sig = sass_function_get_signature(c_func);
|
79
|
-
Parser sig_parser = Parser::from_c_str(sig, ctx, ctx.traces, ParserState("[c function]"));
|
80
|
-
// allow to overload generic callback plus @warn, @error and @debug with custom functions
|
81
|
-
sig_parser.lex < alternatives < identifier, exactly <'*'>,
|
82
|
-
exactly < Constants::warn_kwd >,
|
83
|
-
exactly < Constants::error_kwd >,
|
84
|
-
exactly < Constants::debug_kwd >
|
85
|
-
> >();
|
86
|
-
std::string name(Util::normalize_underscores(sig_parser.lexed));
|
87
|
-
Parameters_Obj params = sig_parser.parse_parameters();
|
88
|
-
return SASS_MEMORY_NEW(Definition,
|
89
|
-
ParserState("[c function]"),
|
90
|
-
sig,
|
91
|
-
name,
|
92
|
-
params,
|
93
|
-
c_func,
|
94
|
-
false, true);
|
95
|
-
}
|
96
|
-
|
97
|
-
std::string function_name(Signature sig)
|
98
|
-
{
|
99
|
-
std::string str(sig);
|
100
|
-
return str.substr(0, str.find('('));
|
101
|
-
}
|
102
|
-
|
103
|
-
namespace Functions {
|
104
|
-
|
105
|
-
inline void handle_utf8_error (const ParserState& pstate, Backtraces traces)
|
106
|
-
{
|
107
|
-
try {
|
108
|
-
throw;
|
109
|
-
}
|
110
|
-
catch (utf8::invalid_code_point) {
|
111
|
-
std::string msg("utf8::invalid_code_point");
|
112
|
-
error(msg, pstate, traces);
|
113
|
-
}
|
114
|
-
catch (utf8::not_enough_room) {
|
115
|
-
std::string msg("utf8::not_enough_room");
|
116
|
-
error(msg, pstate, traces);
|
117
|
-
}
|
118
|
-
catch (utf8::invalid_utf8) {
|
119
|
-
std::string msg("utf8::invalid_utf8");
|
120
|
-
error(msg, pstate, traces);
|
121
|
-
}
|
122
|
-
catch (...) { throw; }
|
123
|
-
}
|
124
|
-
|
125
|
-
template <typename T>
|
126
|
-
T* get_arg(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces)
|
127
|
-
{
|
128
|
-
// Minimal error handling -- the expectation is that built-ins will be written correctly!
|
129
|
-
T* val = Cast<T>(env[argname]);
|
130
|
-
if (!val) {
|
131
|
-
std::string msg("argument `");
|
132
|
-
msg += argname;
|
133
|
-
msg += "` of `";
|
134
|
-
msg += sig;
|
135
|
-
msg += "` must be a ";
|
136
|
-
msg += T::type_name();
|
137
|
-
error(msg, pstate, traces);
|
138
|
-
}
|
139
|
-
return val;
|
140
|
-
}
|
141
|
-
|
142
|
-
Map_Ptr get_arg_m(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx)
|
143
|
-
{
|
144
|
-
// Minimal error handling -- the expectation is that built-ins will be written correctly!
|
145
|
-
Map_Ptr val = Cast<Map>(env[argname]);
|
146
|
-
if (val) return val;
|
147
|
-
|
148
|
-
List_Ptr lval = Cast<List>(env[argname]);
|
149
|
-
if (lval && lval->length() == 0) return SASS_MEMORY_NEW(Map, pstate, 0);
|
150
|
-
|
151
|
-
// fallback on get_arg for error handling
|
152
|
-
val = get_arg<Map>(argname, env, sig, pstate, traces);
|
153
|
-
return val;
|
154
|
-
}
|
155
|
-
|
156
|
-
double get_arg_r(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, double lo, double hi)
|
157
|
-
{
|
158
|
-
// Minimal error handling -- the expectation is that built-ins will be written correctly!
|
159
|
-
Number_Ptr val = get_arg<Number>(argname, env, sig, pstate, traces);
|
160
|
-
Number tmpnr(val);
|
161
|
-
tmpnr.reduce();
|
162
|
-
double v = tmpnr.value();
|
163
|
-
if (!(lo <= v && v <= hi)) {
|
164
|
-
std::stringstream msg;
|
165
|
-
msg << "argument `" << argname << "` of `" << sig << "` must be between ";
|
166
|
-
msg << lo << " and " << hi;
|
167
|
-
error(msg.str(), pstate, traces);
|
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();
|
178
|
-
return val;
|
179
|
-
}
|
180
|
-
|
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)
|
232
|
-
|
233
|
-
template <typename T>
|
234
|
-
T get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx);
|
235
|
-
|
236
|
-
template <>
|
237
|
-
Selector_List_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) {
|
238
|
-
Expression_Obj exp = ARG(argname, Expression);
|
239
|
-
if (exp->concrete_type() == Expression::NULL_VAL) {
|
240
|
-
std::stringstream msg;
|
241
|
-
msg << argname << ": null is not a valid selector: it must be a string,\n";
|
242
|
-
msg << "a list of strings, or a list of lists of strings for `" << function_name(sig) << "'";
|
243
|
-
error(msg.str(), pstate, traces);
|
244
|
-
}
|
245
|
-
if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
|
246
|
-
str->quote_mark(0);
|
247
|
-
}
|
248
|
-
std::string exp_src = exp->to_string(ctx.c_options);
|
249
|
-
return Parser::parse_selector(exp_src.c_str(), ctx, traces);
|
250
|
-
}
|
251
|
-
|
252
|
-
template <>
|
253
|
-
Compound_Selector_Obj get_arg_sel(const std::string& argname, Env& env, Signature sig, ParserState pstate, Backtraces traces, Context& ctx) {
|
254
|
-
Expression_Obj exp = ARG(argname, Expression);
|
255
|
-
if (exp->concrete_type() == Expression::NULL_VAL) {
|
256
|
-
std::stringstream msg;
|
257
|
-
msg << argname << ": null is not a string for `" << function_name(sig) << "'";
|
258
|
-
error(msg.str(), pstate, traces);
|
259
|
-
}
|
260
|
-
if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
|
261
|
-
str->quote_mark(0);
|
262
|
-
}
|
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();
|
269
|
-
}
|
270
|
-
|
271
|
-
#ifdef __MINGW32__
|
272
|
-
uint64_t GetSeed()
|
273
|
-
{
|
274
|
-
HCRYPTPROV hp = 0;
|
275
|
-
BYTE rb[8];
|
276
|
-
CryptAcquireContext(&hp, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
|
277
|
-
CryptGenRandom(hp, sizeof(rb), rb);
|
278
|
-
CryptReleaseContext(hp, 0);
|
279
|
-
|
280
|
-
uint64_t seed;
|
281
|
-
memcpy(&seed, &rb[0], sizeof(seed));
|
282
|
-
|
283
|
-
return seed;
|
284
|
-
}
|
285
|
-
#else
|
286
|
-
uint64_t GetSeed()
|
287
|
-
{
|
288
|
-
std::random_device rd;
|
289
|
-
return rd();
|
290
|
-
}
|
291
|
-
#endif
|
292
|
-
|
293
|
-
// note: the performance of many implementations of
|
294
|
-
// random_device degrades sharply once the entropy pool
|
295
|
-
// is exhausted. For practical use, random_device is
|
296
|
-
// generally only used to seed a PRNG such as mt19937.
|
297
|
-
static std::mt19937 rand(static_cast<unsigned int>(GetSeed()));
|
298
|
-
|
299
|
-
// features
|
300
|
-
static std::set<std::string> features {
|
301
|
-
"global-variable-shadowing",
|
302
|
-
"extend-selector-pseudoclass",
|
303
|
-
"at-error",
|
304
|
-
"units-level-3",
|
305
|
-
"custom-property"
|
306
|
-
};
|
307
|
-
|
308
|
-
////////////////
|
309
|
-
// RGB FUNCTIONS
|
310
|
-
////////////////
|
311
|
-
|
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());
|
319
|
-
}
|
320
|
-
return false;
|
321
|
-
}
|
322
|
-
|
323
|
-
Signature rgb_sig = "rgb($red, $green, $blue)";
|
324
|
-
BUILT_IN(rgb)
|
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
|
-
|
341
|
-
return SASS_MEMORY_NEW(Color,
|
342
|
-
pstate,
|
343
|
-
COLOR_NUM("$red"),
|
344
|
-
COLOR_NUM("$green"),
|
345
|
-
COLOR_NUM("$blue"));
|
346
|
-
}
|
347
|
-
|
348
|
-
Signature rgba_4_sig = "rgba($red, $green, $blue, $alpha)";
|
349
|
-
BUILT_IN(rgba_4)
|
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
|
-
|
369
|
-
return SASS_MEMORY_NEW(Color,
|
370
|
-
pstate,
|
371
|
-
COLOR_NUM("$red"),
|
372
|
-
COLOR_NUM("$green"),
|
373
|
-
COLOR_NUM("$blue"),
|
374
|
-
ALPHA_NUM("$alpha"));
|
375
|
-
}
|
376
|
-
|
377
|
-
Signature rgba_2_sig = "rgba($color, $alpha)";
|
378
|
-
BUILT_IN(rgba_2)
|
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
|
-
|
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
|
-
|
406
|
-
Color_Ptr new_c = SASS_MEMORY_COPY(c_arg);
|
407
|
-
new_c->a(ALPHA_NUM("$alpha"));
|
408
|
-
new_c->disp("");
|
409
|
-
return new_c;
|
410
|
-
}
|
411
|
-
|
412
|
-
Signature red_sig = "red($color)";
|
413
|
-
BUILT_IN(red)
|
414
|
-
{ return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->r()); }
|
415
|
-
|
416
|
-
Signature green_sig = "green($color)";
|
417
|
-
BUILT_IN(green)
|
418
|
-
{ return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->g()); }
|
419
|
-
|
420
|
-
Signature blue_sig = "blue($color)";
|
421
|
-
BUILT_IN(blue)
|
422
|
-
{ return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->b()); }
|
423
|
-
|
424
|
-
Color* colormix(Context& ctx, ParserState& pstate, Color* color1, Color* color2, double weight) {
|
425
|
-
double p = weight/100;
|
426
|
-
double w = 2*p - 1;
|
427
|
-
double a = color1->a() - color2->a();
|
428
|
-
|
429
|
-
double w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0;
|
430
|
-
double w2 = 1 - w1;
|
431
|
-
|
432
|
-
return SASS_MEMORY_NEW(Color,
|
433
|
-
pstate,
|
434
|
-
Sass::round(w1*color1->r() + w2*color2->r(), ctx.c_options.precision),
|
435
|
-
Sass::round(w1*color1->g() + w2*color2->g(), ctx.c_options.precision),
|
436
|
-
Sass::round(w1*color1->b() + w2*color2->b(), ctx.c_options.precision),
|
437
|
-
color1->a()*p + color2->a()*(1-p));
|
438
|
-
}
|
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
|
-
|
450
|
-
////////////////
|
451
|
-
// HSL FUNCTIONS
|
452
|
-
////////////////
|
453
|
-
|
454
|
-
// RGB to HSL helper function
|
455
|
-
struct HSL { double h; double s; double l; };
|
456
|
-
HSL rgb_to_hsl(double r, double g, double b)
|
457
|
-
{
|
458
|
-
|
459
|
-
// Algorithm from http://en.wikipedia.org/wiki/wHSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV
|
460
|
-
r /= 255.0; g /= 255.0; b /= 255.0;
|
461
|
-
|
462
|
-
double max = std::max(r, std::max(g, b));
|
463
|
-
double min = std::min(r, std::min(g, b));
|
464
|
-
double delta = max - min;
|
465
|
-
|
466
|
-
double h = 0;
|
467
|
-
double s;
|
468
|
-
double l = (max + min) / 2.0;
|
469
|
-
|
470
|
-
if (max == min) {
|
471
|
-
h = s = 0; // achromatic
|
472
|
-
}
|
473
|
-
else {
|
474
|
-
if (l < 0.5) s = delta / (max + min);
|
475
|
-
else s = delta / (2.0 - max - min);
|
476
|
-
|
477
|
-
if (r == max) h = (g - b) / delta + (g < b ? 6 : 0);
|
478
|
-
else if (g == max) h = (b - r) / delta + 2;
|
479
|
-
else if (b == max) h = (r - g) / delta + 4;
|
480
|
-
}
|
481
|
-
|
482
|
-
HSL hsl_struct;
|
483
|
-
hsl_struct.h = h / 6 * 360;
|
484
|
-
hsl_struct.s = s * 100;
|
485
|
-
hsl_struct.l = l * 100;
|
486
|
-
|
487
|
-
return hsl_struct;
|
488
|
-
}
|
489
|
-
|
490
|
-
// hue to RGB helper function
|
491
|
-
double h_to_rgb(double m1, double m2, double h) {
|
492
|
-
while (h < 0) h += 1;
|
493
|
-
while (h > 1) h -= 1;
|
494
|
-
if (h*6.0 < 1) return m1 + (m2 - m1)*h*6;
|
495
|
-
if (h*2.0 < 1) return m2;
|
496
|
-
if (h*3.0 < 2) return m1 + (m2 - m1) * (2.0/3.0 - h)*6;
|
497
|
-
return m1;
|
498
|
-
}
|
499
|
-
|
500
|
-
Color_Ptr hsla_impl(double h, double s, double l, double a, Context& ctx, ParserState pstate)
|
501
|
-
{
|
502
|
-
h /= 360.0;
|
503
|
-
s /= 100.0;
|
504
|
-
l /= 100.0;
|
505
|
-
|
506
|
-
if (l < 0) l = 0;
|
507
|
-
if (s < 0) s = 0;
|
508
|
-
if (l > 1) l = 1;
|
509
|
-
if (s > 1) s = 1;
|
510
|
-
while (h < 0) h += 1;
|
511
|
-
while (h > 1) h -= 1;
|
512
|
-
|
513
|
-
// if saturation is exacly zero, we loose
|
514
|
-
// information for hue, since it will evaluate
|
515
|
-
// to zero if converted back from rgb. Setting
|
516
|
-
// saturation to a very tiny number solves this.
|
517
|
-
if (s == 0) s = 1e-10;
|
518
|
-
|
519
|
-
// Algorithm from the CSS3 spec: http://www.w3.org/TR/css3-color/#hsl-color.
|
520
|
-
double m2;
|
521
|
-
if (l <= 0.5) m2 = l*(s+1.0);
|
522
|
-
else m2 = (l+s)-(l*s);
|
523
|
-
double m1 = (l*2.0)-m2;
|
524
|
-
// round the results -- consider moving this into the Color constructor
|
525
|
-
double r = (h_to_rgb(m1, m2, h + 1.0/3.0) * 255.0);
|
526
|
-
double g = (h_to_rgb(m1, m2, h) * 255.0);
|
527
|
-
double b = (h_to_rgb(m1, m2, h - 1.0/3.0) * 255.0);
|
528
|
-
|
529
|
-
return SASS_MEMORY_NEW(Color, pstate, r, g, b, a);
|
530
|
-
}
|
531
|
-
|
532
|
-
Signature hsl_sig = "hsl($hue, $saturation, $lightness)";
|
533
|
-
BUILT_IN(hsl)
|
534
|
-
{
|
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"),
|
553
|
-
1.0,
|
554
|
-
ctx,
|
555
|
-
pstate);
|
556
|
-
}
|
557
|
-
|
558
|
-
Signature hsla_sig = "hsla($hue, $saturation, $lightness, $alpha)";
|
559
|
-
BUILT_IN(hsla)
|
560
|
-
{
|
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"),
|
583
|
-
ctx,
|
584
|
-
pstate);
|
585
|
-
}
|
586
|
-
|
587
|
-
Signature hue_sig = "hue($color)";
|
588
|
-
BUILT_IN(hue)
|
589
|
-
{
|
590
|
-
Color_Ptr rgb_color = ARG("$color", Color);
|
591
|
-
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
592
|
-
rgb_color->g(),
|
593
|
-
rgb_color->b());
|
594
|
-
return SASS_MEMORY_NEW(Number, pstate, hsl_color.h, "deg");
|
595
|
-
}
|
596
|
-
|
597
|
-
Signature saturation_sig = "saturation($color)";
|
598
|
-
BUILT_IN(saturation)
|
599
|
-
{
|
600
|
-
Color_Ptr rgb_color = ARG("$color", Color);
|
601
|
-
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
602
|
-
rgb_color->g(),
|
603
|
-
rgb_color->b());
|
604
|
-
return SASS_MEMORY_NEW(Number, pstate, hsl_color.s, "%");
|
605
|
-
}
|
606
|
-
|
607
|
-
Signature lightness_sig = "lightness($color)";
|
608
|
-
BUILT_IN(lightness)
|
609
|
-
{
|
610
|
-
Color_Ptr rgb_color = ARG("$color", Color);
|
611
|
-
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
612
|
-
rgb_color->g(),
|
613
|
-
rgb_color->b());
|
614
|
-
return SASS_MEMORY_NEW(Number, pstate, hsl_color.l, "%");
|
615
|
-
}
|
616
|
-
|
617
|
-
Signature adjust_hue_sig = "adjust-hue($color, $degrees)";
|
618
|
-
BUILT_IN(adjust_hue)
|
619
|
-
{
|
620
|
-
Color_Ptr rgb_color = ARG("$color", Color);
|
621
|
-
double degrees = ARGVAL("$degrees");
|
622
|
-
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
623
|
-
rgb_color->g(),
|
624
|
-
rgb_color->b());
|
625
|
-
return hsla_impl(hsl_color.h + degrees,
|
626
|
-
hsl_color.s,
|
627
|
-
hsl_color.l,
|
628
|
-
rgb_color->a(),
|
629
|
-
ctx,
|
630
|
-
pstate);
|
631
|
-
}
|
632
|
-
|
633
|
-
Signature lighten_sig = "lighten($color, $amount)";
|
634
|
-
BUILT_IN(lighten)
|
635
|
-
{
|
636
|
-
Color_Ptr rgb_color = ARG("$color", Color);
|
637
|
-
double amount = DARG_U_PRCT("$amount");
|
638
|
-
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
639
|
-
rgb_color->g(),
|
640
|
-
rgb_color->b());
|
641
|
-
//Check lightness is not negative before lighten it
|
642
|
-
double hslcolorL = hsl_color.l;
|
643
|
-
if (hslcolorL < 0) {
|
644
|
-
hslcolorL = 0;
|
645
|
-
}
|
646
|
-
|
647
|
-
return hsla_impl(hsl_color.h,
|
648
|
-
hsl_color.s,
|
649
|
-
hslcolorL + amount,
|
650
|
-
rgb_color->a(),
|
651
|
-
ctx,
|
652
|
-
pstate);
|
653
|
-
}
|
654
|
-
|
655
|
-
Signature darken_sig = "darken($color, $amount)";
|
656
|
-
BUILT_IN(darken)
|
657
|
-
{
|
658
|
-
Color_Ptr rgb_color = ARG("$color", Color);
|
659
|
-
double amount = DARG_U_PRCT("$amount");
|
660
|
-
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
661
|
-
rgb_color->g(),
|
662
|
-
rgb_color->b());
|
663
|
-
|
664
|
-
//Check lightness if not over 100, before darken it
|
665
|
-
double hslcolorL = hsl_color.l;
|
666
|
-
if (hslcolorL > 100) {
|
667
|
-
hslcolorL = 100;
|
668
|
-
}
|
669
|
-
|
670
|
-
return hsla_impl(hsl_color.h,
|
671
|
-
hsl_color.s,
|
672
|
-
hslcolorL - amount,
|
673
|
-
rgb_color->a(),
|
674
|
-
ctx,
|
675
|
-
pstate);
|
676
|
-
}
|
677
|
-
|
678
|
-
Signature saturate_sig = "saturate($color, $amount: false)";
|
679
|
-
BUILT_IN(saturate)
|
680
|
-
{
|
681
|
-
// CSS3 filter function overload: pass literal through directly
|
682
|
-
if (!Cast<Number>(env["$amount"])) {
|
683
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, "saturate(" + env["$color"]->to_string(ctx.c_options) + ")");
|
684
|
-
}
|
685
|
-
|
686
|
-
double amount = DARG_U_PRCT("$amount");
|
687
|
-
Color_Ptr rgb_color = ARG("$color", Color);
|
688
|
-
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
689
|
-
rgb_color->g(),
|
690
|
-
rgb_color->b());
|
691
|
-
|
692
|
-
double hslcolorS = hsl_color.s + amount;
|
693
|
-
|
694
|
-
// Saturation cannot be below 0 or above 100
|
695
|
-
if (hslcolorS < 0) {
|
696
|
-
hslcolorS = 0;
|
697
|
-
}
|
698
|
-
if (hslcolorS > 100) {
|
699
|
-
hslcolorS = 100;
|
700
|
-
}
|
701
|
-
|
702
|
-
return hsla_impl(hsl_color.h,
|
703
|
-
hslcolorS,
|
704
|
-
hsl_color.l,
|
705
|
-
rgb_color->a(),
|
706
|
-
ctx,
|
707
|
-
pstate);
|
708
|
-
}
|
709
|
-
|
710
|
-
Signature desaturate_sig = "desaturate($color, $amount)";
|
711
|
-
BUILT_IN(desaturate)
|
712
|
-
{
|
713
|
-
Color_Ptr rgb_color = ARG("$color", Color);
|
714
|
-
double amount = DARG_U_PRCT("$amount");
|
715
|
-
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
716
|
-
rgb_color->g(),
|
717
|
-
rgb_color->b());
|
718
|
-
|
719
|
-
double hslcolorS = hsl_color.s - amount;
|
720
|
-
|
721
|
-
// Saturation cannot be below 0 or above 100
|
722
|
-
if (hslcolorS <= 0) {
|
723
|
-
hslcolorS = 0;
|
724
|
-
}
|
725
|
-
if (hslcolorS > 100) {
|
726
|
-
hslcolorS = 100;
|
727
|
-
}
|
728
|
-
|
729
|
-
return hsla_impl(hsl_color.h,
|
730
|
-
hslcolorS,
|
731
|
-
hsl_color.l,
|
732
|
-
rgb_color->a(),
|
733
|
-
ctx,
|
734
|
-
pstate);
|
735
|
-
}
|
736
|
-
|
737
|
-
Signature grayscale_sig = "grayscale($color)";
|
738
|
-
BUILT_IN(grayscale)
|
739
|
-
{
|
740
|
-
// CSS3 filter function overload: pass literal through directly
|
741
|
-
Number_Ptr amount = Cast<Number>(env["$color"]);
|
742
|
-
if (amount) {
|
743
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, "grayscale(" + amount->to_string(ctx.c_options) + ")");
|
744
|
-
}
|
745
|
-
|
746
|
-
Color_Ptr rgb_color = ARG("$color", Color);
|
747
|
-
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
748
|
-
rgb_color->g(),
|
749
|
-
rgb_color->b());
|
750
|
-
return hsla_impl(hsl_color.h,
|
751
|
-
0.0,
|
752
|
-
hsl_color.l,
|
753
|
-
rgb_color->a(),
|
754
|
-
ctx,
|
755
|
-
pstate);
|
756
|
-
}
|
757
|
-
|
758
|
-
Signature complement_sig = "complement($color)";
|
759
|
-
BUILT_IN(complement)
|
760
|
-
{
|
761
|
-
Color_Ptr rgb_color = ARG("$color", Color);
|
762
|
-
HSL hsl_color = rgb_to_hsl(rgb_color->r(),
|
763
|
-
rgb_color->g(),
|
764
|
-
rgb_color->b());
|
765
|
-
return hsla_impl(hsl_color.h - 180.0,
|
766
|
-
hsl_color.s,
|
767
|
-
hsl_color.l,
|
768
|
-
rgb_color->a(),
|
769
|
-
ctx,
|
770
|
-
pstate);
|
771
|
-
}
|
772
|
-
|
773
|
-
Signature invert_sig = "invert($color, $weight: 100%)";
|
774
|
-
BUILT_IN(invert)
|
775
|
-
{
|
776
|
-
// CSS3 filter function overload: pass literal through directly
|
777
|
-
Number_Ptr amount = Cast<Number>(env["$color"]);
|
778
|
-
if (amount) {
|
779
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, "invert(" + amount->to_string(ctx.c_options) + ")");
|
780
|
-
}
|
781
|
-
|
782
|
-
double weight = DARG_U_PRCT("$weight");
|
783
|
-
Color_Ptr rgb_color = ARG("$color", Color);
|
784
|
-
Color_Obj inv = SASS_MEMORY_NEW(Color,
|
785
|
-
pstate,
|
786
|
-
255 - rgb_color->r(),
|
787
|
-
255 - rgb_color->g(),
|
788
|
-
255 - rgb_color->b(),
|
789
|
-
rgb_color->a());
|
790
|
-
return colormix(ctx, pstate, inv, rgb_color, weight);
|
791
|
-
}
|
792
|
-
|
793
|
-
////////////////////
|
794
|
-
// OPACITY FUNCTIONS
|
795
|
-
////////////////////
|
796
|
-
Signature alpha_sig = "alpha($color)";
|
797
|
-
Signature opacity_sig = "opacity($color)";
|
798
|
-
BUILT_IN(alpha)
|
799
|
-
{
|
800
|
-
String_Constant_Ptr ie_kwd = Cast<String_Constant>(env["$color"]);
|
801
|
-
if (ie_kwd) {
|
802
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, "alpha(" + ie_kwd->value() + ")");
|
803
|
-
}
|
804
|
-
|
805
|
-
// CSS3 filter function overload: pass literal through directly
|
806
|
-
Number_Ptr amount = Cast<Number>(env["$color"]);
|
807
|
-
if (amount) {
|
808
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, "opacity(" + amount->to_string(ctx.c_options) + ")");
|
809
|
-
}
|
810
|
-
|
811
|
-
return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->a());
|
812
|
-
}
|
813
|
-
|
814
|
-
Signature opacify_sig = "opacify($color, $amount)";
|
815
|
-
Signature fade_in_sig = "fade-in($color, $amount)";
|
816
|
-
BUILT_IN(opacify)
|
817
|
-
{
|
818
|
-
Color_Ptr color = ARG("$color", Color);
|
819
|
-
double amount = DARG_U_FACT("$amount");
|
820
|
-
double alpha = std::min(color->a() + amount, 1.0);
|
821
|
-
return SASS_MEMORY_NEW(Color,
|
822
|
-
pstate,
|
823
|
-
color->r(),
|
824
|
-
color->g(),
|
825
|
-
color->b(),
|
826
|
-
alpha);
|
827
|
-
}
|
828
|
-
|
829
|
-
Signature transparentize_sig = "transparentize($color, $amount)";
|
830
|
-
Signature fade_out_sig = "fade-out($color, $amount)";
|
831
|
-
BUILT_IN(transparentize)
|
832
|
-
{
|
833
|
-
Color_Ptr color = ARG("$color", Color);
|
834
|
-
double amount = DARG_U_FACT("$amount");
|
835
|
-
double alpha = std::max(color->a() - amount, 0.0);
|
836
|
-
return SASS_MEMORY_NEW(Color,
|
837
|
-
pstate,
|
838
|
-
color->r(),
|
839
|
-
color->g(),
|
840
|
-
color->b(),
|
841
|
-
alpha);
|
842
|
-
}
|
843
|
-
|
844
|
-
////////////////////////
|
845
|
-
// OTHER COLOR FUNCTIONS
|
846
|
-
////////////////////////
|
847
|
-
|
848
|
-
Signature adjust_color_sig = "adjust-color($color, $red: false, $green: false, $blue: false, $hue: false, $saturation: false, $lightness: false, $alpha: false)";
|
849
|
-
BUILT_IN(adjust_color)
|
850
|
-
{
|
851
|
-
Color_Ptr color = ARG("$color", Color);
|
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"]);
|
859
|
-
|
860
|
-
bool rgb = r || g || b;
|
861
|
-
bool hsl = h || s || l;
|
862
|
-
|
863
|
-
if (rgb && hsl) {
|
864
|
-
error("Cannot specify HSL and RGB values for a color at the same time for `adjust-color'", pstate, traces);
|
865
|
-
}
|
866
|
-
if (rgb) {
|
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;
|
871
|
-
return SASS_MEMORY_NEW(Color,
|
872
|
-
pstate,
|
873
|
-
color->r() + rr,
|
874
|
-
color->g() + gg,
|
875
|
-
color->b() + bb,
|
876
|
-
color->a() + aa);
|
877
|
-
}
|
878
|
-
if (hsl) {
|
879
|
-
HSL hsl_struct = rgb_to_hsl(color->r(), color->g(), color->b());
|
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;
|
883
|
-
return hsla_impl(hsl_struct.h + (h ? h->value() : 0),
|
884
|
-
hsl_struct.s + ss,
|
885
|
-
hsl_struct.l + ll,
|
886
|
-
color->a() + aa,
|
887
|
-
ctx,
|
888
|
-
pstate);
|
889
|
-
}
|
890
|
-
if (a) {
|
891
|
-
return SASS_MEMORY_NEW(Color,
|
892
|
-
pstate,
|
893
|
-
color->r(),
|
894
|
-
color->g(),
|
895
|
-
color->b(),
|
896
|
-
color->a() + (a ? a->value() : 0));
|
897
|
-
}
|
898
|
-
error("not enough arguments for `adjust-color'", pstate, traces);
|
899
|
-
// unreachable
|
900
|
-
return color;
|
901
|
-
}
|
902
|
-
|
903
|
-
Signature scale_color_sig = "scale-color($color, $red: false, $green: false, $blue: false, $hue: false, $saturation: false, $lightness: false, $alpha: false)";
|
904
|
-
BUILT_IN(scale_color)
|
905
|
-
{
|
906
|
-
Color_Ptr color = ARG("$color", Color);
|
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"]);
|
914
|
-
|
915
|
-
bool rgb = r || g || b;
|
916
|
-
bool hsl = h || s || l;
|
917
|
-
|
918
|
-
if (rgb && hsl) {
|
919
|
-
error("Cannot specify HSL and RGB values for a color at the same time for `scale-color'", pstate, traces);
|
920
|
-
}
|
921
|
-
if (rgb) {
|
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;
|
926
|
-
return SASS_MEMORY_NEW(Color,
|
927
|
-
pstate,
|
928
|
-
color->r() + rscale * (rscale > 0.0 ? 255 - color->r() : color->r()),
|
929
|
-
color->g() + gscale * (gscale > 0.0 ? 255 - color->g() : color->g()),
|
930
|
-
color->b() + bscale * (bscale > 0.0 ? 255 - color->b() : color->b()),
|
931
|
-
color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->a()));
|
932
|
-
}
|
933
|
-
if (hsl) {
|
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;
|
938
|
-
HSL hsl_struct = rgb_to_hsl(color->r(), color->g(), color->b());
|
939
|
-
hsl_struct.h += hscale * (hscale > 0.0 ? 360.0 - hsl_struct.h : hsl_struct.h);
|
940
|
-
hsl_struct.s += sscale * (sscale > 0.0 ? 100.0 - hsl_struct.s : hsl_struct.s);
|
941
|
-
hsl_struct.l += lscale * (lscale > 0.0 ? 100.0 - hsl_struct.l : hsl_struct.l);
|
942
|
-
double alpha = color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->a());
|
943
|
-
return hsla_impl(hsl_struct.h, hsl_struct.s, hsl_struct.l, alpha, ctx, pstate);
|
944
|
-
}
|
945
|
-
if (a) {
|
946
|
-
double ascale = (DARG_R_PRCT("$alpha")) / 100.0;
|
947
|
-
return SASS_MEMORY_NEW(Color,
|
948
|
-
pstate,
|
949
|
-
color->r(),
|
950
|
-
color->g(),
|
951
|
-
color->b(),
|
952
|
-
color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->a()));
|
953
|
-
}
|
954
|
-
error("not enough arguments for `scale-color'", pstate, traces);
|
955
|
-
// unreachable
|
956
|
-
return color;
|
957
|
-
}
|
958
|
-
|
959
|
-
Signature change_color_sig = "change-color($color, $red: false, $green: false, $blue: false, $hue: false, $saturation: false, $lightness: false, $alpha: false)";
|
960
|
-
BUILT_IN(change_color)
|
961
|
-
{
|
962
|
-
Color_Ptr color = ARG("$color", Color);
|
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"]);
|
970
|
-
|
971
|
-
bool rgb = r || g || b;
|
972
|
-
bool hsl = h || s || l;
|
973
|
-
|
974
|
-
if (rgb && hsl) {
|
975
|
-
error("Cannot specify HSL and RGB values for a color at the same time for `change-color'", pstate, traces);
|
976
|
-
}
|
977
|
-
if (rgb) {
|
978
|
-
return SASS_MEMORY_NEW(Color,
|
979
|
-
pstate,
|
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());
|
984
|
-
}
|
985
|
-
if (hsl) {
|
986
|
-
HSL hsl_struct = rgb_to_hsl(color->r(), color->g(), color->b());
|
987
|
-
if (h) hsl_struct.h = std::fmod(h->value(), 360.0);
|
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();
|
991
|
-
return hsla_impl(hsl_struct.h, hsl_struct.s, hsl_struct.l, alpha, ctx, pstate);
|
992
|
-
}
|
993
|
-
if (a) {
|
994
|
-
double alpha = DARG_U_FACT("$alpha");
|
995
|
-
return SASS_MEMORY_NEW(Color,
|
996
|
-
pstate,
|
997
|
-
color->r(),
|
998
|
-
color->g(),
|
999
|
-
color->b(),
|
1000
|
-
alpha);
|
1001
|
-
}
|
1002
|
-
error("not enough arguments for `change-color'", pstate, traces);
|
1003
|
-
// unreachable
|
1004
|
-
return color;
|
1005
|
-
}
|
1006
|
-
|
1007
|
-
template <size_t range>
|
1008
|
-
static double cap_channel(double c) {
|
1009
|
-
if (c > range) return range;
|
1010
|
-
else if (c < 0) return 0;
|
1011
|
-
else return c;
|
1012
|
-
}
|
1013
|
-
|
1014
|
-
Signature ie_hex_str_sig = "ie-hex-str($color)";
|
1015
|
-
BUILT_IN(ie_hex_str)
|
1016
|
-
{
|
1017
|
-
Color_Ptr c = ARG("$color", Color);
|
1018
|
-
double r = cap_channel<0xff>(c->r());
|
1019
|
-
double g = cap_channel<0xff>(c->g());
|
1020
|
-
double b = cap_channel<0xff>(c->b());
|
1021
|
-
double a = cap_channel<1> (c->a()) * 255;
|
1022
|
-
|
1023
|
-
std::stringstream ss;
|
1024
|
-
ss << '#' << std::setw(2) << std::setfill('0');
|
1025
|
-
ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(a, ctx.c_options.precision));
|
1026
|
-
ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(r, ctx.c_options.precision));
|
1027
|
-
ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(g, ctx.c_options.precision));
|
1028
|
-
ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(b, ctx.c_options.precision));
|
1029
|
-
|
1030
|
-
std::string result(ss.str());
|
1031
|
-
for (size_t i = 0, L = result.length(); i < L; ++i) {
|
1032
|
-
result[i] = std::toupper(result[i]);
|
1033
|
-
}
|
1034
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, result);
|
1035
|
-
}
|
1036
|
-
|
1037
|
-
///////////////////
|
1038
|
-
// STRING FUNCTIONS
|
1039
|
-
///////////////////
|
1040
|
-
|
1041
|
-
Signature unquote_sig = "unquote($string)";
|
1042
|
-
BUILT_IN(sass_unquote)
|
1043
|
-
{
|
1044
|
-
AST_Node_Obj arg = env["$string"];
|
1045
|
-
if (String_Quoted_Ptr string_quoted = Cast<String_Quoted>(arg)) {
|
1046
|
-
String_Constant_Ptr result = SASS_MEMORY_NEW(String_Constant, pstate, string_quoted->value());
|
1047
|
-
// remember if the string was quoted (color tokens)
|
1048
|
-
result->is_delayed(true); // delay colors
|
1049
|
-
return result;
|
1050
|
-
}
|
1051
|
-
else if (String_Constant_Ptr str = Cast<String_Constant>(arg)) {
|
1052
|
-
return str;
|
1053
|
-
}
|
1054
|
-
else if (Expression_Ptr ex = Cast<Expression>(arg)) {
|
1055
|
-
Sass_Output_Style oldstyle = ctx.c_options.output_style;
|
1056
|
-
ctx.c_options.output_style = SASS_STYLE_NESTED;
|
1057
|
-
std::string val(arg->to_string(ctx.c_options));
|
1058
|
-
val = Cast<Null>(arg) ? "null" : val;
|
1059
|
-
ctx.c_options.output_style = oldstyle;
|
1060
|
-
|
1061
|
-
deprecated_function("Passing " + val + ", a non-string value, to unquote()", pstate);
|
1062
|
-
return ex;
|
1063
|
-
}
|
1064
|
-
throw std::runtime_error("Invalid Data Type for unquote");
|
1065
|
-
}
|
1066
|
-
|
1067
|
-
Signature quote_sig = "quote($string)";
|
1068
|
-
BUILT_IN(sass_quote)
|
1069
|
-
{
|
1070
|
-
AST_Node_Obj arg = env["$string"];
|
1071
|
-
// only set quote mark to true if already a string
|
1072
|
-
if (String_Quoted_Ptr qstr = Cast<String_Quoted>(arg)) {
|
1073
|
-
qstr->quote_mark('*');
|
1074
|
-
return qstr;
|
1075
|
-
}
|
1076
|
-
// all other nodes must be converted to a string node
|
1077
|
-
std::string str(quote(arg->to_string(ctx.c_options), String_Constant::double_quote()));
|
1078
|
-
String_Quoted_Ptr result = SASS_MEMORY_NEW(String_Quoted, pstate, str);
|
1079
|
-
result->quote_mark('*');
|
1080
|
-
return result;
|
1081
|
-
}
|
1082
|
-
|
1083
|
-
|
1084
|
-
Signature str_length_sig = "str-length($string)";
|
1085
|
-
BUILT_IN(str_length)
|
1086
|
-
{
|
1087
|
-
size_t len = std::string::npos;
|
1088
|
-
try {
|
1089
|
-
String_Constant_Ptr s = ARG("$string", String_Constant);
|
1090
|
-
len = UTF_8::code_point_count(s->value(), 0, s->value().size());
|
1091
|
-
|
1092
|
-
}
|
1093
|
-
// handle any invalid utf8 errors
|
1094
|
-
// other errors will be re-thrown
|
1095
|
-
catch (...) { handle_utf8_error(pstate, traces); }
|
1096
|
-
// return something even if we had an error (-1)
|
1097
|
-
return SASS_MEMORY_NEW(Number, pstate, (double)len);
|
1098
|
-
}
|
1099
|
-
|
1100
|
-
Signature str_insert_sig = "str-insert($string, $insert, $index)";
|
1101
|
-
BUILT_IN(str_insert)
|
1102
|
-
{
|
1103
|
-
std::string str;
|
1104
|
-
try {
|
1105
|
-
String_Constant_Ptr s = ARG("$string", String_Constant);
|
1106
|
-
str = s->value();
|
1107
|
-
str = unquote(str);
|
1108
|
-
String_Constant_Ptr i = ARG("$insert", String_Constant);
|
1109
|
-
std::string ins = i->value();
|
1110
|
-
ins = unquote(ins);
|
1111
|
-
double index = ARGVAL("$index");
|
1112
|
-
size_t len = UTF_8::code_point_count(str, 0, str.size());
|
1113
|
-
|
1114
|
-
if (index > 0 && index <= len) {
|
1115
|
-
// positive and within string length
|
1116
|
-
str.insert(UTF_8::offset_at_position(str, static_cast<size_t>(index) - 1), ins);
|
1117
|
-
}
|
1118
|
-
else if (index > len) {
|
1119
|
-
// positive and past string length
|
1120
|
-
str += ins;
|
1121
|
-
}
|
1122
|
-
else if (index == 0) {
|
1123
|
-
str = ins + str;
|
1124
|
-
}
|
1125
|
-
else if (std::abs(index) <= len) {
|
1126
|
-
// negative and within string length
|
1127
|
-
index += len + 1;
|
1128
|
-
str.insert(UTF_8::offset_at_position(str, static_cast<size_t>(index)), ins);
|
1129
|
-
}
|
1130
|
-
else {
|
1131
|
-
// negative and past string length
|
1132
|
-
str = ins + str;
|
1133
|
-
}
|
1134
|
-
|
1135
|
-
if (String_Quoted_Ptr ss = Cast<String_Quoted>(s)) {
|
1136
|
-
if (ss->quote_mark()) str = quote(str);
|
1137
|
-
}
|
1138
|
-
}
|
1139
|
-
// handle any invalid utf8 errors
|
1140
|
-
// other errors will be re-thrown
|
1141
|
-
catch (...) { handle_utf8_error(pstate, traces); }
|
1142
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, str);
|
1143
|
-
}
|
1144
|
-
|
1145
|
-
Signature str_index_sig = "str-index($string, $substring)";
|
1146
|
-
BUILT_IN(str_index)
|
1147
|
-
{
|
1148
|
-
size_t index = std::string::npos;
|
1149
|
-
try {
|
1150
|
-
String_Constant_Ptr s = ARG("$string", String_Constant);
|
1151
|
-
String_Constant_Ptr t = ARG("$substring", String_Constant);
|
1152
|
-
std::string str = s->value();
|
1153
|
-
str = unquote(str);
|
1154
|
-
std::string substr = t->value();
|
1155
|
-
substr = unquote(substr);
|
1156
|
-
|
1157
|
-
size_t c_index = str.find(substr);
|
1158
|
-
if(c_index == std::string::npos) {
|
1159
|
-
return SASS_MEMORY_NEW(Null, pstate);
|
1160
|
-
}
|
1161
|
-
index = UTF_8::code_point_count(str, 0, c_index) + 1;
|
1162
|
-
}
|
1163
|
-
// handle any invalid utf8 errors
|
1164
|
-
// other errors will be re-thrown
|
1165
|
-
catch (...) { handle_utf8_error(pstate, traces); }
|
1166
|
-
// return something even if we had an error (-1)
|
1167
|
-
return SASS_MEMORY_NEW(Number, pstate, (double)index);
|
1168
|
-
}
|
1169
|
-
|
1170
|
-
Signature str_slice_sig = "str-slice($string, $start-at, $end-at:-1)";
|
1171
|
-
BUILT_IN(str_slice)
|
1172
|
-
{
|
1173
|
-
std::string newstr;
|
1174
|
-
try {
|
1175
|
-
String_Constant_Ptr s = ARG("$string", String_Constant);
|
1176
|
-
double start_at = ARGVAL("$start-at");
|
1177
|
-
double end_at = ARGVAL("$end-at");
|
1178
|
-
String_Quoted_Ptr ss = Cast<String_Quoted>(s);
|
1179
|
-
|
1180
|
-
std::string str = unquote(s->value());
|
1181
|
-
|
1182
|
-
size_t size = utf8::distance(str.begin(), str.end());
|
1183
|
-
|
1184
|
-
if (!Cast<Number>(env["$end-at"])) {
|
1185
|
-
end_at = -1;
|
1186
|
-
}
|
1187
|
-
|
1188
|
-
if (end_at == 0 || (end_at + size) < 0) {
|
1189
|
-
if (ss && ss->quote_mark()) newstr = quote("");
|
1190
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, newstr);
|
1191
|
-
}
|
1192
|
-
|
1193
|
-
if (end_at < 0) {
|
1194
|
-
end_at += size + 1;
|
1195
|
-
if (end_at == 0) end_at = 1;
|
1196
|
-
}
|
1197
|
-
if (end_at > size) { end_at = (double)size; }
|
1198
|
-
if (start_at < 0) {
|
1199
|
-
start_at += size + 1;
|
1200
|
-
if (start_at < 0) start_at = 0;
|
1201
|
-
}
|
1202
|
-
else if (start_at == 0) { ++ start_at; }
|
1203
|
-
|
1204
|
-
if (start_at <= end_at)
|
1205
|
-
{
|
1206
|
-
std::string::iterator start = str.begin();
|
1207
|
-
utf8::advance(start, start_at - 1, str.end());
|
1208
|
-
std::string::iterator end = start;
|
1209
|
-
utf8::advance(end, end_at - start_at + 1, str.end());
|
1210
|
-
newstr = std::string(start, end);
|
1211
|
-
}
|
1212
|
-
if (ss) {
|
1213
|
-
if(ss->quote_mark()) newstr = quote(newstr);
|
1214
|
-
}
|
1215
|
-
}
|
1216
|
-
// handle any invalid utf8 errors
|
1217
|
-
// other errors will be re-thrown
|
1218
|
-
catch (...) { handle_utf8_error(pstate, traces); }
|
1219
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, newstr);
|
1220
|
-
}
|
1221
|
-
|
1222
|
-
Signature to_upper_case_sig = "to-upper-case($string)";
|
1223
|
-
BUILT_IN(to_upper_case)
|
1224
|
-
{
|
1225
|
-
String_Constant_Ptr s = ARG("$string", String_Constant);
|
1226
|
-
std::string str = s->value();
|
1227
|
-
|
1228
|
-
for (size_t i = 0, L = str.length(); i < L; ++i) {
|
1229
|
-
if (Sass::Util::isAscii(str[i])) {
|
1230
|
-
str[i] = std::toupper(str[i]);
|
1231
|
-
}
|
1232
|
-
}
|
1233
|
-
|
1234
|
-
if (String_Quoted_Ptr ss = Cast<String_Quoted>(s)) {
|
1235
|
-
String_Quoted_Ptr cpy = SASS_MEMORY_COPY(ss);
|
1236
|
-
cpy->value(str);
|
1237
|
-
return cpy;
|
1238
|
-
} else {
|
1239
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, str);
|
1240
|
-
}
|
1241
|
-
}
|
1242
|
-
|
1243
|
-
Signature to_lower_case_sig = "to-lower-case($string)";
|
1244
|
-
BUILT_IN(to_lower_case)
|
1245
|
-
{
|
1246
|
-
String_Constant_Ptr s = ARG("$string", String_Constant);
|
1247
|
-
std::string str = s->value();
|
1248
|
-
|
1249
|
-
for (size_t i = 0, L = str.length(); i < L; ++i) {
|
1250
|
-
if (Sass::Util::isAscii(str[i])) {
|
1251
|
-
str[i] = std::tolower(str[i]);
|
1252
|
-
}
|
1253
|
-
}
|
1254
|
-
|
1255
|
-
if (String_Quoted_Ptr ss = Cast<String_Quoted>(s)) {
|
1256
|
-
String_Quoted_Ptr cpy = SASS_MEMORY_COPY(ss);
|
1257
|
-
cpy->value(str);
|
1258
|
-
return cpy;
|
1259
|
-
} else {
|
1260
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, str);
|
1261
|
-
}
|
1262
|
-
}
|
1263
|
-
|
1264
|
-
///////////////////
|
1265
|
-
// NUMBER FUNCTIONS
|
1266
|
-
///////////////////
|
1267
|
-
|
1268
|
-
Signature percentage_sig = "percentage($number)";
|
1269
|
-
BUILT_IN(percentage)
|
1270
|
-
{
|
1271
|
-
Number_Obj n = ARGN("$number");
|
1272
|
-
if (!n->is_unitless()) error("argument $number of `" + std::string(sig) + "` must be unitless", pstate, traces);
|
1273
|
-
return SASS_MEMORY_NEW(Number, pstate, n->value() * 100, "%");
|
1274
|
-
}
|
1275
|
-
|
1276
|
-
Signature round_sig = "round($number)";
|
1277
|
-
BUILT_IN(round)
|
1278
|
-
{
|
1279
|
-
Number_Obj r = ARGN("$number");
|
1280
|
-
r->value(Sass::round(r->value(), ctx.c_options.precision));
|
1281
|
-
r->pstate(pstate);
|
1282
|
-
return r.detach();
|
1283
|
-
}
|
1284
|
-
|
1285
|
-
Signature ceil_sig = "ceil($number)";
|
1286
|
-
BUILT_IN(ceil)
|
1287
|
-
{
|
1288
|
-
Number_Obj r = ARGN("$number");
|
1289
|
-
r->value(std::ceil(r->value()));
|
1290
|
-
r->pstate(pstate);
|
1291
|
-
return r.detach();
|
1292
|
-
}
|
1293
|
-
|
1294
|
-
Signature floor_sig = "floor($number)";
|
1295
|
-
BUILT_IN(floor)
|
1296
|
-
{
|
1297
|
-
Number_Obj r = ARGN("$number");
|
1298
|
-
r->value(std::floor(r->value()));
|
1299
|
-
r->pstate(pstate);
|
1300
|
-
return r.detach();
|
1301
|
-
}
|
1302
|
-
|
1303
|
-
Signature abs_sig = "abs($number)";
|
1304
|
-
BUILT_IN(abs)
|
1305
|
-
{
|
1306
|
-
Number_Obj r = ARGN("$number");
|
1307
|
-
r->value(std::abs(r->value()));
|
1308
|
-
r->pstate(pstate);
|
1309
|
-
return r.detach();
|
1310
|
-
}
|
1311
|
-
|
1312
|
-
Signature min_sig = "min($numbers...)";
|
1313
|
-
BUILT_IN(min)
|
1314
|
-
{
|
1315
|
-
List_Ptr arglist = ARG("$numbers", List);
|
1316
|
-
Number_Obj least = NULL;
|
1317
|
-
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
1318
|
-
Expression_Obj val = arglist->value_at_index(i);
|
1319
|
-
Number_Obj xi = Cast<Number>(val);
|
1320
|
-
if (!xi) {
|
1321
|
-
error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `min'", pstate, traces);
|
1322
|
-
}
|
1323
|
-
if (least) {
|
1324
|
-
if (*xi < *least) least = xi;
|
1325
|
-
} else least = xi;
|
1326
|
-
}
|
1327
|
-
return least.detach();
|
1328
|
-
}
|
1329
|
-
|
1330
|
-
Signature max_sig = "max($numbers...)";
|
1331
|
-
BUILT_IN(max)
|
1332
|
-
{
|
1333
|
-
List_Ptr arglist = ARG("$numbers", List);
|
1334
|
-
Number_Obj greatest = NULL;
|
1335
|
-
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
1336
|
-
Expression_Obj val = arglist->value_at_index(i);
|
1337
|
-
Number_Obj xi = Cast<Number>(val);
|
1338
|
-
if (!xi) {
|
1339
|
-
error("\"" + val->to_string(ctx.c_options) + "\" is not a number for `max'", pstate, traces);
|
1340
|
-
}
|
1341
|
-
if (greatest) {
|
1342
|
-
if (*greatest < *xi) greatest = xi;
|
1343
|
-
} else greatest = xi;
|
1344
|
-
}
|
1345
|
-
return greatest.detach();
|
1346
|
-
}
|
1347
|
-
|
1348
|
-
Signature random_sig = "random($limit:false)";
|
1349
|
-
BUILT_IN(random)
|
1350
|
-
{
|
1351
|
-
AST_Node_Obj arg = env["$limit"];
|
1352
|
-
Value_Ptr v = Cast<Value>(arg);
|
1353
|
-
Number_Ptr l = Cast<Number>(arg);
|
1354
|
-
Boolean_Ptr b = Cast<Boolean>(arg);
|
1355
|
-
if (l) {
|
1356
|
-
double lv = l->value();
|
1357
|
-
if (lv < 1) {
|
1358
|
-
stringstream err;
|
1359
|
-
err << "$limit " << lv << " must be greater than or equal to 1 for `random'";
|
1360
|
-
error(err.str(), pstate, traces);
|
1361
|
-
}
|
1362
|
-
bool eq_int = std::fabs(trunc(lv) - lv) < NUMBER_EPSILON;
|
1363
|
-
if (!eq_int) {
|
1364
|
-
stringstream err;
|
1365
|
-
err << "Expected $limit to be an integer but got " << lv << " for `random'";
|
1366
|
-
error(err.str(), pstate, traces);
|
1367
|
-
}
|
1368
|
-
std::uniform_real_distribution<> distributor(1, lv + 1);
|
1369
|
-
uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
|
1370
|
-
return SASS_MEMORY_NEW(Number, pstate, (double)distributed);
|
1371
|
-
}
|
1372
|
-
else if (b) {
|
1373
|
-
std::uniform_real_distribution<> distributor(0, 1);
|
1374
|
-
double distributed = static_cast<double>(distributor(rand));
|
1375
|
-
return SASS_MEMORY_NEW(Number, pstate, distributed);
|
1376
|
-
} else if (v) {
|
1377
|
-
traces.push_back(Backtrace(pstate));
|
1378
|
-
throw Exception::InvalidArgumentType(pstate, traces, "random", "$limit", "number", v);
|
1379
|
-
} else {
|
1380
|
-
traces.push_back(Backtrace(pstate));
|
1381
|
-
throw Exception::InvalidArgumentType(pstate, traces, "random", "$limit", "number");
|
1382
|
-
}
|
1383
|
-
}
|
1384
|
-
|
1385
|
-
/////////////////
|
1386
|
-
// LIST FUNCTIONS
|
1387
|
-
/////////////////
|
1388
|
-
|
1389
|
-
Signature length_sig = "length($list)";
|
1390
|
-
BUILT_IN(length)
|
1391
|
-
{
|
1392
|
-
if (Selector_List_Ptr sl = Cast<Selector_List>(env["$list"])) {
|
1393
|
-
return SASS_MEMORY_NEW(Number, pstate, (double)sl->length());
|
1394
|
-
}
|
1395
|
-
Expression_Ptr v = ARG("$list", Expression);
|
1396
|
-
if (v->concrete_type() == Expression::MAP) {
|
1397
|
-
Map_Ptr map = Cast<Map>(env["$list"]);
|
1398
|
-
return SASS_MEMORY_NEW(Number, pstate, (double)(map ? map->length() : 1));
|
1399
|
-
}
|
1400
|
-
if (v->concrete_type() == Expression::SELECTOR) {
|
1401
|
-
if (Compound_Selector_Ptr h = Cast<Compound_Selector>(v)) {
|
1402
|
-
return SASS_MEMORY_NEW(Number, pstate, (double)h->length());
|
1403
|
-
} else if (Selector_List_Ptr ls = Cast<Selector_List>(v)) {
|
1404
|
-
return SASS_MEMORY_NEW(Number, pstate, (double)ls->length());
|
1405
|
-
} else {
|
1406
|
-
return SASS_MEMORY_NEW(Number, pstate, 1);
|
1407
|
-
}
|
1408
|
-
}
|
1409
|
-
|
1410
|
-
List_Ptr list = Cast<List>(env["$list"]);
|
1411
|
-
return SASS_MEMORY_NEW(Number,
|
1412
|
-
pstate,
|
1413
|
-
(double)(list ? list->size() : 1));
|
1414
|
-
}
|
1415
|
-
|
1416
|
-
Signature nth_sig = "nth($list, $n)";
|
1417
|
-
BUILT_IN(nth)
|
1418
|
-
{
|
1419
|
-
double nr = ARGVAL("$n");
|
1420
|
-
Map_Ptr m = Cast<Map>(env["$list"]);
|
1421
|
-
if (Selector_List_Ptr sl = Cast<Selector_List>(env["$list"])) {
|
1422
|
-
size_t len = m ? m->length() : sl->length();
|
1423
|
-
bool empty = m ? m->empty() : sl->empty();
|
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);
|
1427
|
-
// return (*sl)[static_cast<int>(index)];
|
1428
|
-
Listize listize;
|
1429
|
-
return (*sl)[static_cast<int>(index)]->perform(&listize);
|
1430
|
-
}
|
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);
|
1433
|
-
// if the argument isn't a list, then wrap it in a singleton list
|
1434
|
-
if (!m && !l) {
|
1435
|
-
l = SASS_MEMORY_NEW(List, pstate, 1);
|
1436
|
-
l->append(ARG("$list", Expression));
|
1437
|
-
}
|
1438
|
-
size_t len = m ? m->length() : l->length();
|
1439
|
-
bool empty = m ? m->empty() : l->empty();
|
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);
|
1443
|
-
|
1444
|
-
if (m) {
|
1445
|
-
l = SASS_MEMORY_NEW(List, pstate, 1);
|
1446
|
-
l->append(m->keys()[static_cast<unsigned int>(index)]);
|
1447
|
-
l->append(m->at(m->keys()[static_cast<unsigned int>(index)]));
|
1448
|
-
return l.detach();
|
1449
|
-
}
|
1450
|
-
else {
|
1451
|
-
Expression_Obj rv = l->value_at_index(static_cast<int>(index));
|
1452
|
-
rv->set_delayed(false);
|
1453
|
-
return rv.detach();
|
1454
|
-
}
|
1455
|
-
}
|
1456
|
-
|
1457
|
-
Signature set_nth_sig = "set-nth($list, $n, $value)";
|
1458
|
-
BUILT_IN(set_nth)
|
1459
|
-
{
|
1460
|
-
Map_Obj m = Cast<Map>(env["$list"]);
|
1461
|
-
List_Obj l = Cast<List>(env["$list"]);
|
1462
|
-
Number_Obj n = ARG("$n", Number);
|
1463
|
-
Expression_Obj v = ARG("$value", Expression);
|
1464
|
-
if (!l) {
|
1465
|
-
l = SASS_MEMORY_NEW(List, pstate, 1);
|
1466
|
-
l->append(ARG("$list", Expression));
|
1467
|
-
}
|
1468
|
-
if (m) {
|
1469
|
-
l = m->to_list(pstate);
|
1470
|
-
}
|
1471
|
-
if (l->empty()) error("argument `$list` of `" + std::string(sig) + "` must not be empty", pstate, traces);
|
1472
|
-
double index = std::floor(n->value() < 0 ? l->length() + n->value() : n->value() - 1);
|
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());
|
1475
|
-
for (size_t i = 0, L = l->length(); i < L; ++i) {
|
1476
|
-
result->append(((i == index) ? v : (*l)[i]));
|
1477
|
-
}
|
1478
|
-
return result;
|
1479
|
-
}
|
1480
|
-
|
1481
|
-
Signature index_sig = "index($list, $value)";
|
1482
|
-
BUILT_IN(index)
|
1483
|
-
{
|
1484
|
-
Map_Obj m = Cast<Map>(env["$list"]);
|
1485
|
-
List_Obj l = Cast<List>(env["$list"]);
|
1486
|
-
Expression_Obj v = ARG("$value", Expression);
|
1487
|
-
if (!l) {
|
1488
|
-
l = SASS_MEMORY_NEW(List, pstate, 1);
|
1489
|
-
l->append(ARG("$list", Expression));
|
1490
|
-
}
|
1491
|
-
if (m) {
|
1492
|
-
l = m->to_list(pstate);
|
1493
|
-
}
|
1494
|
-
for (size_t i = 0, L = l->length(); i < L; ++i) {
|
1495
|
-
if (Operators::eq(l->value_at_index(i), v)) return SASS_MEMORY_NEW(Number, pstate, (double)(i+1));
|
1496
|
-
}
|
1497
|
-
return SASS_MEMORY_NEW(Null, pstate);
|
1498
|
-
}
|
1499
|
-
|
1500
|
-
Signature join_sig = "join($list1, $list2, $separator: auto, $bracketed: auto)";
|
1501
|
-
BUILT_IN(join)
|
1502
|
-
{
|
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"]);
|
1507
|
-
String_Constant_Obj sep = ARG("$separator", String_Constant);
|
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);
|
1511
|
-
if (!l1) {
|
1512
|
-
l1 = SASS_MEMORY_NEW(List, pstate, 1);
|
1513
|
-
l1->append(ARG("$list1", Expression));
|
1514
|
-
sep_val = (l2 ? l2->separator() : SASS_SPACE);
|
1515
|
-
is_bracketed = (l2 ? l2->is_bracketed() : false);
|
1516
|
-
}
|
1517
|
-
if (!l2) {
|
1518
|
-
l2 = SASS_MEMORY_NEW(List, pstate, 1);
|
1519
|
-
l2->append(ARG("$list2", Expression));
|
1520
|
-
}
|
1521
|
-
if (m1) {
|
1522
|
-
l1 = m1->to_list(pstate);
|
1523
|
-
sep_val = SASS_COMMA;
|
1524
|
-
}
|
1525
|
-
if (m2) {
|
1526
|
-
l2 = m2->to_list(pstate);
|
1527
|
-
}
|
1528
|
-
size_t len = l1->length() + l2->length();
|
1529
|
-
std::string sep_str = unquote(sep->value());
|
1530
|
-
if (sep_str == "space") sep_val = SASS_SPACE;
|
1531
|
-
else if (sep_str == "comma") sep_val = SASS_COMMA;
|
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);
|
1541
|
-
return result.detach();
|
1542
|
-
}
|
1543
|
-
|
1544
|
-
Signature append_sig = "append($list, $val, $separator: auto)";
|
1545
|
-
BUILT_IN(append)
|
1546
|
-
{
|
1547
|
-
Map_Obj m = Cast<Map>(env["$list"]);
|
1548
|
-
List_Obj l = Cast<List>(env["$list"]);
|
1549
|
-
Expression_Obj v = ARG("$val", Expression);
|
1550
|
-
if (Selector_List_Ptr sl = Cast<Selector_List>(env["$list"])) {
|
1551
|
-
Listize listize;
|
1552
|
-
l = Cast<List>(sl->perform(&listize));
|
1553
|
-
}
|
1554
|
-
String_Constant_Obj sep = ARG("$separator", String_Constant);
|
1555
|
-
if (!l) {
|
1556
|
-
l = SASS_MEMORY_NEW(List, pstate, 1);
|
1557
|
-
l->append(ARG("$list", Expression));
|
1558
|
-
}
|
1559
|
-
if (m) {
|
1560
|
-
l = m->to_list(pstate);
|
1561
|
-
}
|
1562
|
-
List_Ptr result = SASS_MEMORY_COPY(l);
|
1563
|
-
std::string sep_str(unquote(sep->value()));
|
1564
|
-
if (sep_str != "auto") { // check default first
|
1565
|
-
if (sep_str == "space") result->separator(SASS_SPACE);
|
1566
|
-
else if (sep_str == "comma") result->separator(SASS_COMMA);
|
1567
|
-
else error("argument `$separator` of `" + std::string(sig) + "` must be `space`, `comma`, or `auto`", pstate, traces);
|
1568
|
-
}
|
1569
|
-
if (l->is_arglist()) {
|
1570
|
-
result->append(SASS_MEMORY_NEW(Argument,
|
1571
|
-
v->pstate(),
|
1572
|
-
v,
|
1573
|
-
"",
|
1574
|
-
false,
|
1575
|
-
false));
|
1576
|
-
|
1577
|
-
} else {
|
1578
|
-
result->append(v);
|
1579
|
-
}
|
1580
|
-
return result;
|
1581
|
-
}
|
1582
|
-
|
1583
|
-
Signature zip_sig = "zip($lists...)";
|
1584
|
-
BUILT_IN(zip)
|
1585
|
-
{
|
1586
|
-
List_Obj arglist = SASS_MEMORY_COPY(ARG("$lists", List));
|
1587
|
-
size_t shortest = 0;
|
1588
|
-
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
1589
|
-
List_Obj ith = Cast<List>(arglist->value_at_index(i));
|
1590
|
-
Map_Obj mith = Cast<Map>(arglist->value_at_index(i));
|
1591
|
-
if (!ith) {
|
1592
|
-
if (mith) {
|
1593
|
-
ith = mith->to_list(pstate);
|
1594
|
-
} else {
|
1595
|
-
ith = SASS_MEMORY_NEW(List, pstate, 1);
|
1596
|
-
ith->append(arglist->value_at_index(i));
|
1597
|
-
}
|
1598
|
-
if (arglist->is_arglist()) {
|
1599
|
-
Argument_Obj arg = (Argument_Ptr)(arglist->at(i).ptr()); // XXX
|
1600
|
-
arg->value(ith);
|
1601
|
-
} else {
|
1602
|
-
(*arglist)[i] = ith;
|
1603
|
-
}
|
1604
|
-
}
|
1605
|
-
shortest = (i ? std::min(shortest, ith->length()) : ith->length());
|
1606
|
-
}
|
1607
|
-
List_Ptr zippers = SASS_MEMORY_NEW(List, pstate, shortest, SASS_COMMA);
|
1608
|
-
size_t L = arglist->length();
|
1609
|
-
for (size_t i = 0; i < shortest; ++i) {
|
1610
|
-
List_Ptr zipper = SASS_MEMORY_NEW(List, pstate, L);
|
1611
|
-
for (size_t j = 0; j < L; ++j) {
|
1612
|
-
zipper->append(Cast<List>(arglist->value_at_index(j))->at(i));
|
1613
|
-
}
|
1614
|
-
zippers->append(zipper);
|
1615
|
-
}
|
1616
|
-
return zippers;
|
1617
|
-
}
|
1618
|
-
|
1619
|
-
Signature list_separator_sig = "list_separator($list)";
|
1620
|
-
BUILT_IN(list_separator)
|
1621
|
-
{
|
1622
|
-
List_Obj l = Cast<List>(env["$list"]);
|
1623
|
-
if (!l) {
|
1624
|
-
l = SASS_MEMORY_NEW(List, pstate, 1);
|
1625
|
-
l->append(ARG("$list", Expression));
|
1626
|
-
}
|
1627
|
-
return SASS_MEMORY_NEW(String_Quoted,
|
1628
|
-
pstate,
|
1629
|
-
l->separator() == SASS_COMMA ? "comma" : "space");
|
1630
|
-
}
|
1631
|
-
|
1632
|
-
/////////////////
|
1633
|
-
// MAP FUNCTIONS
|
1634
|
-
/////////////////
|
1635
|
-
|
1636
|
-
Signature map_get_sig = "map-get($map, $key)";
|
1637
|
-
BUILT_IN(map_get)
|
1638
|
-
{
|
1639
|
-
// leaks for "map-get((), foo)" if not Obj
|
1640
|
-
// investigate why this is (unexpected)
|
1641
|
-
Map_Obj m = ARGM("$map", Map, ctx);
|
1642
|
-
Expression_Obj v = ARG("$key", Expression);
|
1643
|
-
try {
|
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();
|
1648
|
-
} catch (const std::out_of_range&) {
|
1649
|
-
return SASS_MEMORY_NEW(Null, pstate);
|
1650
|
-
}
|
1651
|
-
catch (...) { throw; }
|
1652
|
-
}
|
1653
|
-
|
1654
|
-
Signature map_has_key_sig = "map-has-key($map, $key)";
|
1655
|
-
BUILT_IN(map_has_key)
|
1656
|
-
{
|
1657
|
-
Map_Obj m = ARGM("$map", Map, ctx);
|
1658
|
-
Expression_Obj v = ARG("$key", Expression);
|
1659
|
-
return SASS_MEMORY_NEW(Boolean, pstate, m->has(v));
|
1660
|
-
}
|
1661
|
-
|
1662
|
-
Signature map_keys_sig = "map-keys($map)";
|
1663
|
-
BUILT_IN(map_keys)
|
1664
|
-
{
|
1665
|
-
Map_Obj m = ARGM("$map", Map, ctx);
|
1666
|
-
List_Ptr result = SASS_MEMORY_NEW(List, pstate, m->length(), SASS_COMMA);
|
1667
|
-
for ( auto key : m->keys()) {
|
1668
|
-
result->append(key);
|
1669
|
-
}
|
1670
|
-
return result;
|
1671
|
-
}
|
1672
|
-
|
1673
|
-
Signature map_values_sig = "map-values($map)";
|
1674
|
-
BUILT_IN(map_values)
|
1675
|
-
{
|
1676
|
-
Map_Obj m = ARGM("$map", Map, ctx);
|
1677
|
-
List_Ptr result = SASS_MEMORY_NEW(List, pstate, m->length(), SASS_COMMA);
|
1678
|
-
for ( auto key : m->keys()) {
|
1679
|
-
result->append(m->at(key));
|
1680
|
-
}
|
1681
|
-
return result;
|
1682
|
-
}
|
1683
|
-
|
1684
|
-
Signature map_merge_sig = "map-merge($map1, $map2)";
|
1685
|
-
BUILT_IN(map_merge)
|
1686
|
-
{
|
1687
|
-
Map_Obj m1 = ARGM("$map1", Map, ctx);
|
1688
|
-
Map_Obj m2 = ARGM("$map2", Map, ctx);
|
1689
|
-
|
1690
|
-
size_t len = m1->length() + m2->length();
|
1691
|
-
Map_Ptr result = SASS_MEMORY_NEW(Map, pstate, len);
|
1692
|
-
// concat not implemented for maps
|
1693
|
-
*result += m1;
|
1694
|
-
*result += m2;
|
1695
|
-
return result;
|
1696
|
-
}
|
1697
|
-
|
1698
|
-
Signature map_remove_sig = "map-remove($map, $keys...)";
|
1699
|
-
BUILT_IN(map_remove)
|
1700
|
-
{
|
1701
|
-
bool remove;
|
1702
|
-
Map_Obj m = ARGM("$map", Map, ctx);
|
1703
|
-
List_Obj arglist = ARG("$keys", List);
|
1704
|
-
Map_Ptr result = SASS_MEMORY_NEW(Map, pstate, 1);
|
1705
|
-
for (auto key : m->keys()) {
|
1706
|
-
remove = false;
|
1707
|
-
for (size_t j = 0, K = arglist->length(); j < K && !remove; ++j) {
|
1708
|
-
remove = Operators::eq(key, arglist->value_at_index(j));
|
1709
|
-
}
|
1710
|
-
if (!remove) *result << std::make_pair(key, m->at(key));
|
1711
|
-
}
|
1712
|
-
return result;
|
1713
|
-
}
|
1714
|
-
|
1715
|
-
Signature keywords_sig = "keywords($args)";
|
1716
|
-
BUILT_IN(keywords)
|
1717
|
-
{
|
1718
|
-
List_Obj arglist = SASS_MEMORY_COPY(ARG("$args", List)); // copy
|
1719
|
-
Map_Obj result = SASS_MEMORY_NEW(Map, pstate, 1);
|
1720
|
-
for (size_t i = arglist->size(), L = arglist->length(); i < L; ++i) {
|
1721
|
-
Expression_Obj obj = arglist->at(i);
|
1722
|
-
Argument_Obj arg = (Argument_Ptr) obj.ptr(); // XXX
|
1723
|
-
std::string name = std::string(arg->name());
|
1724
|
-
name = name.erase(0, 1); // sanitize name (remove dollar sign)
|
1725
|
-
*result << std::make_pair(SASS_MEMORY_NEW(String_Quoted,
|
1726
|
-
pstate, name),
|
1727
|
-
arg->value());
|
1728
|
-
}
|
1729
|
-
return result.detach();
|
1730
|
-
}
|
1731
|
-
|
1732
|
-
//////////////////////////
|
1733
|
-
// INTROSPECTION FUNCTIONS
|
1734
|
-
//////////////////////////
|
1735
|
-
|
1736
|
-
Signature type_of_sig = "type-of($value)";
|
1737
|
-
BUILT_IN(type_of)
|
1738
|
-
{
|
1739
|
-
Expression_Ptr v = ARG("$value", Expression);
|
1740
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, v->type());
|
1741
|
-
}
|
1742
|
-
|
1743
|
-
Signature unit_sig = "unit($number)";
|
1744
|
-
BUILT_IN(unit)
|
1745
|
-
{
|
1746
|
-
Number_Obj arg = ARGN("$number");
|
1747
|
-
std::string str(quote(arg->unit(), '"'));
|
1748
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, str);
|
1749
|
-
}
|
1750
|
-
|
1751
|
-
Signature unitless_sig = "unitless($number)";
|
1752
|
-
BUILT_IN(unitless)
|
1753
|
-
{
|
1754
|
-
Number_Obj arg = ARGN("$number");
|
1755
|
-
bool unitless = arg->is_unitless();
|
1756
|
-
return SASS_MEMORY_NEW(Boolean, pstate, unitless);
|
1757
|
-
}
|
1758
|
-
|
1759
|
-
Signature comparable_sig = "comparable($number-1, $number-2)";
|
1760
|
-
BUILT_IN(comparable)
|
1761
|
-
{
|
1762
|
-
Number_Obj n1 = ARGN("$number-1");
|
1763
|
-
Number_Obj n2 = ARGN("$number-2");
|
1764
|
-
if (n1->is_unitless() || n2->is_unitless()) {
|
1765
|
-
return SASS_MEMORY_NEW(Boolean, pstate, true);
|
1766
|
-
}
|
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);
|
1772
|
-
}
|
1773
|
-
|
1774
|
-
Signature variable_exists_sig = "variable-exists($name)";
|
1775
|
-
BUILT_IN(variable_exists)
|
1776
|
-
{
|
1777
|
-
std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
|
1778
|
-
|
1779
|
-
if(d_env.has("$"+s)) {
|
1780
|
-
return SASS_MEMORY_NEW(Boolean, pstate, true);
|
1781
|
-
}
|
1782
|
-
else {
|
1783
|
-
return SASS_MEMORY_NEW(Boolean, pstate, false);
|
1784
|
-
}
|
1785
|
-
}
|
1786
|
-
|
1787
|
-
Signature global_variable_exists_sig = "global-variable-exists($name)";
|
1788
|
-
BUILT_IN(global_variable_exists)
|
1789
|
-
{
|
1790
|
-
std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
|
1791
|
-
|
1792
|
-
if(d_env.has_global("$"+s)) {
|
1793
|
-
return SASS_MEMORY_NEW(Boolean, pstate, true);
|
1794
|
-
}
|
1795
|
-
else {
|
1796
|
-
return SASS_MEMORY_NEW(Boolean, pstate, false);
|
1797
|
-
}
|
1798
|
-
}
|
1799
|
-
|
1800
|
-
Signature function_exists_sig = "function-exists($name)";
|
1801
|
-
BUILT_IN(function_exists)
|
1802
|
-
{
|
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()));
|
1809
|
-
|
1810
|
-
if(d_env.has_global(name+"[f]")) {
|
1811
|
-
return SASS_MEMORY_NEW(Boolean, pstate, true);
|
1812
|
-
}
|
1813
|
-
else {
|
1814
|
-
return SASS_MEMORY_NEW(Boolean, pstate, false);
|
1815
|
-
}
|
1816
|
-
}
|
1817
|
-
|
1818
|
-
Signature mixin_exists_sig = "mixin-exists($name)";
|
1819
|
-
BUILT_IN(mixin_exists)
|
1820
|
-
{
|
1821
|
-
std::string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
|
1822
|
-
|
1823
|
-
if(d_env.has_global(s+"[m]")) {
|
1824
|
-
return SASS_MEMORY_NEW(Boolean, pstate, true);
|
1825
|
-
}
|
1826
|
-
else {
|
1827
|
-
return SASS_MEMORY_NEW(Boolean, pstate, false);
|
1828
|
-
}
|
1829
|
-
}
|
1830
|
-
|
1831
|
-
Signature feature_exists_sig = "feature-exists($name)";
|
1832
|
-
BUILT_IN(feature_exists)
|
1833
|
-
{
|
1834
|
-
std::string s = unquote(ARG("$name", String_Constant)->value());
|
1835
|
-
|
1836
|
-
if(features.find(s) == features.end()) {
|
1837
|
-
return SASS_MEMORY_NEW(Boolean, pstate, false);
|
1838
|
-
}
|
1839
|
-
else {
|
1840
|
-
return SASS_MEMORY_NEW(Boolean, pstate, true);
|
1841
|
-
}
|
1842
|
-
}
|
1843
|
-
|
1844
|
-
Signature call_sig = "call($name, $args...)";
|
1845
|
-
BUILT_IN(call)
|
1846
|
-
{
|
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
|
-
|
1861
|
-
List_Obj arglist = SASS_MEMORY_COPY(ARG("$args", List));
|
1862
|
-
|
1863
|
-
Arguments_Obj args = SASS_MEMORY_NEW(Arguments, pstate);
|
1864
|
-
// std::string full_name(name + "[f]");
|
1865
|
-
// Definition_Ptr def = d_env.has(full_name) ? Cast<Definition>((d_env)[full_name]) : 0;
|
1866
|
-
// Parameters_Ptr params = def ? def->parameters() : 0;
|
1867
|
-
// size_t param_size = params ? params->length() : 0;
|
1868
|
-
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
1869
|
-
Expression_Obj expr = arglist->value_at_index(i);
|
1870
|
-
// if (params && params->has_rest_parameter()) {
|
1871
|
-
// Parameter_Obj p = param_size > i ? (*params)[i] : 0;
|
1872
|
-
// List_Ptr list = Cast<List>(expr);
|
1873
|
-
// if (list && p && !p->is_rest_parameter()) expr = (*list)[0];
|
1874
|
-
// }
|
1875
|
-
if (arglist->is_arglist()) {
|
1876
|
-
Expression_Obj obj = arglist->at(i);
|
1877
|
-
Argument_Obj arg = (Argument_Ptr) obj.ptr(); // XXX
|
1878
|
-
args->append(SASS_MEMORY_NEW(Argument,
|
1879
|
-
pstate,
|
1880
|
-
expr,
|
1881
|
-
arg ? arg->name() : "",
|
1882
|
-
arg ? arg->is_rest_argument() : false,
|
1883
|
-
arg ? arg->is_keyword_argument() : false));
|
1884
|
-
} else {
|
1885
|
-
args->append(SASS_MEMORY_NEW(Argument, pstate, expr));
|
1886
|
-
}
|
1887
|
-
}
|
1888
|
-
Function_Call_Obj func = SASS_MEMORY_NEW(Function_Call, pstate, name, args);
|
1889
|
-
Expand expand(ctx, &d_env, &selector_stack);
|
1890
|
-
func->via_call(true); // calc invoke is allowed
|
1891
|
-
if (ff) func->func(ff);
|
1892
|
-
return func->perform(&expand.eval);
|
1893
|
-
}
|
1894
|
-
|
1895
|
-
////////////////////
|
1896
|
-
// BOOLEAN FUNCTIONS
|
1897
|
-
////////////////////
|
1898
|
-
|
1899
|
-
Signature not_sig = "not($value)";
|
1900
|
-
BUILT_IN(sass_not)
|
1901
|
-
{
|
1902
|
-
return SASS_MEMORY_NEW(Boolean, pstate, ARG("$value", Expression)->is_false());
|
1903
|
-
}
|
1904
|
-
|
1905
|
-
Signature if_sig = "if($condition, $if-true, $if-false)";
|
1906
|
-
// BUILT_IN(sass_if)
|
1907
|
-
// { return ARG("$condition", Expression)->is_false() ? ARG("$if-false", Expression) : ARG("$if-true", Expression); }
|
1908
|
-
BUILT_IN(sass_if)
|
1909
|
-
{
|
1910
|
-
Expand expand(ctx, &d_env, &selector_stack);
|
1911
|
-
Expression_Obj cond = ARG("$condition", Expression)->perform(&expand.eval);
|
1912
|
-
bool is_true = !cond->is_false();
|
1913
|
-
Expression_Obj res = ARG(is_true ? "$if-true" : "$if-false", Expression);
|
1914
|
-
res = res->perform(&expand.eval);
|
1915
|
-
res->set_delayed(false); // clone?
|
1916
|
-
return res.detach();
|
1917
|
-
}
|
1918
|
-
|
1919
|
-
//////////////////////////
|
1920
|
-
// MISCELLANEOUS FUNCTIONS
|
1921
|
-
//////////////////////////
|
1922
|
-
|
1923
|
-
// value.check_deprecated_interp if value.is_a?(Sass::Script::Value::String)
|
1924
|
-
// unquoted_string(value.to_sass)
|
1925
|
-
|
1926
|
-
Signature inspect_sig = "inspect($value)";
|
1927
|
-
BUILT_IN(inspect)
|
1928
|
-
{
|
1929
|
-
Expression_Ptr v = ARG("$value", Expression);
|
1930
|
-
if (v->concrete_type() == Expression::NULL_VAL) {
|
1931
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, "null");
|
1932
|
-
} else if (v->concrete_type() == Expression::BOOLEAN && v->is_false()) {
|
1933
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, "false");
|
1934
|
-
} else if (v->concrete_type() == Expression::STRING) {
|
1935
|
-
return v;
|
1936
|
-
} else {
|
1937
|
-
// ToDo: fix to_sass for nested parentheses
|
1938
|
-
Sass_Output_Style old_style;
|
1939
|
-
old_style = ctx.c_options.output_style;
|
1940
|
-
ctx.c_options.output_style = TO_SASS;
|
1941
|
-
Emitter emitter(ctx.c_options);
|
1942
|
-
Inspect i(emitter);
|
1943
|
-
i.in_declaration = false;
|
1944
|
-
v->perform(&i);
|
1945
|
-
ctx.c_options.output_style = old_style;
|
1946
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, i.get_buffer());
|
1947
|
-
}
|
1948
|
-
// return v;
|
1949
|
-
}
|
1950
|
-
Signature selector_nest_sig = "selector-nest($selectors...)";
|
1951
|
-
BUILT_IN(selector_nest)
|
1952
|
-
{
|
1953
|
-
List_Ptr arglist = ARG("$selectors", List);
|
1954
|
-
|
1955
|
-
// Not enough parameters
|
1956
|
-
if( arglist->length() == 0 )
|
1957
|
-
error("$selectors: At least one selector must be passed for `selector-nest'", pstate, traces);
|
1958
|
-
|
1959
|
-
// Parse args into vector of selectors
|
1960
|
-
std::vector<Selector_List_Obj> parsedSelectors;
|
1961
|
-
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
1962
|
-
Expression_Obj exp = Cast<Expression>(arglist->value_at_index(i));
|
1963
|
-
if (exp->concrete_type() == Expression::NULL_VAL) {
|
1964
|
-
std::stringstream msg;
|
1965
|
-
msg << "$selectors: null is not a valid selector: it must be a string,\n";
|
1966
|
-
msg << "a list of strings, or a list of lists of strings for 'selector-nest'";
|
1967
|
-
error(msg.str(), pstate, traces);
|
1968
|
-
}
|
1969
|
-
if (String_Constant_Obj str = Cast<String_Constant>(exp)) {
|
1970
|
-
str->quote_mark(0);
|
1971
|
-
}
|
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);
|
1975
|
-
}
|
1976
|
-
|
1977
|
-
// Nothing to do
|
1978
|
-
if( parsedSelectors.empty() ) {
|
1979
|
-
return SASS_MEMORY_NEW(Null, pstate);
|
1980
|
-
}
|
1981
|
-
|
1982
|
-
// Set the first element as the `result`, keep appending to as we go down the parsedSelector vector.
|
1983
|
-
std::vector<Selector_List_Obj>::iterator itr = parsedSelectors.begin();
|
1984
|
-
Selector_List_Obj result = *itr;
|
1985
|
-
++itr;
|
1986
|
-
|
1987
|
-
for(;itr != parsedSelectors.end(); ++itr) {
|
1988
|
-
Selector_List_Obj child = *itr;
|
1989
|
-
std::vector<Complex_Selector_Obj> exploded;
|
1990
|
-
selector_stack.push_back(result);
|
1991
|
-
Selector_List_Obj rv = child->resolve_parent_refs(selector_stack, traces);
|
1992
|
-
selector_stack.pop_back();
|
1993
|
-
for (size_t m = 0, mLen = rv->length(); m < mLen; ++m) {
|
1994
|
-
exploded.push_back((*rv)[m]);
|
1995
|
-
}
|
1996
|
-
result->elements(exploded);
|
1997
|
-
}
|
1998
|
-
|
1999
|
-
Listize listize;
|
2000
|
-
return result->perform(&listize);
|
2001
|
-
}
|
2002
|
-
|
2003
|
-
Signature selector_append_sig = "selector-append($selectors...)";
|
2004
|
-
BUILT_IN(selector_append)
|
2005
|
-
{
|
2006
|
-
List_Ptr arglist = ARG("$selectors", List);
|
2007
|
-
|
2008
|
-
// Not enough parameters
|
2009
|
-
if( arglist->length() == 0 )
|
2010
|
-
error("$selectors: At least one selector must be passed for `selector-append'", pstate, traces);
|
2011
|
-
|
2012
|
-
// Parse args into vector of selectors
|
2013
|
-
std::vector<Selector_List_Obj> parsedSelectors;
|
2014
|
-
for (size_t i = 0, L = arglist->length(); i < L; ++i) {
|
2015
|
-
Expression_Obj exp = Cast<Expression>(arglist->value_at_index(i));
|
2016
|
-
if (exp->concrete_type() == Expression::NULL_VAL) {
|
2017
|
-
std::stringstream msg;
|
2018
|
-
msg << "$selectors: null is not a valid selector: it must be a string,\n";
|
2019
|
-
msg << "a list of strings, or a list of lists of strings for 'selector-append'";
|
2020
|
-
error(msg.str(), pstate, traces);
|
2021
|
-
}
|
2022
|
-
if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
|
2023
|
-
str->quote_mark(0);
|
2024
|
-
}
|
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);
|
2028
|
-
}
|
2029
|
-
|
2030
|
-
// Nothing to do
|
2031
|
-
if( parsedSelectors.empty() ) {
|
2032
|
-
return SASS_MEMORY_NEW(Null, pstate);
|
2033
|
-
}
|
2034
|
-
|
2035
|
-
// Set the first element as the `result`, keep appending to as we go down the parsedSelector vector.
|
2036
|
-
std::vector<Selector_List_Obj>::iterator itr = parsedSelectors.begin();
|
2037
|
-
Selector_List_Obj result = *itr;
|
2038
|
-
++itr;
|
2039
|
-
|
2040
|
-
for(;itr != parsedSelectors.end(); ++itr) {
|
2041
|
-
Selector_List_Obj child = *itr;
|
2042
|
-
std::vector<Complex_Selector_Obj> newElements;
|
2043
|
-
|
2044
|
-
// For every COMPLEX_SELECTOR in `result`
|
2045
|
-
// For every COMPLEX_SELECTOR in `child`
|
2046
|
-
// let parentSeqClone equal a copy of result->elements[i]
|
2047
|
-
// let childSeq equal child->elements[j]
|
2048
|
-
// Append all of childSeq head elements into parentSeqClone
|
2049
|
-
// Set the innermost tail of parentSeqClone, to childSeq's tail
|
2050
|
-
// Replace result->elements with newElements
|
2051
|
-
for (size_t i = 0, resultLen = result->length(); i < resultLen; ++i) {
|
2052
|
-
for (size_t j = 0, childLen = child->length(); j < childLen; ++j) {
|
2053
|
-
Complex_Selector_Obj parentSeqClone = SASS_MEMORY_CLONE((*result)[i]);
|
2054
|
-
Complex_Selector_Obj childSeq = (*child)[j];
|
2055
|
-
Complex_Selector_Obj base = childSeq->tail();
|
2056
|
-
|
2057
|
-
// Must be a simple sequence
|
2058
|
-
if( childSeq->combinator() != Complex_Selector::Combinator::ANCESTOR_OF ) {
|
2059
|
-
std::string msg("Can't append \"");
|
2060
|
-
msg += childSeq->to_string();
|
2061
|
-
msg += "\" to \"";
|
2062
|
-
msg += parentSeqClone->to_string();
|
2063
|
-
msg += "\" for `selector-append'";
|
2064
|
-
error(msg, pstate, traces);
|
2065
|
-
}
|
2066
|
-
|
2067
|
-
// Cannot be a Universal selector
|
2068
|
-
Element_Selector_Obj pType = Cast<Element_Selector>(childSeq->head()->first());
|
2069
|
-
if(pType && pType->name() == "*") {
|
2070
|
-
std::string msg("Can't append \"");
|
2071
|
-
msg += childSeq->to_string();
|
2072
|
-
msg += "\" to \"";
|
2073
|
-
msg += parentSeqClone->to_string();
|
2074
|
-
msg += "\" for `selector-append'";
|
2075
|
-
error(msg, pstate, traces);
|
2076
|
-
}
|
2077
|
-
|
2078
|
-
// TODO: Add check for namespace stuff
|
2079
|
-
|
2080
|
-
// append any selectors in childSeq's head
|
2081
|
-
parentSeqClone->innermost()->head()->concat(base->head());
|
2082
|
-
|
2083
|
-
// Set parentSeqClone new tail
|
2084
|
-
parentSeqClone->innermost()->tail( base->tail() );
|
2085
|
-
|
2086
|
-
newElements.push_back(parentSeqClone);
|
2087
|
-
}
|
2088
|
-
}
|
2089
|
-
|
2090
|
-
result->elements(newElements);
|
2091
|
-
}
|
2092
|
-
|
2093
|
-
Listize listize;
|
2094
|
-
return result->perform(&listize);
|
2095
|
-
}
|
2096
|
-
|
2097
|
-
Signature selector_unify_sig = "selector-unify($selector1, $selector2)";
|
2098
|
-
BUILT_IN(selector_unify)
|
2099
|
-
{
|
2100
|
-
Selector_List_Obj selector1 = ARGSEL("$selector1", Selector_List_Obj, p_contextualize);
|
2101
|
-
Selector_List_Obj selector2 = ARGSEL("$selector2", Selector_List_Obj, p_contextualize);
|
2102
|
-
|
2103
|
-
Selector_List_Obj result = selector1->unify_with(selector2);
|
2104
|
-
Listize listize;
|
2105
|
-
return result->perform(&listize);
|
2106
|
-
}
|
2107
|
-
|
2108
|
-
Signature simple_selectors_sig = "simple-selectors($selector)";
|
2109
|
-
BUILT_IN(simple_selectors)
|
2110
|
-
{
|
2111
|
-
Compound_Selector_Obj sel = ARGSEL("$selector", Compound_Selector_Obj, p_contextualize);
|
2112
|
-
|
2113
|
-
List_Ptr l = SASS_MEMORY_NEW(List, sel->pstate(), sel->length(), SASS_COMMA);
|
2114
|
-
|
2115
|
-
for (size_t i = 0, L = sel->length(); i < L; ++i) {
|
2116
|
-
Simple_Selector_Obj ss = (*sel)[i];
|
2117
|
-
std::string ss_string = ss->to_string() ;
|
2118
|
-
|
2119
|
-
l->append(SASS_MEMORY_NEW(String_Quoted, ss->pstate(), ss_string));
|
2120
|
-
}
|
2121
|
-
|
2122
|
-
return l;
|
2123
|
-
}
|
2124
|
-
|
2125
|
-
Signature selector_extend_sig = "selector-extend($selector, $extendee, $extender)";
|
2126
|
-
BUILT_IN(selector_extend)
|
2127
|
-
{
|
2128
|
-
Selector_List_Obj selector = ARGSEL("$selector", Selector_List_Obj, p_contextualize);
|
2129
|
-
Selector_List_Obj extendee = ARGSEL("$extendee", Selector_List_Obj, p_contextualize);
|
2130
|
-
Selector_List_Obj extender = ARGSEL("$extender", Selector_List_Obj, p_contextualize);
|
2131
|
-
|
2132
|
-
Subset_Map subset_map;
|
2133
|
-
extender->populate_extends(extendee, subset_map);
|
2134
|
-
Extend extend(subset_map);
|
2135
|
-
|
2136
|
-
Selector_List_Obj result = extend.extendSelectorList(selector, false);
|
2137
|
-
|
2138
|
-
Listize listize;
|
2139
|
-
return result->perform(&listize);
|
2140
|
-
}
|
2141
|
-
|
2142
|
-
Signature selector_replace_sig = "selector-replace($selector, $original, $replacement)";
|
2143
|
-
BUILT_IN(selector_replace)
|
2144
|
-
{
|
2145
|
-
Selector_List_Obj selector = ARGSEL("$selector", Selector_List_Obj, p_contextualize);
|
2146
|
-
Selector_List_Obj original = ARGSEL("$original", Selector_List_Obj, p_contextualize);
|
2147
|
-
Selector_List_Obj replacement = ARGSEL("$replacement", Selector_List_Obj, p_contextualize);
|
2148
|
-
Subset_Map subset_map;
|
2149
|
-
replacement->populate_extends(original, subset_map);
|
2150
|
-
Extend extend(subset_map);
|
2151
|
-
|
2152
|
-
Selector_List_Obj result = extend.extendSelectorList(selector, true);
|
2153
|
-
|
2154
|
-
Listize listize;
|
2155
|
-
return result->perform(&listize);
|
2156
|
-
}
|
2157
|
-
|
2158
|
-
Signature selector_parse_sig = "selector-parse($selector)";
|
2159
|
-
BUILT_IN(selector_parse)
|
2160
|
-
{
|
2161
|
-
Selector_List_Obj sel = ARGSEL("$selector", Selector_List_Obj, p_contextualize);
|
2162
|
-
|
2163
|
-
Listize listize;
|
2164
|
-
return sel->perform(&listize);
|
2165
|
-
}
|
2166
|
-
|
2167
|
-
Signature is_superselector_sig = "is-superselector($super, $sub)";
|
2168
|
-
BUILT_IN(is_superselector)
|
2169
|
-
{
|
2170
|
-
Selector_List_Obj sel_sup = ARGSEL("$super", Selector_List_Obj, p_contextualize);
|
2171
|
-
Selector_List_Obj sel_sub = ARGSEL("$sub", Selector_List_Obj, p_contextualize);
|
2172
|
-
bool result = sel_sup->is_superselector_of(sel_sub);
|
2173
|
-
return SASS_MEMORY_NEW(Boolean, pstate, result);
|
2174
|
-
}
|
2175
|
-
|
2176
|
-
Signature unique_id_sig = "unique-id()";
|
2177
|
-
BUILT_IN(unique_id)
|
2178
|
-
{
|
2179
|
-
std::stringstream ss;
|
2180
|
-
std::uniform_real_distribution<> distributor(0, 4294967296); // 16^8
|
2181
|
-
uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
|
2182
|
-
ss << "u" << std::setfill('0') << std::setw(8) << std::hex << distributed;
|
2183
|
-
return SASS_MEMORY_NEW(String_Quoted, pstate, ss.str());
|
2184
|
-
}
|
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
|
-
}
|
2233
|
-
}
|
2234
|
-
}
|