sassc4 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.gitmodules +3 -0
- data/.travis.yml +16 -0
- data/CHANGELOG.md +97 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +80 -0
- data/Rakefile +51 -0
- data/ext/depend +4 -0
- data/ext/extconf.rb +92 -0
- data/ext/libsass/VERSION +1 -0
- data/ext/libsass/contrib/plugin.cpp +60 -0
- data/ext/libsass/include/sass/base.h +97 -0
- data/ext/libsass/include/sass/context.h +174 -0
- data/ext/libsass/include/sass/functions.h +139 -0
- data/ext/libsass/include/sass/values.h +145 -0
- data/ext/libsass/include/sass/version.h +12 -0
- data/ext/libsass/include/sass.h +15 -0
- data/ext/libsass/include/sass2scss.h +120 -0
- data/ext/libsass/src/MurmurHash2.hpp +91 -0
- data/ext/libsass/src/ast.cpp +953 -0
- data/ext/libsass/src/ast.hpp +1064 -0
- data/ext/libsass/src/ast2c.cpp +80 -0
- data/ext/libsass/src/ast2c.hpp +39 -0
- data/ext/libsass/src/ast_def_macros.hpp +140 -0
- data/ext/libsass/src/ast_fwd_decl.cpp +31 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +274 -0
- data/ext/libsass/src/ast_helpers.hpp +316 -0
- data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
- data/ext/libsass/src/ast_sel_super.cpp +539 -0
- data/ext/libsass/src/ast_sel_unify.cpp +275 -0
- data/ext/libsass/src/ast_sel_weave.cpp +616 -0
- data/ext/libsass/src/ast_selectors.cpp +1070 -0
- data/ext/libsass/src/ast_selectors.hpp +523 -0
- data/ext/libsass/src/ast_supports.cpp +114 -0
- data/ext/libsass/src/ast_supports.hpp +121 -0
- data/ext/libsass/src/ast_values.cpp +1154 -0
- data/ext/libsass/src/ast_values.hpp +498 -0
- data/ext/libsass/src/b64/cencode.h +32 -0
- data/ext/libsass/src/b64/encode.h +79 -0
- data/ext/libsass/src/backtrace.cpp +50 -0
- data/ext/libsass/src/backtrace.hpp +29 -0
- data/ext/libsass/src/base64vlq.cpp +47 -0
- data/ext/libsass/src/base64vlq.hpp +30 -0
- data/ext/libsass/src/bind.cpp +312 -0
- data/ext/libsass/src/bind.hpp +15 -0
- data/ext/libsass/src/c2ast.cpp +64 -0
- data/ext/libsass/src/c2ast.hpp +14 -0
- data/ext/libsass/src/c99func.c +54 -0
- data/ext/libsass/src/cencode.c +106 -0
- data/ext/libsass/src/check_nesting.cpp +393 -0
- data/ext/libsass/src/check_nesting.hpp +70 -0
- data/ext/libsass/src/color_maps.cpp +652 -0
- data/ext/libsass/src/color_maps.hpp +323 -0
- data/ext/libsass/src/color_spaces.cpp +241 -0
- data/ext/libsass/src/color_spaces.hpp +227 -0
- data/ext/libsass/src/constants.cpp +199 -0
- data/ext/libsass/src/constants.hpp +200 -0
- data/ext/libsass/src/context.cpp +870 -0
- data/ext/libsass/src/context.hpp +140 -0
- data/ext/libsass/src/cssize.cpp +521 -0
- data/ext/libsass/src/cssize.hpp +71 -0
- data/ext/libsass/src/dart_helpers.hpp +199 -0
- data/ext/libsass/src/debug.hpp +43 -0
- data/ext/libsass/src/debugger.hpp +964 -0
- data/ext/libsass/src/emitter.cpp +297 -0
- data/ext/libsass/src/emitter.hpp +101 -0
- data/ext/libsass/src/environment.cpp +260 -0
- data/ext/libsass/src/environment.hpp +124 -0
- data/ext/libsass/src/error_handling.cpp +239 -0
- data/ext/libsass/src/error_handling.hpp +248 -0
- data/ext/libsass/src/eval.cpp +1543 -0
- data/ext/libsass/src/eval.hpp +110 -0
- data/ext/libsass/src/eval_selectors.cpp +75 -0
- data/ext/libsass/src/expand.cpp +875 -0
- data/ext/libsass/src/expand.hpp +98 -0
- data/ext/libsass/src/extender.cpp +1226 -0
- data/ext/libsass/src/extender.hpp +399 -0
- data/ext/libsass/src/extension.cpp +43 -0
- data/ext/libsass/src/extension.hpp +89 -0
- data/ext/libsass/src/file.cpp +531 -0
- data/ext/libsass/src/file.hpp +124 -0
- data/ext/libsass/src/fn_colors.cpp +836 -0
- data/ext/libsass/src/fn_colors.hpp +99 -0
- data/ext/libsass/src/fn_lists.cpp +285 -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 +248 -0
- data/ext/libsass/src/fn_miscs.hpp +40 -0
- data/ext/libsass/src/fn_numbers.cpp +246 -0
- data/ext/libsass/src/fn_numbers.hpp +45 -0
- data/ext/libsass/src/fn_selectors.cpp +205 -0
- data/ext/libsass/src/fn_selectors.hpp +35 -0
- data/ext/libsass/src/fn_strings.cpp +268 -0
- data/ext/libsass/src/fn_strings.hpp +34 -0
- data/ext/libsass/src/fn_utils.cpp +159 -0
- data/ext/libsass/src/fn_utils.hpp +62 -0
- data/ext/libsass/src/inspect.cpp +1126 -0
- data/ext/libsass/src/inspect.hpp +101 -0
- data/ext/libsass/src/json.cpp +1436 -0
- data/ext/libsass/src/json.hpp +117 -0
- data/ext/libsass/src/kwd_arg_macros.hpp +28 -0
- data/ext/libsass/src/lexer.cpp +122 -0
- data/ext/libsass/src/lexer.hpp +304 -0
- data/ext/libsass/src/listize.cpp +70 -0
- data/ext/libsass/src/listize.hpp +37 -0
- data/ext/libsass/src/mapping.hpp +19 -0
- data/ext/libsass/src/memory/allocator.cpp +48 -0
- data/ext/libsass/src/memory/allocator.hpp +138 -0
- data/ext/libsass/src/memory/config.hpp +20 -0
- data/ext/libsass/src/memory/memory_pool.hpp +186 -0
- data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
- data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
- data/ext/libsass/src/memory.hpp +12 -0
- data/ext/libsass/src/operation.hpp +223 -0
- data/ext/libsass/src/operators.cpp +267 -0
- data/ext/libsass/src/operators.hpp +30 -0
- data/ext/libsass/src/ordered_map.hpp +112 -0
- data/ext/libsass/src/output.cpp +320 -0
- data/ext/libsass/src/output.hpp +47 -0
- data/ext/libsass/src/parser.cpp +3059 -0
- data/ext/libsass/src/parser.hpp +395 -0
- data/ext/libsass/src/parser_selectors.cpp +189 -0
- data/ext/libsass/src/permutate.hpp +164 -0
- data/ext/libsass/src/plugins.cpp +188 -0
- data/ext/libsass/src/plugins.hpp +57 -0
- data/ext/libsass/src/position.cpp +163 -0
- data/ext/libsass/src/position.hpp +147 -0
- data/ext/libsass/src/prelexer.cpp +1780 -0
- data/ext/libsass/src/prelexer.hpp +484 -0
- data/ext/libsass/src/remove_placeholders.cpp +86 -0
- data/ext/libsass/src/remove_placeholders.hpp +37 -0
- data/ext/libsass/src/sass.cpp +156 -0
- data/ext/libsass/src/sass.hpp +147 -0
- data/ext/libsass/src/sass2scss.cpp +895 -0
- data/ext/libsass/src/sass_context.cpp +742 -0
- data/ext/libsass/src/sass_context.hpp +129 -0
- data/ext/libsass/src/sass_functions.cpp +210 -0
- data/ext/libsass/src/sass_functions.hpp +50 -0
- data/ext/libsass/src/sass_values.cpp +362 -0
- data/ext/libsass/src/sass_values.hpp +82 -0
- data/ext/libsass/src/settings.hpp +19 -0
- data/ext/libsass/src/source.cpp +69 -0
- data/ext/libsass/src/source.hpp +95 -0
- data/ext/libsass/src/source_data.hpp +32 -0
- data/ext/libsass/src/source_map.cpp +202 -0
- data/ext/libsass/src/source_map.hpp +65 -0
- data/ext/libsass/src/stylesheet.cpp +22 -0
- data/ext/libsass/src/stylesheet.hpp +57 -0
- data/ext/libsass/src/to_value.cpp +114 -0
- data/ext/libsass/src/to_value.hpp +46 -0
- data/ext/libsass/src/units.cpp +507 -0
- data/ext/libsass/src/units.hpp +110 -0
- data/ext/libsass/src/utf8/checked.h +336 -0
- data/ext/libsass/src/utf8/core.h +332 -0
- data/ext/libsass/src/utf8/unchecked.h +235 -0
- data/ext/libsass/src/utf8.h +34 -0
- data/ext/libsass/src/utf8_string.cpp +104 -0
- data/ext/libsass/src/utf8_string.hpp +38 -0
- data/ext/libsass/src/util.cpp +723 -0
- data/ext/libsass/src/util.hpp +105 -0
- data/ext/libsass/src/util_string.cpp +125 -0
- data/ext/libsass/src/util_string.hpp +73 -0
- data/ext/libsass/src/values.cpp +140 -0
- data/ext/libsass/src/values.hpp +12 -0
- data/lib/sassc/dependency.rb +17 -0
- data/lib/sassc/engine.rb +141 -0
- data/lib/sassc/error.rb +37 -0
- data/lib/sassc/functions_handler.rb +73 -0
- data/lib/sassc/import_handler.rb +50 -0
- data/lib/sassc/importer.rb +31 -0
- data/lib/sassc/native/native_context_api.rb +147 -0
- data/lib/sassc/native/native_functions_api.rb +159 -0
- data/lib/sassc/native/sass2scss_api.rb +10 -0
- data/lib/sassc/native/sass_input_style.rb +13 -0
- data/lib/sassc/native/sass_output_style.rb +12 -0
- data/lib/sassc/native/sass_value.rb +97 -0
- data/lib/sassc/native/string_list.rb +10 -0
- data/lib/sassc/native.rb +64 -0
- data/lib/sassc/sass_2_scss.rb +9 -0
- data/lib/sassc/script/functions.rb +8 -0
- data/lib/sassc/script/value/bool.rb +32 -0
- data/lib/sassc/script/value/color.rb +95 -0
- data/lib/sassc/script/value/list.rb +136 -0
- data/lib/sassc/script/value/map.rb +69 -0
- data/lib/sassc/script/value/number.rb +389 -0
- data/lib/sassc/script/value/string.rb +96 -0
- data/lib/sassc/script/value.rb +137 -0
- data/lib/sassc/script/value_conversion/base.rb +13 -0
- data/lib/sassc/script/value_conversion/bool.rb +13 -0
- data/lib/sassc/script/value_conversion/color.rb +18 -0
- data/lib/sassc/script/value_conversion/list.rb +25 -0
- data/lib/sassc/script/value_conversion/map.rb +21 -0
- data/lib/sassc/script/value_conversion/number.rb +13 -0
- data/lib/sassc/script/value_conversion/string.rb +17 -0
- data/lib/sassc/script/value_conversion.rb +69 -0
- data/lib/sassc/script.rb +17 -0
- data/lib/sassc/util/normalized_map.rb +117 -0
- data/lib/sassc/util.rb +231 -0
- data/lib/sassc/version.rb +5 -0
- data/lib/sassc.rb +57 -0
- data/sassc.gemspec +69 -0
- data/test/css_color_level4_test.rb +168 -0
- data/test/custom_importer_test.rb +127 -0
- data/test/engine_test.rb +314 -0
- data/test/error_test.rb +29 -0
- data/test/fixtures/paths.scss +10 -0
- data/test/functions_test.rb +340 -0
- data/test/native_test.rb +213 -0
- data/test/output_style_test.rb +107 -0
- data/test/sass_2_scss_test.rb +14 -0
- data/test/test_helper.rb +45 -0
- metadata +396 -0
|
@@ -0,0 +1,875 @@
|
|
|
1
|
+
// sass.hpp must go before all system headers to get the
|
|
2
|
+
// __EXTENSIONS__ fix on Solaris.
|
|
3
|
+
#include "sass.hpp"
|
|
4
|
+
|
|
5
|
+
#include <iostream>
|
|
6
|
+
#include <typeinfo>
|
|
7
|
+
|
|
8
|
+
#include "ast.hpp"
|
|
9
|
+
#include "expand.hpp"
|
|
10
|
+
#include "bind.hpp"
|
|
11
|
+
#include "eval.hpp"
|
|
12
|
+
#include "backtrace.hpp"
|
|
13
|
+
#include "context.hpp"
|
|
14
|
+
#include "parser.hpp"
|
|
15
|
+
#include "sass_functions.hpp"
|
|
16
|
+
#include "error_handling.hpp"
|
|
17
|
+
|
|
18
|
+
namespace Sass {
|
|
19
|
+
|
|
20
|
+
// simple endless recursion protection
|
|
21
|
+
const size_t maxRecursion = 500;
|
|
22
|
+
|
|
23
|
+
Expand::Expand(Context& ctx, Env* env, SelectorStack* stack, SelectorStack* originals)
|
|
24
|
+
: ctx(ctx),
|
|
25
|
+
traces(ctx.traces),
|
|
26
|
+
eval(Eval(*this)),
|
|
27
|
+
recursions(0),
|
|
28
|
+
in_keyframes(false),
|
|
29
|
+
at_root_without_rule(false),
|
|
30
|
+
old_at_root_without_rule(false),
|
|
31
|
+
env_stack(),
|
|
32
|
+
block_stack(),
|
|
33
|
+
call_stack(),
|
|
34
|
+
selector_stack(),
|
|
35
|
+
originalStack(),
|
|
36
|
+
mediaStack()
|
|
37
|
+
{
|
|
38
|
+
env_stack.push_back(nullptr);
|
|
39
|
+
env_stack.push_back(env);
|
|
40
|
+
block_stack.push_back(nullptr);
|
|
41
|
+
call_stack.push_back({});
|
|
42
|
+
if (stack == NULL) { pushToSelectorStack({}); }
|
|
43
|
+
else {
|
|
44
|
+
for (auto item : *stack) {
|
|
45
|
+
if (item.isNull()) pushToSelectorStack({});
|
|
46
|
+
else pushToSelectorStack(item);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (originals == NULL) { pushToOriginalStack({}); }
|
|
50
|
+
else {
|
|
51
|
+
for (auto item : *stack) {
|
|
52
|
+
if (item.isNull()) pushToOriginalStack({});
|
|
53
|
+
else pushToOriginalStack(item);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
mediaStack.push_back({});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
Env* Expand::environment()
|
|
60
|
+
{
|
|
61
|
+
if (env_stack.size() > 0)
|
|
62
|
+
return env_stack.back();
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
void Expand::pushNullSelector()
|
|
67
|
+
{
|
|
68
|
+
pushToSelectorStack({});
|
|
69
|
+
pushToOriginalStack({});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
void Expand::popNullSelector()
|
|
73
|
+
{
|
|
74
|
+
popFromOriginalStack();
|
|
75
|
+
popFromSelectorStack();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
SelectorStack Expand::getOriginalStack()
|
|
79
|
+
{
|
|
80
|
+
return originalStack;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
SelectorStack Expand::getSelectorStack()
|
|
84
|
+
{
|
|
85
|
+
return selector_stack;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
SelectorListObj& Expand::selector()
|
|
89
|
+
{
|
|
90
|
+
if (selector_stack.size() > 0) {
|
|
91
|
+
auto& sel = selector_stack.back();
|
|
92
|
+
if (sel.isNull()) return sel;
|
|
93
|
+
return sel;
|
|
94
|
+
}
|
|
95
|
+
// Avoid the need to return copies
|
|
96
|
+
// We always want an empty first item
|
|
97
|
+
selector_stack.push_back({});
|
|
98
|
+
return selector_stack.back();;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
SelectorListObj& Expand::original()
|
|
102
|
+
{
|
|
103
|
+
if (originalStack.size() > 0) {
|
|
104
|
+
auto& sel = originalStack.back();
|
|
105
|
+
if (sel.isNull()) return sel;
|
|
106
|
+
return sel;
|
|
107
|
+
}
|
|
108
|
+
// Avoid the need to return copies
|
|
109
|
+
// We always want an empty first item
|
|
110
|
+
originalStack.push_back({});
|
|
111
|
+
return originalStack.back();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
SelectorListObj Expand::popFromSelectorStack()
|
|
115
|
+
{
|
|
116
|
+
SelectorListObj last = selector_stack.back();
|
|
117
|
+
if (selector_stack.size() > 0)
|
|
118
|
+
selector_stack.pop_back();
|
|
119
|
+
if (last.isNull()) return {};
|
|
120
|
+
return last;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
void Expand::pushToSelectorStack(SelectorListObj selector)
|
|
124
|
+
{
|
|
125
|
+
selector_stack.push_back(selector);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
SelectorListObj Expand::popFromOriginalStack()
|
|
129
|
+
{
|
|
130
|
+
SelectorListObj last = originalStack.back();
|
|
131
|
+
if (originalStack.size() > 0)
|
|
132
|
+
originalStack.pop_back();
|
|
133
|
+
if (last.isNull()) return {};
|
|
134
|
+
return last;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
void Expand::pushToOriginalStack(SelectorListObj selector)
|
|
138
|
+
{
|
|
139
|
+
originalStack.push_back(selector);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// blocks create new variable scopes
|
|
143
|
+
Block* Expand::operator()(Block* b)
|
|
144
|
+
{
|
|
145
|
+
// create new local environment
|
|
146
|
+
// set the current env as parent
|
|
147
|
+
Env env(environment());
|
|
148
|
+
// copy the block object (add items later)
|
|
149
|
+
Block_Obj bb = SASS_MEMORY_NEW(Block,
|
|
150
|
+
b->pstate(),
|
|
151
|
+
b->length(),
|
|
152
|
+
b->is_root());
|
|
153
|
+
// setup block and env stack
|
|
154
|
+
this->block_stack.push_back(bb);
|
|
155
|
+
this->env_stack.push_back(&env);
|
|
156
|
+
// operate on block
|
|
157
|
+
// this may throw up!
|
|
158
|
+
this->append_block(b);
|
|
159
|
+
// revert block and env stack
|
|
160
|
+
this->block_stack.pop_back();
|
|
161
|
+
this->env_stack.pop_back();
|
|
162
|
+
// return copy
|
|
163
|
+
return bb.detach();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
Statement* Expand::operator()(StyleRule* r)
|
|
167
|
+
{
|
|
168
|
+
LOCAL_FLAG(old_at_root_without_rule, at_root_without_rule);
|
|
169
|
+
|
|
170
|
+
if (in_keyframes) {
|
|
171
|
+
Block* bb = operator()(r->block());
|
|
172
|
+
Keyframe_Rule_Obj k = SASS_MEMORY_NEW(Keyframe_Rule, r->pstate(), bb);
|
|
173
|
+
if (r->schema()) {
|
|
174
|
+
pushNullSelector();
|
|
175
|
+
k->name(eval(r->schema()));
|
|
176
|
+
popNullSelector();
|
|
177
|
+
}
|
|
178
|
+
else if (r->selector()) {
|
|
179
|
+
if (SelectorListObj s = r->selector()) {
|
|
180
|
+
pushNullSelector();
|
|
181
|
+
k->name(eval(s));
|
|
182
|
+
popNullSelector();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return k.detach();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (r->schema()) {
|
|
190
|
+
SelectorListObj sel = eval(r->schema());
|
|
191
|
+
r->selector(sel);
|
|
192
|
+
for (auto complex : sel->elements()) {
|
|
193
|
+
// ToDo: maybe we can get rid of chroots?
|
|
194
|
+
complex->chroots(complex->has_real_parent_ref());
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// reset when leaving scope
|
|
200
|
+
LOCAL_FLAG(at_root_without_rule, false);
|
|
201
|
+
|
|
202
|
+
SelectorListObj evaled = eval(r->selector());
|
|
203
|
+
// do not connect parent again
|
|
204
|
+
Env env(environment());
|
|
205
|
+
if (block_stack.back()->is_root()) {
|
|
206
|
+
env_stack.push_back(&env);
|
|
207
|
+
}
|
|
208
|
+
Block_Obj blk;
|
|
209
|
+
pushToSelectorStack(evaled);
|
|
210
|
+
// The copy is needed for parent reference evaluation
|
|
211
|
+
// dart-sass stores it as `originalSelector` member
|
|
212
|
+
pushToOriginalStack(SASS_MEMORY_COPY(evaled));
|
|
213
|
+
ctx.extender.addSelector(evaled, mediaStack.back());
|
|
214
|
+
if (r->block()) blk = operator()(r->block());
|
|
215
|
+
popFromOriginalStack();
|
|
216
|
+
popFromSelectorStack();
|
|
217
|
+
StyleRule* rr = SASS_MEMORY_NEW(StyleRule,
|
|
218
|
+
r->pstate(),
|
|
219
|
+
evaled,
|
|
220
|
+
blk);
|
|
221
|
+
|
|
222
|
+
if (block_stack.back()->is_root()) {
|
|
223
|
+
env_stack.pop_back();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
rr->is_root(r->is_root());
|
|
227
|
+
rr->tabs(r->tabs());
|
|
228
|
+
|
|
229
|
+
return rr;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
Statement* Expand::operator()(SupportsRule* f)
|
|
233
|
+
{
|
|
234
|
+
ExpressionObj condition = f->condition()->perform(&eval);
|
|
235
|
+
SupportsRuleObj ff = SASS_MEMORY_NEW(SupportsRule,
|
|
236
|
+
f->pstate(),
|
|
237
|
+
Cast<SupportsCondition>(condition),
|
|
238
|
+
operator()(f->block()));
|
|
239
|
+
return ff.detach();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
sass::vector<CssMediaQuery_Obj> Expand::mergeMediaQueries(
|
|
243
|
+
const sass::vector<CssMediaQuery_Obj>& lhs,
|
|
244
|
+
const sass::vector<CssMediaQuery_Obj>& rhs)
|
|
245
|
+
{
|
|
246
|
+
sass::vector<CssMediaQuery_Obj> queries;
|
|
247
|
+
for (CssMediaQuery_Obj query1 : lhs) {
|
|
248
|
+
for (CssMediaQuery_Obj query2 : rhs) {
|
|
249
|
+
CssMediaQuery_Obj result = query1->merge(query2);
|
|
250
|
+
if (result && !result->empty()) {
|
|
251
|
+
queries.push_back(result);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return queries;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
Statement* Expand::operator()(MediaRule* m)
|
|
259
|
+
{
|
|
260
|
+
ExpressionObj mq = eval(m->schema());
|
|
261
|
+
sass::string str_mq(mq->to_css(ctx.c_options));
|
|
262
|
+
ItplFile* source = SASS_MEMORY_NEW(ItplFile,
|
|
263
|
+
str_mq.c_str(), m->pstate());
|
|
264
|
+
Parser parser(source, ctx, traces);
|
|
265
|
+
// Create a new CSS only representation of the media rule
|
|
266
|
+
CssMediaRuleObj css = SASS_MEMORY_NEW(CssMediaRule, m->pstate(), m->block());
|
|
267
|
+
sass::vector<CssMediaQuery_Obj> parsed = parser.parseCssMediaQueries();
|
|
268
|
+
if (mediaStack.size() && mediaStack.back()) {
|
|
269
|
+
auto& parent = mediaStack.back()->elements();
|
|
270
|
+
css->concat(mergeMediaQueries(parent, parsed));
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
css->concat(parsed);
|
|
274
|
+
}
|
|
275
|
+
mediaStack.push_back(css);
|
|
276
|
+
css->block(operator()(m->block()));
|
|
277
|
+
mediaStack.pop_back();
|
|
278
|
+
return css.detach();
|
|
279
|
+
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
Statement* Expand::operator()(AtRootRule* a)
|
|
283
|
+
{
|
|
284
|
+
Block_Obj ab = a->block();
|
|
285
|
+
ExpressionObj ae = a->expression();
|
|
286
|
+
|
|
287
|
+
if (ae) ae = ae->perform(&eval);
|
|
288
|
+
else ae = SASS_MEMORY_NEW(At_Root_Query, a->pstate());
|
|
289
|
+
|
|
290
|
+
LOCAL_FLAG(at_root_without_rule, Cast<At_Root_Query>(ae)->exclude("rule"));
|
|
291
|
+
LOCAL_FLAG(in_keyframes, false);
|
|
292
|
+
|
|
293
|
+
;
|
|
294
|
+
|
|
295
|
+
Block_Obj bb = ab ? operator()(ab) : NULL;
|
|
296
|
+
AtRootRuleObj aa = SASS_MEMORY_NEW(AtRootRule,
|
|
297
|
+
a->pstate(),
|
|
298
|
+
bb,
|
|
299
|
+
Cast<At_Root_Query>(ae));
|
|
300
|
+
return aa.detach();
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
Statement* Expand::operator()(AtRule* a)
|
|
304
|
+
{
|
|
305
|
+
LOCAL_FLAG(in_keyframes, a->is_keyframes());
|
|
306
|
+
Block* ab = a->block();
|
|
307
|
+
SelectorList* as = a->selector();
|
|
308
|
+
Expression* av = a->value();
|
|
309
|
+
pushNullSelector();
|
|
310
|
+
if (av) av = av->perform(&eval);
|
|
311
|
+
if (as) as = eval(as);
|
|
312
|
+
popNullSelector();
|
|
313
|
+
Block* bb = ab ? operator()(ab) : NULL;
|
|
314
|
+
AtRule* aa = SASS_MEMORY_NEW(AtRule,
|
|
315
|
+
a->pstate(),
|
|
316
|
+
a->keyword(),
|
|
317
|
+
as,
|
|
318
|
+
bb,
|
|
319
|
+
av);
|
|
320
|
+
return aa;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
Statement* Expand::operator()(Declaration* d)
|
|
324
|
+
{
|
|
325
|
+
Block_Obj ab = d->block();
|
|
326
|
+
String_Obj old_p = d->property();
|
|
327
|
+
ExpressionObj prop = old_p->perform(&eval);
|
|
328
|
+
String_Obj new_p = Cast<String>(prop);
|
|
329
|
+
// we might get a color back
|
|
330
|
+
if (!new_p) {
|
|
331
|
+
sass::string str(prop->to_string(ctx.c_options));
|
|
332
|
+
new_p = SASS_MEMORY_NEW(String_Constant, old_p->pstate(), str);
|
|
333
|
+
}
|
|
334
|
+
ExpressionObj value = d->value();
|
|
335
|
+
if (value) value = value->perform(&eval);
|
|
336
|
+
Block_Obj bb = ab ? operator()(ab) : NULL;
|
|
337
|
+
if (!bb) {
|
|
338
|
+
if (!value || (value->is_invisible() && !d->is_important())) {
|
|
339
|
+
if (d->is_custom_property()) {
|
|
340
|
+
error("Custom property values may not be empty.", d->value()->pstate(), traces);
|
|
341
|
+
} else {
|
|
342
|
+
return nullptr;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
Declaration* decl = SASS_MEMORY_NEW(Declaration,
|
|
347
|
+
d->pstate(),
|
|
348
|
+
new_p,
|
|
349
|
+
value,
|
|
350
|
+
d->is_important(),
|
|
351
|
+
d->is_custom_property(),
|
|
352
|
+
bb);
|
|
353
|
+
decl->tabs(d->tabs());
|
|
354
|
+
return decl;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
Statement* Expand::operator()(Assignment* a)
|
|
358
|
+
{
|
|
359
|
+
Env* env = environment();
|
|
360
|
+
const sass::string& var(a->variable());
|
|
361
|
+
if (a->is_global()) {
|
|
362
|
+
if (!env->has_global(var)) {
|
|
363
|
+
deprecated(
|
|
364
|
+
"!global assignments won't be able to declare new variables in future versions.",
|
|
365
|
+
"Consider adding `" + var + ": null` at the top level.",
|
|
366
|
+
true, a->pstate());
|
|
367
|
+
}
|
|
368
|
+
if (a->is_default()) {
|
|
369
|
+
if (env->has_global(var)) {
|
|
370
|
+
ExpressionObj e = Cast<Expression>(env->get_global(var));
|
|
371
|
+
if (!e || e->concrete_type() == Expression::NULL_VAL) {
|
|
372
|
+
env->set_global(var, a->value()->perform(&eval));
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
env->set_global(var, a->value()->perform(&eval));
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
env->set_global(var, a->value()->perform(&eval));
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
else if (a->is_default()) {
|
|
384
|
+
if (env->has_lexical(var)) {
|
|
385
|
+
auto cur = env;
|
|
386
|
+
while (cur && cur->is_lexical()) {
|
|
387
|
+
if (cur->has_local(var)) {
|
|
388
|
+
if (AST_Node_Obj node = cur->get_local(var)) {
|
|
389
|
+
ExpressionObj e = Cast<Expression>(node);
|
|
390
|
+
if (!e || e->concrete_type() == Expression::NULL_VAL) {
|
|
391
|
+
cur->set_local(var, a->value()->perform(&eval));
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
throw std::runtime_error("Env not in sync");
|
|
396
|
+
}
|
|
397
|
+
return 0;
|
|
398
|
+
}
|
|
399
|
+
cur = cur->parent();
|
|
400
|
+
}
|
|
401
|
+
throw std::runtime_error("Env not in sync");
|
|
402
|
+
}
|
|
403
|
+
else if (env->has_global(var)) {
|
|
404
|
+
if (AST_Node_Obj node = env->get_global(var)) {
|
|
405
|
+
ExpressionObj e = Cast<Expression>(node);
|
|
406
|
+
if (!e || e->concrete_type() == Expression::NULL_VAL) {
|
|
407
|
+
env->set_global(var, a->value()->perform(&eval));
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
else if (env->is_lexical()) {
|
|
412
|
+
env->set_local(var, a->value()->perform(&eval));
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
env->set_local(var, a->value()->perform(&eval));
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
env->set_lexical(var, a->value()->perform(&eval));
|
|
420
|
+
}
|
|
421
|
+
return 0;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
Statement* Expand::operator()(Import* imp)
|
|
425
|
+
{
|
|
426
|
+
Import_Obj result = SASS_MEMORY_NEW(Import, imp->pstate());
|
|
427
|
+
if (imp->import_queries() && imp->import_queries()->size()) {
|
|
428
|
+
ExpressionObj ex = imp->import_queries()->perform(&eval);
|
|
429
|
+
result->import_queries(Cast<List>(ex));
|
|
430
|
+
}
|
|
431
|
+
for ( size_t i = 0, S = imp->urls().size(); i < S; ++i) {
|
|
432
|
+
result->urls().push_back(imp->urls()[i]->perform(&eval));
|
|
433
|
+
}
|
|
434
|
+
// all resources have been dropped for Input_Stubs
|
|
435
|
+
// for ( size_t i = 0, S = imp->incs().size(); i < S; ++i) {}
|
|
436
|
+
return result.detach();
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
Statement* Expand::operator()(Import_Stub* i)
|
|
440
|
+
{
|
|
441
|
+
traces.push_back(Backtrace(i->pstate()));
|
|
442
|
+
// get parent node from call stack
|
|
443
|
+
AST_Node_Obj parent = call_stack.back();
|
|
444
|
+
if (Cast<Block>(parent) == NULL) {
|
|
445
|
+
error("Import directives may not be used within control directives or mixins.", i->pstate(), traces);
|
|
446
|
+
}
|
|
447
|
+
// we don't seem to need that actually afterall
|
|
448
|
+
Sass_Import_Entry import = sass_make_import(
|
|
449
|
+
i->imp_path().c_str(),
|
|
450
|
+
i->abs_path().c_str(),
|
|
451
|
+
0, 0
|
|
452
|
+
);
|
|
453
|
+
ctx.import_stack.push_back(import);
|
|
454
|
+
|
|
455
|
+
Block_Obj trace_block = SASS_MEMORY_NEW(Block, i->pstate());
|
|
456
|
+
Trace_Obj trace = SASS_MEMORY_NEW(Trace, i->pstate(), i->imp_path(), trace_block, 'i');
|
|
457
|
+
block_stack.back()->append(trace);
|
|
458
|
+
block_stack.push_back(trace_block);
|
|
459
|
+
|
|
460
|
+
const sass::string& abs_path(i->resource().abs_path);
|
|
461
|
+
append_block(ctx.sheets.at(abs_path).root);
|
|
462
|
+
sass_delete_import(ctx.import_stack.back());
|
|
463
|
+
ctx.import_stack.pop_back();
|
|
464
|
+
block_stack.pop_back();
|
|
465
|
+
traces.pop_back();
|
|
466
|
+
return 0;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
Statement* Expand::operator()(WarningRule* w)
|
|
470
|
+
{
|
|
471
|
+
// eval handles this too, because warnings may occur in functions
|
|
472
|
+
w->perform(&eval);
|
|
473
|
+
return 0;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
Statement* Expand::operator()(ErrorRule* e)
|
|
477
|
+
{
|
|
478
|
+
// eval handles this too, because errors may occur in functions
|
|
479
|
+
e->perform(&eval);
|
|
480
|
+
return 0;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
Statement* Expand::operator()(DebugRule* d)
|
|
484
|
+
{
|
|
485
|
+
// eval handles this too, because warnings may occur in functions
|
|
486
|
+
d->perform(&eval);
|
|
487
|
+
return 0;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
Statement* Expand::operator()(Comment* c)
|
|
491
|
+
{
|
|
492
|
+
if (ctx.output_style() == COMPRESSED) {
|
|
493
|
+
// comments should not be evaluated in compact
|
|
494
|
+
// https://github.com/sass/libsass/issues/2359
|
|
495
|
+
if (!c->is_important()) return NULL;
|
|
496
|
+
}
|
|
497
|
+
eval.is_in_comment = true;
|
|
498
|
+
Comment* rv = SASS_MEMORY_NEW(Comment, c->pstate(), Cast<String>(c->text()->perform(&eval)), c->is_important());
|
|
499
|
+
eval.is_in_comment = false;
|
|
500
|
+
// TODO: eval the text, once we're parsing/storing it as a String_Schema
|
|
501
|
+
return rv;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
Statement* Expand::operator()(If* i)
|
|
505
|
+
{
|
|
506
|
+
Env env(environment(), true);
|
|
507
|
+
env_stack.push_back(&env);
|
|
508
|
+
call_stack.push_back(i);
|
|
509
|
+
ExpressionObj rv = i->predicate()->perform(&eval);
|
|
510
|
+
if (*rv) {
|
|
511
|
+
append_block(i->block());
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
Block* alt = i->alternative();
|
|
515
|
+
if (alt) append_block(alt);
|
|
516
|
+
}
|
|
517
|
+
call_stack.pop_back();
|
|
518
|
+
env_stack.pop_back();
|
|
519
|
+
return 0;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// For does not create a new env scope
|
|
523
|
+
// But iteration vars are reset afterwards
|
|
524
|
+
Statement* Expand::operator()(ForRule* f)
|
|
525
|
+
{
|
|
526
|
+
sass::string variable(f->variable());
|
|
527
|
+
ExpressionObj low = f->lower_bound()->perform(&eval);
|
|
528
|
+
if (low->concrete_type() != Expression::NUMBER) {
|
|
529
|
+
traces.push_back(Backtrace(low->pstate()));
|
|
530
|
+
throw Exception::TypeMismatch(traces, *low, "integer");
|
|
531
|
+
}
|
|
532
|
+
ExpressionObj high = f->upper_bound()->perform(&eval);
|
|
533
|
+
if (high->concrete_type() != Expression::NUMBER) {
|
|
534
|
+
traces.push_back(Backtrace(high->pstate()));
|
|
535
|
+
throw Exception::TypeMismatch(traces, *high, "integer");
|
|
536
|
+
}
|
|
537
|
+
Number_Obj sass_start = Cast<Number>(low);
|
|
538
|
+
Number_Obj sass_end = Cast<Number>(high);
|
|
539
|
+
// check if units are valid for sequence
|
|
540
|
+
if (sass_start->unit() != sass_end->unit()) {
|
|
541
|
+
sass::ostream msg; msg << "Incompatible units: '"
|
|
542
|
+
<< sass_start->unit() << "' and '"
|
|
543
|
+
<< sass_end->unit() << "'.";
|
|
544
|
+
error(msg.str(), low->pstate(), traces);
|
|
545
|
+
}
|
|
546
|
+
double start = sass_start->value();
|
|
547
|
+
double end = sass_end->value();
|
|
548
|
+
// only create iterator once in this environment
|
|
549
|
+
Env env(environment(), true);
|
|
550
|
+
env_stack.push_back(&env);
|
|
551
|
+
call_stack.push_back(f);
|
|
552
|
+
Block* body = f->block();
|
|
553
|
+
if (start < end) {
|
|
554
|
+
if (f->is_inclusive()) ++end;
|
|
555
|
+
for (double i = start;
|
|
556
|
+
i < end;
|
|
557
|
+
++i) {
|
|
558
|
+
Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit());
|
|
559
|
+
env.set_local(variable, it);
|
|
560
|
+
append_block(body);
|
|
561
|
+
}
|
|
562
|
+
} else {
|
|
563
|
+
if (f->is_inclusive()) --end;
|
|
564
|
+
for (double i = start;
|
|
565
|
+
i > end;
|
|
566
|
+
--i) {
|
|
567
|
+
Number_Obj it = SASS_MEMORY_NEW(Number, low->pstate(), i, sass_end->unit());
|
|
568
|
+
env.set_local(variable, it);
|
|
569
|
+
append_block(body);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
call_stack.pop_back();
|
|
573
|
+
env_stack.pop_back();
|
|
574
|
+
return 0;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// Eval does not create a new env scope
|
|
578
|
+
// But iteration vars are reset afterwards
|
|
579
|
+
Statement* Expand::operator()(EachRule* e)
|
|
580
|
+
{
|
|
581
|
+
sass::vector<sass::string> variables(e->variables());
|
|
582
|
+
ExpressionObj expr = e->list()->perform(&eval);
|
|
583
|
+
List_Obj list;
|
|
584
|
+
Map_Obj map;
|
|
585
|
+
if (expr->concrete_type() == Expression::MAP) {
|
|
586
|
+
map = Cast<Map>(expr);
|
|
587
|
+
}
|
|
588
|
+
else if (SelectorList * ls = Cast<SelectorList>(expr)) {
|
|
589
|
+
ExpressionObj rv = Listize::perform(ls);
|
|
590
|
+
list = Cast<List>(rv);
|
|
591
|
+
}
|
|
592
|
+
else if (expr->concrete_type() != Expression::LIST) {
|
|
593
|
+
list = SASS_MEMORY_NEW(List, expr->pstate(), 1, SASS_COMMA);
|
|
594
|
+
list->append(expr);
|
|
595
|
+
}
|
|
596
|
+
else {
|
|
597
|
+
list = Cast<List>(expr);
|
|
598
|
+
}
|
|
599
|
+
// remember variables and then reset them
|
|
600
|
+
Env env(environment(), true);
|
|
601
|
+
env_stack.push_back(&env);
|
|
602
|
+
call_stack.push_back(e);
|
|
603
|
+
Block* body = e->block();
|
|
604
|
+
|
|
605
|
+
if (map) {
|
|
606
|
+
for (auto key : map->keys()) {
|
|
607
|
+
ExpressionObj k = key->perform(&eval);
|
|
608
|
+
ExpressionObj v = map->at(key)->perform(&eval);
|
|
609
|
+
|
|
610
|
+
if (variables.size() == 1) {
|
|
611
|
+
List_Obj variable = SASS_MEMORY_NEW(List, map->pstate(), 2, SASS_SPACE);
|
|
612
|
+
variable->append(k);
|
|
613
|
+
variable->append(v);
|
|
614
|
+
env.set_local(variables[0], variable);
|
|
615
|
+
} else {
|
|
616
|
+
env.set_local(variables[0], k);
|
|
617
|
+
env.set_local(variables[1], v);
|
|
618
|
+
}
|
|
619
|
+
append_block(body);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
// bool arglist = list->is_arglist();
|
|
624
|
+
if (list->length() == 1 && Cast<SelectorList>(list)) {
|
|
625
|
+
list = Cast<List>(list);
|
|
626
|
+
}
|
|
627
|
+
for (size_t i = 0, L = list->length(); i < L; ++i) {
|
|
628
|
+
ExpressionObj item = list->at(i);
|
|
629
|
+
// unwrap value if the expression is an argument
|
|
630
|
+
if (Argument_Obj arg = Cast<Argument>(item)) item = arg->value();
|
|
631
|
+
// check if we got passed a list of args (investigate)
|
|
632
|
+
if (List_Obj scalars = Cast<List>(item)) {
|
|
633
|
+
if (variables.size() == 1) {
|
|
634
|
+
List_Obj var = scalars;
|
|
635
|
+
// if (arglist) var = (*scalars)[0];
|
|
636
|
+
env.set_local(variables[0], var);
|
|
637
|
+
} else {
|
|
638
|
+
for (size_t j = 0, K = variables.size(); j < K; ++j) {
|
|
639
|
+
env.set_local(variables[j], j >= scalars->length()
|
|
640
|
+
? SASS_MEMORY_NEW(Null, expr->pstate())
|
|
641
|
+
: (*scalars)[j]->perform(&eval));
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
} else {
|
|
645
|
+
if (variables.size() > 0) {
|
|
646
|
+
env.set_local(variables.at(0), item);
|
|
647
|
+
for (size_t j = 1, K = variables.size(); j < K; ++j) {
|
|
648
|
+
ExpressionObj res = SASS_MEMORY_NEW(Null, expr->pstate());
|
|
649
|
+
env.set_local(variables[j], res);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
append_block(body);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
call_stack.pop_back();
|
|
657
|
+
env_stack.pop_back();
|
|
658
|
+
return 0;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
Statement* Expand::operator()(WhileRule* w)
|
|
662
|
+
{
|
|
663
|
+
ExpressionObj pred = w->predicate();
|
|
664
|
+
Block* body = w->block();
|
|
665
|
+
Env env(environment(), true);
|
|
666
|
+
env_stack.push_back(&env);
|
|
667
|
+
call_stack.push_back(w);
|
|
668
|
+
ExpressionObj cond = pred->perform(&eval);
|
|
669
|
+
while (!cond->is_false()) {
|
|
670
|
+
append_block(body);
|
|
671
|
+
cond = pred->perform(&eval);
|
|
672
|
+
}
|
|
673
|
+
call_stack.pop_back();
|
|
674
|
+
env_stack.pop_back();
|
|
675
|
+
return 0;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
Statement* Expand::operator()(Return* r)
|
|
679
|
+
{
|
|
680
|
+
error("@return may only be used within a function", r->pstate(), traces);
|
|
681
|
+
return 0;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
Statement* Expand::operator()(ExtendRule* e)
|
|
685
|
+
{
|
|
686
|
+
|
|
687
|
+
// evaluate schema first
|
|
688
|
+
if (e->schema()) {
|
|
689
|
+
e->selector(eval(e->schema()));
|
|
690
|
+
e->isOptional(e->selector()->is_optional());
|
|
691
|
+
}
|
|
692
|
+
// evaluate the selector
|
|
693
|
+
e->selector(eval(e->selector()));
|
|
694
|
+
|
|
695
|
+
if (e->selector()) {
|
|
696
|
+
|
|
697
|
+
for (auto complex : e->selector()->elements()) {
|
|
698
|
+
|
|
699
|
+
if (complex->length() != 1) {
|
|
700
|
+
error("complex selectors may not be extended.", complex->pstate(), traces);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
if (const CompoundSelector* compound = complex->first()->getCompound()) {
|
|
704
|
+
|
|
705
|
+
if (compound->length() != 1) {
|
|
706
|
+
|
|
707
|
+
sass::ostream sels; bool addComma = false;
|
|
708
|
+
sels << "Compound selectors may no longer be extended.\n";
|
|
709
|
+
sels << "Consider `@extend ";
|
|
710
|
+
for (auto sel : compound->elements()) {
|
|
711
|
+
if (addComma) sels << ", ";
|
|
712
|
+
sels << sel->to_sass();
|
|
713
|
+
addComma = true;
|
|
714
|
+
}
|
|
715
|
+
sels << "` instead.\n";
|
|
716
|
+
sels << "See http://bit.ly/ExtendCompound for details.";
|
|
717
|
+
|
|
718
|
+
warning(sels.str(), compound->pstate());
|
|
719
|
+
|
|
720
|
+
// Make this an error once deprecation is over
|
|
721
|
+
for (SimpleSelectorObj simple : compound->elements()) {
|
|
722
|
+
// Pass every selector we ever see to extender (to make them findable for extend)
|
|
723
|
+
ctx.extender.addExtension(selector(), simple, mediaStack.back(), e->isOptional());
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
}
|
|
727
|
+
else {
|
|
728
|
+
// Pass every selector we ever see to extender (to make them findable for extend)
|
|
729
|
+
ctx.extender.addExtension(selector(), compound->first(), mediaStack.back(), e->isOptional());
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
error("complex selectors may not be extended.", complex->pstate(), traces);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
return nullptr;
|
|
740
|
+
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
Statement* Expand::operator()(Definition* d)
|
|
744
|
+
{
|
|
745
|
+
Env* env = environment();
|
|
746
|
+
Definition_Obj dd = SASS_MEMORY_COPY(d);
|
|
747
|
+
env->local_frame()[d->name() +
|
|
748
|
+
(d->type() == Definition::MIXIN ? "[m]" : "[f]")] = dd;
|
|
749
|
+
|
|
750
|
+
if (d->type() == Definition::FUNCTION && (
|
|
751
|
+
Prelexer::calc_fn_call(d->name().c_str()) ||
|
|
752
|
+
d->name() == "element" ||
|
|
753
|
+
d->name() == "expression" ||
|
|
754
|
+
d->name() == "url"
|
|
755
|
+
)) {
|
|
756
|
+
deprecated(
|
|
757
|
+
"Naming a function \"" + d->name() + "\" is disallowed and will be an error in future versions of Sass.",
|
|
758
|
+
"This name conflicts with an existing CSS function with special parse rules.",
|
|
759
|
+
false, d->pstate()
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// set the static link so we can have lexical scoping
|
|
764
|
+
dd->environment(env);
|
|
765
|
+
return 0;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
Statement* Expand::operator()(Mixin_Call* c)
|
|
769
|
+
{
|
|
770
|
+
|
|
771
|
+
if (recursions > maxRecursion) {
|
|
772
|
+
throw Exception::StackError(traces, *c);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
recursions ++;
|
|
776
|
+
|
|
777
|
+
Env* env = environment();
|
|
778
|
+
sass::string full_name(c->name() + "[m]");
|
|
779
|
+
if (!env->has(full_name)) {
|
|
780
|
+
error("no mixin named " + c->name(), c->pstate(), traces);
|
|
781
|
+
}
|
|
782
|
+
Definition_Obj def = Cast<Definition>((*env)[full_name]);
|
|
783
|
+
Block_Obj body = def->block();
|
|
784
|
+
Parameters_Obj params = def->parameters();
|
|
785
|
+
|
|
786
|
+
if (c->block() && c->name() != "@content" && !body->has_content()) {
|
|
787
|
+
error("Mixin \"" + c->name() + "\" does not accept a content block.", c->pstate(), traces);
|
|
788
|
+
}
|
|
789
|
+
ExpressionObj rv = c->arguments()->perform(&eval);
|
|
790
|
+
Arguments_Obj args = Cast<Arguments>(rv);
|
|
791
|
+
sass::string msg(", in mixin `" + c->name() + "`");
|
|
792
|
+
traces.push_back(Backtrace(c->pstate(), msg));
|
|
793
|
+
ctx.callee_stack.push_back({
|
|
794
|
+
c->name().c_str(),
|
|
795
|
+
c->pstate().getPath(),
|
|
796
|
+
c->pstate().getLine(),
|
|
797
|
+
c->pstate().getColumn(),
|
|
798
|
+
SASS_CALLEE_MIXIN,
|
|
799
|
+
{ env }
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
Env new_env(def->environment());
|
|
803
|
+
env_stack.push_back(&new_env);
|
|
804
|
+
if (c->block()) {
|
|
805
|
+
Parameters_Obj params = c->block_parameters();
|
|
806
|
+
if (!params) params = SASS_MEMORY_NEW(Parameters, c->pstate());
|
|
807
|
+
// represent mixin content blocks as thunks/closures
|
|
808
|
+
Definition_Obj thunk = SASS_MEMORY_NEW(Definition,
|
|
809
|
+
c->pstate(),
|
|
810
|
+
"@content",
|
|
811
|
+
params,
|
|
812
|
+
c->block(),
|
|
813
|
+
Definition::MIXIN);
|
|
814
|
+
thunk->environment(env);
|
|
815
|
+
new_env.local_frame()["@content[m]"] = thunk;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
bind(sass::string("Mixin"), c->name(), params, args, &new_env, &eval, traces);
|
|
819
|
+
|
|
820
|
+
Block_Obj trace_block = SASS_MEMORY_NEW(Block, c->pstate());
|
|
821
|
+
Trace_Obj trace = SASS_MEMORY_NEW(Trace, c->pstate(), c->name(), trace_block);
|
|
822
|
+
|
|
823
|
+
env->set_global("is_in_mixin", bool_true);
|
|
824
|
+
if (Block* pr = block_stack.back()) {
|
|
825
|
+
trace_block->is_root(pr->is_root());
|
|
826
|
+
}
|
|
827
|
+
block_stack.push_back(trace_block);
|
|
828
|
+
for (auto bb : body->elements()) {
|
|
829
|
+
if (StyleRule* r = Cast<StyleRule>(bb)) {
|
|
830
|
+
r->is_root(trace_block->is_root());
|
|
831
|
+
}
|
|
832
|
+
Statement_Obj ith = bb->perform(this);
|
|
833
|
+
if (ith) trace->block()->append(ith);
|
|
834
|
+
}
|
|
835
|
+
block_stack.pop_back();
|
|
836
|
+
env->del_global("is_in_mixin");
|
|
837
|
+
|
|
838
|
+
ctx.callee_stack.pop_back();
|
|
839
|
+
env_stack.pop_back();
|
|
840
|
+
traces.pop_back();
|
|
841
|
+
|
|
842
|
+
recursions --;
|
|
843
|
+
return trace.detach();
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
Statement* Expand::operator()(Content* c)
|
|
847
|
+
{
|
|
848
|
+
Env* env = environment();
|
|
849
|
+
// convert @content directives into mixin calls to the underlying thunk
|
|
850
|
+
if (!env->has("@content[m]")) return 0;
|
|
851
|
+
Arguments_Obj args = c->arguments();
|
|
852
|
+
if (!args) args = SASS_MEMORY_NEW(Arguments, c->pstate());
|
|
853
|
+
|
|
854
|
+
Mixin_Call_Obj call = SASS_MEMORY_NEW(Mixin_Call,
|
|
855
|
+
c->pstate(),
|
|
856
|
+
"@content",
|
|
857
|
+
args);
|
|
858
|
+
|
|
859
|
+
Trace_Obj trace = Cast<Trace>(call->perform(this));
|
|
860
|
+
return trace.detach();
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// process and add to last block on stack
|
|
864
|
+
inline void Expand::append_block(Block* b)
|
|
865
|
+
{
|
|
866
|
+
if (b->is_root()) call_stack.push_back(b);
|
|
867
|
+
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
|
868
|
+
Statement* stm = b->at(i);
|
|
869
|
+
Statement_Obj ith = stm->perform(this);
|
|
870
|
+
if (ith) block_stack.back()->append(ith);
|
|
871
|
+
}
|
|
872
|
+
if (b->is_root()) call_stack.pop_back();
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
}
|