sassc 2.2.1 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +13 -0
- data/Rakefile +1 -3
- data/ext/extconf.rb +13 -5
- data/ext/libsass/VERSION +1 -1
- data/ext/libsass/include/sass/base.h +2 -1
- data/ext/libsass/include/sass/context.h +1 -0
- data/ext/libsass/src/ast.cpp +49 -59
- data/ext/libsass/src/ast.hpp +263 -102
- data/ext/libsass/src/ast_def_macros.hpp +8 -0
- data/ext/libsass/src/ast_fwd_decl.cpp +2 -1
- data/ext/libsass/src/ast_fwd_decl.hpp +40 -116
- data/ext/libsass/src/ast_helpers.hpp +292 -0
- data/ext/libsass/src/ast_sel_cmp.cpp +209 -722
- data/ext/libsass/src/ast_sel_super.cpp +539 -0
- data/ext/libsass/src/ast_sel_unify.cpp +207 -212
- data/ext/libsass/src/ast_sel_weave.cpp +616 -0
- data/ext/libsass/src/ast_selectors.cpp +559 -1001
- data/ext/libsass/src/ast_selectors.hpp +311 -367
- data/ext/libsass/src/ast_supports.cpp +1 -17
- data/ext/libsass/src/ast_values.cpp +216 -29
- data/ext/libsass/src/ast_values.hpp +42 -33
- data/ext/libsass/src/bind.cpp +1 -1
- data/ext/libsass/src/cencode.c +4 -6
- data/ext/libsass/src/check_nesting.cpp +5 -6
- data/ext/libsass/src/check_nesting.hpp +4 -0
- data/ext/libsass/src/color_maps.cpp +11 -10
- data/ext/libsass/src/color_maps.hpp +0 -8
- data/ext/libsass/src/constants.cpp +5 -0
- data/ext/libsass/src/constants.hpp +6 -0
- data/ext/libsass/src/context.cpp +30 -60
- data/ext/libsass/src/context.hpp +8 -20
- data/ext/libsass/src/cssize.cpp +36 -120
- data/ext/libsass/src/cssize.hpp +4 -10
- data/ext/libsass/src/dart_helpers.hpp +199 -0
- data/ext/libsass/src/debugger.hpp +364 -207
- data/ext/libsass/src/emitter.cpp +3 -4
- data/ext/libsass/src/emitter.hpp +0 -2
- data/ext/libsass/src/environment.hpp +5 -0
- data/ext/libsass/src/error_handling.cpp +21 -0
- data/ext/libsass/src/error_handling.hpp +25 -3
- data/ext/libsass/src/eval.cpp +33 -153
- data/ext/libsass/src/eval.hpp +11 -13
- data/ext/libsass/src/eval_selectors.cpp +75 -0
- data/ext/libsass/src/expand.cpp +214 -167
- data/ext/libsass/src/expand.hpp +26 -6
- data/ext/libsass/src/extender.cpp +1186 -0
- data/ext/libsass/src/extender.hpp +399 -0
- data/ext/libsass/src/extension.cpp +43 -0
- data/ext/libsass/src/extension.hpp +89 -0
- data/ext/libsass/src/file.cpp +15 -14
- data/ext/libsass/src/file.hpp +5 -12
- data/ext/libsass/src/fn_colors.cpp +12 -10
- data/ext/libsass/src/fn_lists.cpp +12 -11
- data/ext/libsass/src/fn_miscs.cpp +22 -34
- data/ext/libsass/src/fn_numbers.cpp +13 -6
- data/ext/libsass/src/fn_selectors.cpp +94 -124
- data/ext/libsass/src/fn_strings.cpp +16 -14
- data/ext/libsass/src/fn_utils.cpp +5 -6
- data/ext/libsass/src/fn_utils.hpp +9 -3
- data/ext/libsass/src/inspect.cpp +154 -117
- data/ext/libsass/src/inspect.hpp +10 -8
- data/ext/libsass/src/lexer.cpp +17 -81
- data/ext/libsass/src/lexer.hpp +5 -16
- data/ext/libsass/src/listize.cpp +22 -36
- data/ext/libsass/src/listize.hpp +8 -9
- data/ext/libsass/src/memory/SharedPtr.hpp +39 -5
- data/ext/libsass/src/operation.hpp +27 -17
- data/ext/libsass/src/operators.cpp +1 -0
- data/ext/libsass/src/ordered_map.hpp +112 -0
- data/ext/libsass/src/output.cpp +30 -49
- data/ext/libsass/src/output.hpp +1 -1
- data/ext/libsass/src/parser.cpp +211 -381
- data/ext/libsass/src/parser.hpp +17 -15
- data/ext/libsass/src/parser_selectors.cpp +189 -0
- data/ext/libsass/src/permutate.hpp +140 -0
- data/ext/libsass/src/position.hpp +1 -1
- data/ext/libsass/src/prelexer.cpp +6 -6
- data/ext/libsass/src/remove_placeholders.cpp +55 -56
- data/ext/libsass/src/remove_placeholders.hpp +21 -18
- data/ext/libsass/src/sass.hpp +1 -0
- data/ext/libsass/src/sass2scss.cpp +4 -4
- data/ext/libsass/src/sass_context.cpp +42 -91
- data/ext/libsass/src/sass_context.hpp +2 -2
- data/ext/libsass/src/sass_functions.cpp +1 -1
- data/ext/libsass/src/sass_values.cpp +0 -1
- data/ext/libsass/src/stylesheet.cpp +22 -0
- data/ext/libsass/src/stylesheet.hpp +57 -0
- data/ext/libsass/src/to_value.cpp +2 -2
- data/ext/libsass/src/to_value.hpp +1 -1
- data/ext/libsass/src/units.cpp +5 -3
- data/ext/libsass/src/util.cpp +10 -12
- data/ext/libsass/src/util.hpp +2 -3
- data/ext/libsass/src/util_string.cpp +111 -61
- data/ext/libsass/src/util_string.hpp +61 -8
- data/lib/sassc/engine.rb +5 -3
- data/lib/sassc/functions_handler.rb +8 -8
- data/lib/sassc/native.rb +1 -1
- data/lib/sassc/script.rb +4 -4
- data/lib/sassc/version.rb +1 -1
- data/test/functions_test.rb +18 -1
- data/test/native_test.rb +1 -1
- metadata +17 -12
- data/ext/libsass/src/extend.cpp +0 -2132
- data/ext/libsass/src/extend.hpp +0 -86
- data/ext/libsass/src/node.cpp +0 -322
- data/ext/libsass/src/node.hpp +0 -118
- data/ext/libsass/src/paths.hpp +0 -71
- data/ext/libsass/src/sass_util.cpp +0 -152
- data/ext/libsass/src/sass_util.hpp +0 -256
- data/ext/libsass/src/subset_map.cpp +0 -58
- data/ext/libsass/src/subset_map.hpp +0 -76
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aebf2c0084662833c589a03cd0de02b8b72d3968f4c33a27d1b37c330a692bf2
|
4
|
+
data.tar.gz: b828b00fb88f9ed8414cd7abfd86afdced6458f47e9560789690d8f9a3670c43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 802546b5350e0b550b8ba01a125e03dbe52ce9541003ae811782b4cf2c197e12b5056520376a5dbf5317a2b033f70808fafd1e62fe40ecd12cf2d56c52881c6e
|
7
|
+
data.tar.gz: 864f16c8f74351159107fb1ccfd3abf837447b41a846a1c990481e7b28732222c4abde988aebe953fb500db2424a0d7d7ce2fc1c351ed2711aa1fa5ea88e37c1
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
- **2.3.0**
|
2
|
+
- [Fix rake gem:native task](https://github.com/sass/sassc-ruby/pull/196)
|
3
|
+
- [disable lto flag for darwin + nix](https://github.com/sass/sassc-ruby/pull/166)
|
4
|
+
- [Sort input file list](https://github.com/sass/sassc-ruby/pull/178)
|
5
|
+
- [Set appropriate encoding for source_map](https://github.com/sass/sassc-ruby/pull/152)
|
6
|
+
- [allow passing functions directly](https://github.com/sass/sassc-ruby/pull/162)
|
7
|
+
- [always dispose data context](https://github.com/sass/sassc-ruby/pull/161)
|
8
|
+
- [Update libsass to 3.6.3](https://github.com/sass/sassc-ruby/pull/164)
|
9
|
+
- [Restore strip symbols](https://github.com/sass/sassc-ruby/pull/184)
|
10
|
+
- [Default --march-tune-native to false](https://github.com/sass/sassc-ruby/pull/158)
|
11
|
+
- [Fix compile issue on Mac OS X](https://github.com/sass/sassc-ruby/pull/174)
|
12
|
+
- [Test on TruffleRuby in TravisCI](https://github.com/sass/sassc-ruby/pull/171)
|
13
|
+
- [Use RbConfig::MAKEFILE_CONFIG['DLEXT'] instead of hardcoding extensions](https://github.com/sass/sassc-ruby/pull/173)
|
1
14
|
- **2.2.1**
|
2
15
|
- [Fix LoadError on some non-rvm environments](https://github.com/sass/sassc-ruby/pull/156)
|
3
16
|
- **2.2.0**
|
data/Rakefile
CHANGED
@@ -36,9 +36,7 @@ task 'gem:native' do
|
|
36
36
|
|
37
37
|
# The RUBY_CC_VERSION here doesn't matter for the final package.
|
38
38
|
# Only one version should be specified, as the shared library is Ruby-agnostic.
|
39
|
-
|
40
|
-
# g++-multilib is installed for 64->32-bit cross-compilation.
|
41
|
-
RakeCompilerDock.sh "sudo apt-get install -y g++-multilib && gem i rake bundler --no-document && bundle && "\
|
39
|
+
RakeCompilerDock.sh "gem i rake bundler --no-document && bundle && "\
|
42
40
|
"rake clean && rake cross native gem MAKE='nice make -j`nproc`' "\
|
43
41
|
"RUBY_CC_VERSION=2.6.0 CLEAN=1"
|
44
42
|
end
|
data/ext/extconf.rb
CHANGED
@@ -19,13 +19,17 @@ if enable_config('static-stdlib', false)
|
|
19
19
|
$LDFLAGS << ' -static-libgcc -static-libstdc++'
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
if enable_config('march-tune-native', true)
|
22
|
+
if enable_config('march-tune-native', false)
|
24
23
|
$CFLAGS << ' -march=native -mtune=native'
|
25
24
|
$CXXFLAGS << ' -march=native -mtune=native'
|
26
25
|
end
|
27
26
|
|
28
|
-
|
27
|
+
# darwin nix clang doesn't support lto
|
28
|
+
# disable -lto flag for darwin + nix
|
29
|
+
# see: https://github.com/sass/sassc-ruby/issues/148
|
30
|
+
enable_lto_by_default = (Gem::Platform.local.os == "darwin" && !ENV['NIX_CC'].nil?)
|
31
|
+
|
32
|
+
if enable_config('lto', enable_lto_by_default)
|
29
33
|
$CFLAGS << ' -flto'
|
30
34
|
$CXXFLAGS << ' -flto'
|
31
35
|
$LDFLAGS << ' -flto'
|
@@ -56,10 +60,14 @@ $INCFLAGS << " -I$(srcdir)/libsass/include"
|
|
56
60
|
$VPATH << "$(srcdir)/libsass/src"
|
57
61
|
Dir.chdir(__dir__) do
|
58
62
|
$VPATH += Dir['libsass/src/*/'].map { |p| "$(srcdir)/#{p}" }
|
59
|
-
$srcs = Dir['libsass/src/**/*.{c,cpp}']
|
63
|
+
$srcs = Dir['libsass/src/**/*.{c,cpp}'].sort
|
60
64
|
end
|
61
65
|
|
62
|
-
|
66
|
+
# libsass.bundle malformed object (unknown load command 7) on Mac OS X
|
67
|
+
# See https://github.com/sass/sassc-ruby/pull/174
|
68
|
+
if enable_config('strip', RbConfig::CONFIG['host_os'].downcase !~ /darwin/)
|
69
|
+
MakeMakefile::LINK_SO << "\nstrip -x $@"
|
70
|
+
end
|
63
71
|
|
64
72
|
# Don't link libruby.
|
65
73
|
$LIBRUBYARG = nil
|
data/ext/libsass/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.6.
|
1
|
+
3.6.3
|
@@ -134,6 +134,7 @@ ADDAPI char* ADDCALL sass_context_take_error_json (struct Sass_Context* ctx);
|
|
134
134
|
ADDAPI char* ADDCALL sass_context_take_error_text (struct Sass_Context* ctx);
|
135
135
|
ADDAPI char* ADDCALL sass_context_take_error_message (struct Sass_Context* ctx);
|
136
136
|
ADDAPI char* ADDCALL sass_context_take_error_file (struct Sass_Context* ctx);
|
137
|
+
ADDAPI char* ADDCALL sass_context_take_error_src (struct Sass_Context* ctx);
|
137
138
|
ADDAPI char* ADDCALL sass_context_take_output_string (struct Sass_Context* ctx);
|
138
139
|
ADDAPI char* ADDCALL sass_context_take_source_map_string (struct Sass_Context* ctx);
|
139
140
|
ADDAPI char** ADDCALL sass_context_take_included_files (struct Sass_Context* ctx);
|
data/ext/libsass/src/ast.cpp
CHANGED
@@ -1,19 +1,8 @@
|
|
1
|
+
// sass.hpp must go before all system headers to get the
|
2
|
+
// __EXTENSIONS__ fix on Solaris.
|
1
3
|
#include "sass.hpp"
|
4
|
+
|
2
5
|
#include "ast.hpp"
|
3
|
-
#include "context.hpp"
|
4
|
-
#include "node.hpp"
|
5
|
-
#include "eval.hpp"
|
6
|
-
#include "extend.hpp"
|
7
|
-
#include "emitter.hpp"
|
8
|
-
#include "color_maps.hpp"
|
9
|
-
#include "ast_fwd_decl.hpp"
|
10
|
-
#include <set>
|
11
|
-
#include <iomanip>
|
12
|
-
#include <iostream>
|
13
|
-
#include <algorithm>
|
14
|
-
#include <functional>
|
15
|
-
#include <cctype>
|
16
|
-
#include <locale>
|
17
6
|
|
18
7
|
namespace Sass {
|
19
8
|
|
@@ -69,7 +58,7 @@ namespace Sass {
|
|
69
58
|
pstate_.offset += pstate - pstate_ + pstate.offset;
|
70
59
|
}
|
71
60
|
|
72
|
-
|
61
|
+
std::string AST_Node::to_string(Sass_Inspect_Options opt) const
|
73
62
|
{
|
74
63
|
Sass_Output_Options out(opt);
|
75
64
|
Emitter emitter(out);
|
@@ -80,19 +69,21 @@ namespace Sass {
|
|
80
69
|
return i.get_buffer();
|
81
70
|
}
|
82
71
|
|
83
|
-
|
72
|
+
std::string AST_Node::to_css(Sass_Inspect_Options opt) const
|
84
73
|
{
|
85
|
-
|
74
|
+
opt.output_style = TO_CSS;
|
75
|
+
Sass_Output_Options out(opt);
|
76
|
+
Emitter emitter(out);
|
77
|
+
Inspect i(emitter);
|
78
|
+
i.in_declaration = true;
|
79
|
+
// ToDo: inspect should be const
|
80
|
+
const_cast<AST_Node*>(this)->perform(&i);
|
81
|
+
return i.get_buffer();
|
86
82
|
}
|
87
83
|
|
88
|
-
|
89
|
-
/////////////////////////////////////////////////////////////////////////
|
90
|
-
|
91
|
-
Expression_Obj Hashed::at(Expression_Obj k) const
|
84
|
+
std::string AST_Node::to_string() const
|
92
85
|
{
|
93
|
-
|
94
|
-
{ return elements_.at(k); }
|
95
|
-
else { return {}; }
|
86
|
+
return to_string({ NESTED, 5 });
|
96
87
|
}
|
97
88
|
|
98
89
|
/////////////////////////////////////////////////////////////////////////
|
@@ -137,6 +128,14 @@ namespace Sass {
|
|
137
128
|
is_root_(ptr->is_root_)
|
138
129
|
{ }
|
139
130
|
|
131
|
+
bool Block::isInvisible() const
|
132
|
+
{
|
133
|
+
for (auto& item : elements()) {
|
134
|
+
if (!item->is_invisible()) return false;
|
135
|
+
}
|
136
|
+
return true;
|
137
|
+
}
|
138
|
+
|
140
139
|
bool Block::has_content()
|
141
140
|
{
|
142
141
|
for (size_t i = 0, L = elements().size(); i < L; ++i) {
|
@@ -163,19 +162,20 @@ namespace Sass {
|
|
163
162
|
/////////////////////////////////////////////////////////////////////////
|
164
163
|
/////////////////////////////////////////////////////////////////////////
|
165
164
|
|
166
|
-
Ruleset::Ruleset(ParserState pstate,
|
167
|
-
: Has_Block(pstate, b), selector_(s), is_root_(false)
|
165
|
+
Ruleset::Ruleset(ParserState pstate, SelectorListObj s, Block_Obj b)
|
166
|
+
: Has_Block(pstate, b), selector_(s), schema_(), is_root_(false)
|
168
167
|
{ statement_type(RULESET); }
|
169
168
|
Ruleset::Ruleset(const Ruleset* ptr)
|
170
169
|
: Has_Block(ptr),
|
171
170
|
selector_(ptr->selector_),
|
171
|
+
schema_(ptr->schema_),
|
172
172
|
is_root_(ptr->is_root_)
|
173
173
|
{ statement_type(RULESET); }
|
174
174
|
|
175
175
|
bool Ruleset::is_invisible() const {
|
176
|
-
if (
|
177
|
-
for (size_t i = 0, L = sl->length(); i < L;
|
178
|
-
if (!(*sl)[i]->
|
176
|
+
if (const SelectorList * sl = Cast<SelectorList>(selector())) {
|
177
|
+
for (size_t i = 0, L = sl->length(); i < L; i += 1)
|
178
|
+
if (!(*sl)[i]->isInvisible()) return false;
|
179
179
|
}
|
180
180
|
return true;
|
181
181
|
}
|
@@ -212,30 +212,7 @@ namespace Sass {
|
|
212
212
|
/////////////////////////////////////////////////////////////////////////
|
213
213
|
/////////////////////////////////////////////////////////////////////////
|
214
214
|
|
215
|
-
|
216
|
-
: Has_Block(pstate, b), media_queries_(mqs)
|
217
|
-
{ statement_type(MEDIA); }
|
218
|
-
Media_Block::Media_Block(const Media_Block* ptr)
|
219
|
-
: Has_Block(ptr), media_queries_(ptr->media_queries_)
|
220
|
-
{ statement_type(MEDIA); }
|
221
|
-
|
222
|
-
bool Media_Block::is_invisible() const {
|
223
|
-
for (size_t i = 0, L = block()->length(); i < L; ++i) {
|
224
|
-
Statement_Obj stm = block()->at(i);
|
225
|
-
if (!stm->is_invisible()) return false;
|
226
|
-
}
|
227
|
-
return true;
|
228
|
-
}
|
229
|
-
|
230
|
-
bool Media_Block::bubbles()
|
231
|
-
{
|
232
|
-
return true;
|
233
|
-
}
|
234
|
-
|
235
|
-
/////////////////////////////////////////////////////////////////////////
|
236
|
-
/////////////////////////////////////////////////////////////////////////
|
237
|
-
|
238
|
-
Directive::Directive(ParserState pstate, std::string kwd, Selector_List_Obj sel, Block_Obj b, Expression_Obj val)
|
215
|
+
Directive::Directive(ParserState pstate, std::string kwd, SelectorListObj sel, Block_Obj b, Expression_Obj val)
|
239
216
|
: Has_Block(pstate, b), keyword_(kwd), selector_(sel), value_(val) // set value manually if needed
|
240
217
|
{ statement_type(DIRECTIVE); }
|
241
218
|
Directive::Directive(const Directive* ptr)
|
@@ -450,11 +427,19 @@ namespace Sass {
|
|
450
427
|
/////////////////////////////////////////////////////////////////////////
|
451
428
|
/////////////////////////////////////////////////////////////////////////
|
452
429
|
|
453
|
-
|
454
|
-
: Statement(pstate), selector_(s)
|
430
|
+
ExtendRule::ExtendRule(ParserState pstate, SelectorListObj s)
|
431
|
+
: Statement(pstate), isOptional_(false), selector_(s), schema_()
|
455
432
|
{ statement_type(EXTEND); }
|
456
|
-
|
457
|
-
|
433
|
+
ExtendRule::ExtendRule(ParserState pstate, Selector_Schema_Obj s)
|
434
|
+
: Statement(pstate), isOptional_(false), selector_(), schema_(s)
|
435
|
+
{
|
436
|
+
statement_type(EXTEND);
|
437
|
+
}
|
438
|
+
ExtendRule::ExtendRule(const ExtendRule* ptr)
|
439
|
+
: Statement(ptr),
|
440
|
+
isOptional_(ptr->isOptional_),
|
441
|
+
selector_(ptr->selector_),
|
442
|
+
schema_(ptr->schema_)
|
458
443
|
{ statement_type(EXTEND); }
|
459
444
|
|
460
445
|
/////////////////////////////////////////////////////////////////////////
|
@@ -923,8 +908,13 @@ namespace Sass {
|
|
923
908
|
/////////////////////////////////////////////////////////////////////////
|
924
909
|
/////////////////////////////////////////////////////////////////////////
|
925
910
|
|
911
|
+
// If you forget to add a class here you will get
|
912
|
+
// undefined reference to `vtable for Sass::Class'
|
913
|
+
|
926
914
|
IMPLEMENT_AST_OPERATORS(Ruleset);
|
927
|
-
IMPLEMENT_AST_OPERATORS(
|
915
|
+
IMPLEMENT_AST_OPERATORS(MediaRule);
|
916
|
+
IMPLEMENT_AST_OPERATORS(CssMediaRule);
|
917
|
+
IMPLEMENT_AST_OPERATORS(CssMediaQuery);
|
928
918
|
IMPLEMENT_AST_OPERATORS(Import);
|
929
919
|
IMPLEMENT_AST_OPERATORS(Import_Stub);
|
930
920
|
IMPLEMENT_AST_OPERATORS(Directive);
|
@@ -934,7 +924,7 @@ namespace Sass {
|
|
934
924
|
IMPLEMENT_AST_OPERATORS(For);
|
935
925
|
IMPLEMENT_AST_OPERATORS(If);
|
936
926
|
IMPLEMENT_AST_OPERATORS(Mixin_Call);
|
937
|
-
IMPLEMENT_AST_OPERATORS(
|
927
|
+
IMPLEMENT_AST_OPERATORS(ExtendRule);
|
938
928
|
IMPLEMENT_AST_OPERATORS(Media_Query);
|
939
929
|
IMPLEMENT_AST_OPERATORS(Media_Query_Expression);
|
940
930
|
IMPLEMENT_AST_OPERATORS(Debug);
|
data/ext/libsass/src/ast.hpp
CHANGED
@@ -5,47 +5,22 @@
|
|
5
5
|
// __EXTENSIONS__ fix on Solaris.
|
6
6
|
#include "sass.hpp"
|
7
7
|
|
8
|
-
#include <set>
|
9
|
-
#include <deque>
|
10
|
-
#include <vector>
|
11
|
-
#include <string>
|
12
|
-
#include <sstream>
|
13
|
-
#include <iostream>
|
14
8
|
#include <typeinfo>
|
15
|
-
#include <
|
9
|
+
#include <unordered_map>
|
10
|
+
|
16
11
|
#include "sass/base.h"
|
12
|
+
#include "ast_helpers.hpp"
|
17
13
|
#include "ast_fwd_decl.hpp"
|
14
|
+
#include "ast_def_macros.hpp"
|
18
15
|
|
19
|
-
#include "
|
20
|
-
#include "units.hpp"
|
21
|
-
#include "context.hpp"
|
16
|
+
#include "file.hpp"
|
22
17
|
#include "position.hpp"
|
23
|
-
#include "constants.hpp"
|
24
18
|
#include "operation.hpp"
|
25
|
-
#include "position.hpp"
|
26
|
-
#include "inspect.hpp"
|
27
|
-
#include "source_map.hpp"
|
28
19
|
#include "environment.hpp"
|
29
|
-
#include "error_handling.hpp"
|
30
|
-
#include "ast_def_macros.hpp"
|
31
|
-
#include "ast_fwd_decl.hpp"
|
32
|
-
#include "source_map.hpp"
|
33
20
|
#include "fn_utils.hpp"
|
34
21
|
|
35
|
-
#include "sass.h"
|
36
|
-
|
37
22
|
namespace Sass {
|
38
23
|
|
39
|
-
// easier to search with name
|
40
|
-
const bool DELAYED = true;
|
41
|
-
|
42
|
-
// ToDo: should this really be hardcoded
|
43
|
-
// Note: most methods follow precision option
|
44
|
-
const double NUMBER_EPSILON = 1e-12;
|
45
|
-
|
46
|
-
// macro to test if numbers are equal within a small error margin
|
47
|
-
#define NEAR_EQUAL(lhs, rhs) std::fabs(lhs - rhs) < NUMBER_EPSILON
|
48
|
-
|
49
24
|
// ToDo: where does this fit best?
|
50
25
|
// We don't share this with C-API?
|
51
26
|
class Operand {
|
@@ -101,8 +76,9 @@ namespace Sass {
|
|
101
76
|
virtual size_t hash() const { return 0; }
|
102
77
|
virtual std::string inspect() const { return to_string({ INSPECT, 5 }); }
|
103
78
|
virtual std::string to_sass() const { return to_string({ TO_SASS, 5 }); }
|
104
|
-
virtual
|
105
|
-
virtual
|
79
|
+
virtual std::string to_string(Sass_Inspect_Options opt) const;
|
80
|
+
virtual std::string to_css(Sass_Inspect_Options opt) const;
|
81
|
+
virtual std::string to_string() const;
|
106
82
|
virtual void cloneChildren() {};
|
107
83
|
// generic find function (not fully implemented yet)
|
108
84
|
// ToDo: add specific implementions to all children
|
@@ -110,6 +86,20 @@ namespace Sass {
|
|
110
86
|
void update_pstate(const ParserState& pstate);
|
111
87
|
Offset off() { return pstate(); }
|
112
88
|
Position pos() { return pstate(); }
|
89
|
+
|
90
|
+
// Some obects are not meant to be compared
|
91
|
+
// ToDo: maybe fallback to pointer comparison?
|
92
|
+
virtual bool operator== (const AST_Node& rhs) const {
|
93
|
+
throw std::runtime_error("operator== not implemented");
|
94
|
+
}
|
95
|
+
|
96
|
+
// We can give some reasonable implementations by using
|
97
|
+
// inverst operators on the specialized implementations
|
98
|
+
virtual bool operator!= (const AST_Node& rhs) const {
|
99
|
+
// Unequal if not equal
|
100
|
+
return !(*this == rhs);
|
101
|
+
}
|
102
|
+
|
113
103
|
ATTACH_ABSTRACT_AST_OPERATIONS(AST_Node);
|
114
104
|
ATTACH_ABSTRACT_CRTP_PERFORM_METHODS()
|
115
105
|
};
|
@@ -228,37 +218,112 @@ namespace Sass {
|
|
228
218
|
public:
|
229
219
|
Vectorized(size_t s = 0) : hash_(0)
|
230
220
|
{ elements_.reserve(s); }
|
221
|
+
Vectorized(std::vector<T> vec) :
|
222
|
+
elements_(std::move(vec)),
|
223
|
+
hash_(0)
|
224
|
+
{}
|
231
225
|
virtual ~Vectorized() = 0;
|
232
226
|
size_t length() const { return elements_.size(); }
|
233
227
|
bool empty() const { return elements_.empty(); }
|
234
228
|
void clear() { return elements_.clear(); }
|
235
|
-
T last()
|
236
|
-
T first()
|
229
|
+
T& last() { return elements_.back(); }
|
230
|
+
T& first() { return elements_.front(); }
|
231
|
+
const T& last() const { return elements_.back(); }
|
232
|
+
const T& first() const { return elements_.front(); }
|
233
|
+
|
234
|
+
bool operator== (const Vectorized<T>& rhs) const {
|
235
|
+
// Abort early if sizes do not match
|
236
|
+
if (length() != rhs.length()) return false;
|
237
|
+
// Otherwise test each node for object equalicy in order
|
238
|
+
return std::equal(begin(), end(), rhs.begin(), ObjEqualityFn<T>);
|
239
|
+
}
|
240
|
+
|
241
|
+
bool operator!= (const Vectorized<T>& rhs) const {
|
242
|
+
return !(*this == rhs);
|
243
|
+
}
|
244
|
+
|
237
245
|
T& operator[](size_t i) { return elements_[i]; }
|
238
246
|
virtual const T& at(size_t i) const { return elements_.at(i); }
|
239
247
|
virtual T& at(size_t i) { return elements_.at(i); }
|
240
248
|
const T& get(size_t i) const { return elements_[i]; }
|
241
249
|
const T& operator[](size_t i) const { return elements_[i]; }
|
242
|
-
|
250
|
+
|
251
|
+
// Implicitly get the std::vector from our object
|
252
|
+
// Makes the Vector directly assignable to std::vector
|
253
|
+
// You are responsible to make a copy if needed
|
254
|
+
// Note: since this returns the real object, we can't
|
255
|
+
// Note: guarantee that the hash will not get out of sync
|
256
|
+
operator std::vector<T>&() { return elements_; }
|
257
|
+
operator const std::vector<T>&() const { return elements_; }
|
258
|
+
|
259
|
+
// Explicitly request all elements as a real std::vector
|
260
|
+
// You are responsible to make a copy if needed
|
261
|
+
// Note: since this returns the real object, we can't
|
262
|
+
// Note: guarantee that the hash will not get out of sync
|
263
|
+
std::vector<T>& elements() { return elements_; }
|
264
|
+
const std::vector<T>& elements() const { return elements_; }
|
265
|
+
|
266
|
+
// Insert all items from compatible vector
|
267
|
+
void concat(const std::vector<T>& v)
|
268
|
+
{
|
269
|
+
if (!v.empty()) reset_hash();
|
270
|
+
elements().insert(end(), v.begin(), v.end());
|
271
|
+
}
|
272
|
+
|
273
|
+
// Syntatic sugar for pointers
|
274
|
+
void concat(const Vectorized<T>* v)
|
243
275
|
{
|
244
|
-
if (
|
245
|
-
|
246
|
-
elements_.push_back(element);
|
247
|
-
adjust_after_pushing(element);
|
276
|
+
if (v != nullptr) {
|
277
|
+
return concat(*v);
|
248
278
|
}
|
249
279
|
}
|
250
|
-
|
280
|
+
|
281
|
+
// Insert one item on the front
|
282
|
+
void unshift(T element)
|
251
283
|
{
|
252
|
-
|
284
|
+
reset_hash();
|
285
|
+
elements_.insert(begin(), element);
|
253
286
|
}
|
254
|
-
|
287
|
+
|
288
|
+
// Remove and return item on the front
|
289
|
+
// ToDo: handle empty vectors
|
290
|
+
T shift() {
|
291
|
+
reset_hash();
|
292
|
+
T first = get(0);
|
293
|
+
elements_.erase(begin());
|
294
|
+
return first;
|
295
|
+
}
|
296
|
+
|
297
|
+
// Insert one item on the back
|
298
|
+
// ToDo: rename this to push
|
299
|
+
void append(T element)
|
255
300
|
{
|
256
|
-
|
257
|
-
|
301
|
+
reset_hash();
|
302
|
+
elements_.insert(end(), element);
|
303
|
+
// ToDo: Mostly used by parameters and arguments
|
304
|
+
// ToDo: Find a more elegant way to support this
|
305
|
+
adjust_after_pushing(element);
|
306
|
+
}
|
307
|
+
|
308
|
+
// Check if an item already exists
|
309
|
+
// Uses underlying object `operator==`
|
310
|
+
// E.g. compares the actual objects
|
311
|
+
bool contains(const T& el) const {
|
312
|
+
for (const T& rhs : elements_) {
|
313
|
+
// Test the underlying objects for equality
|
314
|
+
// A std::find checks for pointer equality
|
315
|
+
if (ObjEqualityFn(el, rhs)) {
|
316
|
+
return true;
|
317
|
+
}
|
318
|
+
}
|
319
|
+
return false;
|
320
|
+
}
|
321
|
+
|
322
|
+
// This might be better implemented as `operator=`?
|
323
|
+
void elements(std::vector<T> e) {
|
324
|
+
reset_hash();
|
325
|
+
elements_ = std::move(e);
|
258
326
|
}
|
259
|
-
std::vector<T>& elements() { return elements_; }
|
260
|
-
const std::vector<T>& elements() const { return elements_; }
|
261
|
-
std::vector<T>& elements(std::vector<T>& e) { elements_ = e; return elements_; }
|
262
327
|
|
263
328
|
virtual size_t hash() const
|
264
329
|
{
|
@@ -280,8 +345,8 @@ namespace Sass {
|
|
280
345
|
typename std::vector<T>::iterator begin() { return elements_.begin(); }
|
281
346
|
typename std::vector<T>::const_iterator end() const { return elements_.end(); }
|
282
347
|
typename std::vector<T>::const_iterator begin() const { return elements_.begin(); }
|
283
|
-
typename std::vector<T>::iterator erase(typename std::vector<T>::iterator el) { return elements_.erase(el); }
|
284
|
-
typename std::vector<T>::const_iterator erase(typename std::vector<T>::const_iterator el) { return elements_.erase(el); }
|
348
|
+
typename std::vector<T>::iterator erase(typename std::vector<T>::iterator el) { reset_hash(); return elements_.erase(el); }
|
349
|
+
typename std::vector<T>::const_iterator erase(typename std::vector<T>::const_iterator el) { reset_hash(); return elements_.erase(el); }
|
285
350
|
|
286
351
|
};
|
287
352
|
template <typename T>
|
@@ -291,36 +356,61 @@ namespace Sass {
|
|
291
356
|
// Mixin class for AST nodes that should behave like a hash table. Uses an
|
292
357
|
// extra <std::vector> internally to maintain insertion order for interation.
|
293
358
|
/////////////////////////////////////////////////////////////////////////////
|
359
|
+
template <typename K, typename T, typename U>
|
294
360
|
class Hashed {
|
295
361
|
private:
|
296
|
-
|
297
|
-
|
362
|
+
std::unordered_map<
|
363
|
+
K, T, ObjHash, ObjEquality
|
364
|
+
> elements_;
|
365
|
+
|
366
|
+
std::vector<K> _keys;
|
367
|
+
std::vector<T> _values;
|
298
368
|
protected:
|
299
369
|
mutable size_t hash_;
|
300
|
-
|
370
|
+
K duplicate_key_;
|
301
371
|
void reset_hash() { hash_ = 0; }
|
302
372
|
void reset_duplicate_key() { duplicate_key_ = {}; }
|
303
|
-
virtual void adjust_after_pushing(std::pair<
|
373
|
+
virtual void adjust_after_pushing(std::pair<K, T> p) { }
|
304
374
|
public:
|
305
375
|
Hashed(size_t s = 0)
|
306
|
-
: elements_(
|
307
|
-
|
376
|
+
: elements_(),
|
377
|
+
_keys(),
|
378
|
+
_values(),
|
308
379
|
hash_(0), duplicate_key_({})
|
309
|
-
{
|
380
|
+
{
|
381
|
+
_keys.reserve(s);
|
382
|
+
_values.reserve(s);
|
383
|
+
elements_.reserve(s);
|
384
|
+
}
|
310
385
|
virtual ~Hashed();
|
311
|
-
size_t length() const { return
|
312
|
-
bool empty() const { return
|
313
|
-
bool has(
|
314
|
-
|
386
|
+
size_t length() const { return _keys.size(); }
|
387
|
+
bool empty() const { return _keys.empty(); }
|
388
|
+
bool has(K k) const {
|
389
|
+
return elements_.find(k) != elements_.end();
|
390
|
+
}
|
391
|
+
T at(K k) const {
|
392
|
+
if (elements_.count(k))
|
393
|
+
{
|
394
|
+
return elements_.at(k);
|
395
|
+
}
|
396
|
+
else { return {}; }
|
397
|
+
}
|
315
398
|
bool has_duplicate_key() const { return duplicate_key_ != nullptr; }
|
316
|
-
|
317
|
-
const
|
318
|
-
|
399
|
+
K get_duplicate_key() const { return duplicate_key_; }
|
400
|
+
const std::unordered_map<
|
401
|
+
K, T, ObjHash, ObjEquality
|
402
|
+
>& elements() { return elements_; }
|
403
|
+
Hashed& operator<<(std::pair<K, T> p)
|
319
404
|
{
|
320
405
|
reset_hash();
|
321
406
|
|
322
|
-
if (!has(p.first))
|
323
|
-
|
407
|
+
if (!has(p.first)) {
|
408
|
+
_keys.push_back(p.first);
|
409
|
+
_values.push_back(p.second);
|
410
|
+
}
|
411
|
+
else if (!duplicate_key_) {
|
412
|
+
duplicate_key_ = p.first;
|
413
|
+
}
|
324
414
|
|
325
415
|
elements_[p.first] = p.second;
|
326
416
|
|
@@ -331,7 +421,8 @@ namespace Sass {
|
|
331
421
|
{
|
332
422
|
if (length() == 0) {
|
333
423
|
this->elements_ = h->elements_;
|
334
|
-
this->
|
424
|
+
this->_values = h->_values;
|
425
|
+
this->_keys = h->_keys;
|
335
426
|
return *this;
|
336
427
|
}
|
337
428
|
|
@@ -342,8 +433,12 @@ namespace Sass {
|
|
342
433
|
reset_duplicate_key();
|
343
434
|
return *this;
|
344
435
|
}
|
345
|
-
const
|
346
|
-
|
436
|
+
const std::unordered_map<
|
437
|
+
K, T, ObjHash, ObjEquality
|
438
|
+
>& pairs() const { return elements_; }
|
439
|
+
|
440
|
+
const std::vector<K>& keys() const { return _keys; }
|
441
|
+
const std::vector<T>& values() const { return _values; }
|
347
442
|
|
348
443
|
// std::unordered_map<Expression_Obj, Expression_Obj>::iterator end() { return elements_.end(); }
|
349
444
|
// std::unordered_map<Expression_Obj, Expression_Obj>::iterator begin() { return elements_.begin(); }
|
@@ -351,8 +446,8 @@ namespace Sass {
|
|
351
446
|
// std::unordered_map<Expression_Obj, Expression_Obj>::const_iterator begin() const { return elements_.begin(); }
|
352
447
|
|
353
448
|
};
|
354
|
-
|
355
|
-
|
449
|
+
template <typename K, typename T, typename U>
|
450
|
+
inline Hashed<K, T, U>::~Hashed() { }
|
356
451
|
|
357
452
|
/////////////////////////////////////////////////////////////////////////
|
358
453
|
// Abstract base class for statements. This side of the AST hierarchy
|
@@ -411,6 +506,7 @@ namespace Sass {
|
|
411
506
|
void adjust_after_pushing(Statement_Obj s) override {}
|
412
507
|
public:
|
413
508
|
Block(ParserState pstate, size_t s = 0, bool r = false);
|
509
|
+
bool isInvisible() const;
|
414
510
|
bool has_content() override;
|
415
511
|
ATTACH_AST_OPERATIONS(Block)
|
416
512
|
ATTACH_CRTP_PERFORM_METHODS()
|
@@ -434,10 +530,11 @@ namespace Sass {
|
|
434
530
|
// of style declarations.
|
435
531
|
/////////////////////////////////////////////////////////////////////////////
|
436
532
|
class Ruleset final : public Has_Block {
|
437
|
-
ADD_PROPERTY(
|
533
|
+
ADD_PROPERTY(SelectorListObj, selector)
|
534
|
+
ADD_PROPERTY(Selector_Schema_Obj, schema)
|
438
535
|
ADD_PROPERTY(bool, is_root);
|
439
536
|
public:
|
440
|
-
Ruleset(ParserState pstate,
|
537
|
+
Ruleset(ParserState pstate, SelectorListObj s = {}, Block_Obj b = {});
|
441
538
|
bool is_invisible() const override;
|
442
539
|
ATTACH_AST_OPERATIONS(Ruleset)
|
443
540
|
ATTACH_CRTP_PERFORM_METHODS()
|
@@ -468,29 +565,16 @@ namespace Sass {
|
|
468
565
|
ATTACH_CRTP_PERFORM_METHODS()
|
469
566
|
};
|
470
567
|
|
471
|
-
/////////////////
|
472
|
-
// Media queries.
|
473
|
-
/////////////////
|
474
|
-
class Media_Block final : public Has_Block {
|
475
|
-
ADD_PROPERTY(List_Obj, media_queries)
|
476
|
-
public:
|
477
|
-
Media_Block(ParserState pstate, List_Obj mqs, Block_Obj b);
|
478
|
-
bool bubbles() override;
|
479
|
-
bool is_invisible() const override;
|
480
|
-
ATTACH_AST_OPERATIONS(Media_Block)
|
481
|
-
ATTACH_CRTP_PERFORM_METHODS()
|
482
|
-
};
|
483
|
-
|
484
568
|
///////////////////////////////////////////////////////////////////////
|
485
569
|
// At-rules -- arbitrary directives beginning with "@" that may have an
|
486
570
|
// optional statement block.
|
487
571
|
///////////////////////////////////////////////////////////////////////
|
488
572
|
class Directive final : public Has_Block {
|
489
573
|
ADD_CONSTREF(std::string, keyword)
|
490
|
-
ADD_PROPERTY(
|
574
|
+
ADD_PROPERTY(SelectorListObj, selector)
|
491
575
|
ADD_PROPERTY(Expression_Obj, value)
|
492
576
|
public:
|
493
|
-
Directive(ParserState pstate, std::string kwd,
|
577
|
+
Directive(ParserState pstate, std::string kwd, SelectorListObj sel = {}, Block_Obj b = {}, Expression_Obj val = {});
|
494
578
|
bool bubbles() override;
|
495
579
|
bool is_media();
|
496
580
|
bool is_keyframes();
|
@@ -504,7 +588,7 @@ namespace Sass {
|
|
504
588
|
class Keyframe_Rule final : public Has_Block {
|
505
589
|
// according to css spec, this should be <keyframes-name>
|
506
590
|
// <keyframes-name> = <custom-ident> | <string>
|
507
|
-
ADD_PROPERTY(
|
591
|
+
ADD_PROPERTY(SelectorListObj, name)
|
508
592
|
public:
|
509
593
|
Keyframe_Rule(ParserState pstate, Block_Obj b);
|
510
594
|
ATTACH_AST_OPERATIONS(Keyframe_Rule)
|
@@ -677,17 +761,6 @@ namespace Sass {
|
|
677
761
|
ATTACH_CRTP_PERFORM_METHODS()
|
678
762
|
};
|
679
763
|
|
680
|
-
////////////////////////////////
|
681
|
-
// The Sass `@extend` directive.
|
682
|
-
////////////////////////////////
|
683
|
-
class Extension final : public Statement {
|
684
|
-
ADD_PROPERTY(Selector_List_Obj, selector)
|
685
|
-
public:
|
686
|
-
Extension(ParserState pstate, Selector_List_Obj s);
|
687
|
-
ATTACH_AST_OPERATIONS(Extension)
|
688
|
-
ATTACH_CRTP_PERFORM_METHODS()
|
689
|
-
};
|
690
|
-
|
691
764
|
/////////////////////////////////////////////////////////////////////////////
|
692
765
|
// Definitions for both mixins and functions. The two cases are distinguished
|
693
766
|
// by a type tag.
|
@@ -806,9 +879,96 @@ namespace Sass {
|
|
806
879
|
ATTACH_CRTP_PERFORM_METHODS()
|
807
880
|
};
|
808
881
|
|
809
|
-
|
810
|
-
// Media
|
811
|
-
|
882
|
+
|
883
|
+
// A Media Ruleset before it has been evaluated
|
884
|
+
// Could be already final or an interpolation
|
885
|
+
class MediaRule final : public Has_Block {
|
886
|
+
ADD_PROPERTY(List_Obj, schema)
|
887
|
+
public:
|
888
|
+
MediaRule(ParserState pstate, Block_Obj block = {});
|
889
|
+
|
890
|
+
bool bubbles() override { return true; };
|
891
|
+
bool is_invisible() const override { return false; };
|
892
|
+
ATTACH_AST_OPERATIONS(MediaRule)
|
893
|
+
ATTACH_CRTP_PERFORM_METHODS()
|
894
|
+
};
|
895
|
+
|
896
|
+
// A Media Ruleset after it has been evaluated
|
897
|
+
// Representing the static or resulting css
|
898
|
+
class CssMediaRule final : public Has_Block,
|
899
|
+
public Vectorized<CssMediaQuery_Obj> {
|
900
|
+
public:
|
901
|
+
CssMediaRule(ParserState pstate, Block_Obj b);
|
902
|
+
bool bubbles() override { return true; };
|
903
|
+
bool isInvisible() const { return empty(); }
|
904
|
+
bool is_invisible() const override { return false; };
|
905
|
+
|
906
|
+
public:
|
907
|
+
// Hash and equality implemtation from vector
|
908
|
+
size_t hash() const override { return Vectorized::hash(); }
|
909
|
+
// Check if two instances are considered equal
|
910
|
+
bool operator== (const CssMediaRule& rhs) const {
|
911
|
+
return Vectorized::operator== (rhs);
|
912
|
+
}
|
913
|
+
bool operator!=(const CssMediaRule& rhs) const {
|
914
|
+
// Invert from equality
|
915
|
+
return !(*this == rhs);
|
916
|
+
}
|
917
|
+
|
918
|
+
ATTACH_AST_OPERATIONS(CssMediaRule)
|
919
|
+
ATTACH_CRTP_PERFORM_METHODS()
|
920
|
+
};
|
921
|
+
|
922
|
+
// Media Queries after they have been evaluated
|
923
|
+
// Representing the static or resulting css
|
924
|
+
class CssMediaQuery final : public AST_Node {
|
925
|
+
|
926
|
+
// The modifier, probably either "not" or "only".
|
927
|
+
// This may be `null` if no modifier is in use.
|
928
|
+
ADD_PROPERTY(std::string, modifier);
|
929
|
+
|
930
|
+
// The media type, for example "screen" or "print".
|
931
|
+
// This may be `null`. If so, [features] will not be empty.
|
932
|
+
ADD_PROPERTY(std::string, type);
|
933
|
+
|
934
|
+
// Feature queries, including parentheses.
|
935
|
+
ADD_PROPERTY(std::vector<std::string>, features);
|
936
|
+
|
937
|
+
public:
|
938
|
+
CssMediaQuery(ParserState pstate);
|
939
|
+
|
940
|
+
// Check if two instances are considered equal
|
941
|
+
bool operator== (const CssMediaQuery& rhs) const;
|
942
|
+
bool operator!=(const CssMediaQuery& rhs) const {
|
943
|
+
// Invert from equality
|
944
|
+
return !(*this == rhs);
|
945
|
+
}
|
946
|
+
|
947
|
+
// Returns true if this query is empty
|
948
|
+
// Meaning it has no type and features
|
949
|
+
bool empty() const {
|
950
|
+
return type_.empty()
|
951
|
+
&& modifier_.empty()
|
952
|
+
&& features_.empty();
|
953
|
+
}
|
954
|
+
|
955
|
+
// Whether this media query matches all media types.
|
956
|
+
bool matchesAllTypes() const {
|
957
|
+
return type_.empty() || Util::equalsLiteral("all", type_);
|
958
|
+
}
|
959
|
+
|
960
|
+
// Merges this with [other] and adds a query that matches the intersection
|
961
|
+
// of both inputs to [result]. Returns false if the result is unrepresentable
|
962
|
+
CssMediaQuery_Obj merge(CssMediaQuery_Obj& other);
|
963
|
+
|
964
|
+
ATTACH_AST_OPERATIONS(CssMediaQuery)
|
965
|
+
ATTACH_CRTP_PERFORM_METHODS()
|
966
|
+
};
|
967
|
+
|
968
|
+
////////////////////////////////////////////////////
|
969
|
+
// Media queries (replaced by MediaRule at al).
|
970
|
+
// ToDo: only used for interpolation case
|
971
|
+
////////////////////////////////////////////////////
|
812
972
|
class Media_Query final : public Expression,
|
813
973
|
public Vectorized<Media_Query_Expression_Obj> {
|
814
974
|
ADD_PROPERTY(String_Obj, media_type)
|
@@ -822,6 +982,7 @@ namespace Sass {
|
|
822
982
|
|
823
983
|
////////////////////////////////////////////////////
|
824
984
|
// Media expressions (for use inside media queries).
|
985
|
+
// ToDo: only used for interpolation case
|
825
986
|
////////////////////////////////////////////////////
|
826
987
|
class Media_Query_Expression final : public Expression {
|
827
988
|
ADD_PROPERTY(Expression_Obj, feature)
|