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
@@ -0,0 +1,280 @@
|
|
1
|
+
#include "sass.hpp"
|
2
|
+
#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
|
+
|
18
|
+
#include "ast_selectors.hpp"
|
19
|
+
|
20
|
+
// #define DEBUG_UNIFY
|
21
|
+
|
22
|
+
namespace Sass {
|
23
|
+
|
24
|
+
Compound_Selector* Compound_Selector::unify_with(Compound_Selector* rhs)
|
25
|
+
{
|
26
|
+
#ifdef DEBUG_UNIFY
|
27
|
+
const std::string debug_call = "unify(Compound[" + this->to_string() + "], Compound[" + rhs->to_string() + "])";
|
28
|
+
std::cerr << debug_call << std::endl;
|
29
|
+
#endif
|
30
|
+
|
31
|
+
if (empty()) return rhs;
|
32
|
+
Compound_Selector_Obj unified = SASS_MEMORY_COPY(rhs);
|
33
|
+
for (const Simple_Selector_Obj& sel : elements()) {
|
34
|
+
unified = sel->unify_with(unified);
|
35
|
+
if (unified.isNull()) break;
|
36
|
+
}
|
37
|
+
|
38
|
+
#ifdef DEBUG_UNIFY
|
39
|
+
std::cerr << "> " << debug_call << " = Compound[" << unified->to_string() << "]" << std::endl;
|
40
|
+
#endif
|
41
|
+
return unified.detach();
|
42
|
+
}
|
43
|
+
|
44
|
+
Compound_Selector* Simple_Selector::unify_with(Compound_Selector* rhs)
|
45
|
+
{
|
46
|
+
#ifdef DEBUG_UNIFY
|
47
|
+
const std::string debug_call = "unify(Simple[" + this->to_string() + "], Compound[" + rhs->to_string() + "])";
|
48
|
+
std::cerr << debug_call << std::endl;
|
49
|
+
#endif
|
50
|
+
|
51
|
+
if (rhs->length() == 1) {
|
52
|
+
if (rhs->at(0)->is_universal()) {
|
53
|
+
Compound_Selector* this_compound = SASS_MEMORY_NEW(Compound_Selector, pstate(), 1);
|
54
|
+
this_compound->append(SASS_MEMORY_COPY(this));
|
55
|
+
Compound_Selector* unified = rhs->at(0)->unify_with(this_compound);
|
56
|
+
if (unified == nullptr || unified != this_compound) delete this_compound;
|
57
|
+
|
58
|
+
#ifdef DEBUG_UNIFY
|
59
|
+
std::cerr << "> " << debug_call << " = " << "Compound[" << unified->to_string() << "]" << std::endl;
|
60
|
+
#endif
|
61
|
+
return unified;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
for (const Simple_Selector_Obj& sel : rhs->elements()) {
|
65
|
+
if (*this == *sel) {
|
66
|
+
#ifdef DEBUG_UNIFY
|
67
|
+
std::cerr << "> " << debug_call << " = " << "Compound[" << rhs->to_string() << "]" << std::endl;
|
68
|
+
#endif
|
69
|
+
return rhs;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
const int lhs_order = this->unification_order();
|
73
|
+
size_t i = rhs->length();
|
74
|
+
while (i > 0 && lhs_order < rhs->at(i - 1)->unification_order()) --i;
|
75
|
+
rhs->insert(rhs->begin() + i, this);
|
76
|
+
#ifdef DEBUG_UNIFY
|
77
|
+
std::cerr << "> " << debug_call << " = " << "Compound[" << rhs->to_string() << "]" << std::endl;
|
78
|
+
#endif
|
79
|
+
return rhs;
|
80
|
+
}
|
81
|
+
|
82
|
+
Simple_Selector* Type_Selector::unify_with(Simple_Selector* rhs)
|
83
|
+
{
|
84
|
+
#ifdef DEBUG_UNIFY
|
85
|
+
const std::string debug_call = "unify(Type[" + this->to_string() + "], Simple[" + rhs->to_string() + "])";
|
86
|
+
std::cerr << debug_call << std::endl;
|
87
|
+
#endif
|
88
|
+
|
89
|
+
bool rhs_ns = false;
|
90
|
+
if (!(is_ns_eq(*rhs) || rhs->is_universal_ns())) {
|
91
|
+
if (!is_universal_ns()) {
|
92
|
+
#ifdef DEBUG_UNIFY
|
93
|
+
std::cerr << "> " << debug_call << " = nullptr" << std::endl;
|
94
|
+
#endif
|
95
|
+
return nullptr;
|
96
|
+
}
|
97
|
+
rhs_ns = true;
|
98
|
+
}
|
99
|
+
bool rhs_name = false;
|
100
|
+
if (!(name_ == rhs->name() || rhs->is_universal())) {
|
101
|
+
if (!(is_universal())) {
|
102
|
+
#ifdef DEBUG_UNIFY
|
103
|
+
std::cerr << "> " << debug_call << " = nullptr" << std::endl;
|
104
|
+
#endif
|
105
|
+
return nullptr;
|
106
|
+
}
|
107
|
+
rhs_name = true;
|
108
|
+
}
|
109
|
+
if (rhs_ns) {
|
110
|
+
ns(rhs->ns());
|
111
|
+
has_ns(rhs->has_ns());
|
112
|
+
}
|
113
|
+
if (rhs_name) name(rhs->name());
|
114
|
+
#ifdef DEBUG_UNIFY
|
115
|
+
std::cerr << "> " << debug_call << " = Simple[" << this->to_string() << "]" << std::endl;
|
116
|
+
#endif
|
117
|
+
return this;
|
118
|
+
}
|
119
|
+
|
120
|
+
Compound_Selector* Type_Selector::unify_with(Compound_Selector* rhs)
|
121
|
+
{
|
122
|
+
#ifdef DEBUG_UNIFY
|
123
|
+
const std::string debug_call = "unify(Type[" + this->to_string() + "], Compound[" + rhs->to_string() + "])";
|
124
|
+
std::cerr << debug_call << std::endl;
|
125
|
+
#endif
|
126
|
+
|
127
|
+
if (rhs->empty()) {
|
128
|
+
rhs->append(this);
|
129
|
+
#ifdef DEBUG_UNIFY
|
130
|
+
std::cerr << "> " << debug_call << " = Compound[" << rhs->to_string() << "]" << std::endl;
|
131
|
+
#endif
|
132
|
+
return rhs;
|
133
|
+
}
|
134
|
+
Type_Selector* rhs_0 = Cast<Type_Selector>(rhs->at(0));
|
135
|
+
if (rhs_0 != nullptr) {
|
136
|
+
Simple_Selector* unified = unify_with(rhs_0);
|
137
|
+
if (unified == nullptr) {
|
138
|
+
#ifdef DEBUG_UNIFY
|
139
|
+
std::cerr << "> " << debug_call << " = nullptr" << std::endl;
|
140
|
+
#endif
|
141
|
+
return nullptr;
|
142
|
+
}
|
143
|
+
rhs->elements()[0] = unified;
|
144
|
+
} else if (!is_universal() || (has_ns_ && ns_ != "*")) {
|
145
|
+
rhs->insert(rhs->begin(), this);
|
146
|
+
}
|
147
|
+
#ifdef DEBUG_UNIFY
|
148
|
+
std::cerr << "> " << debug_call << " = Compound[" << rhs->to_string() << "]" << std::endl;
|
149
|
+
#endif
|
150
|
+
return rhs;
|
151
|
+
}
|
152
|
+
|
153
|
+
Compound_Selector* Class_Selector::unify_with(Compound_Selector* rhs)
|
154
|
+
{
|
155
|
+
rhs->has_line_break(has_line_break());
|
156
|
+
return Simple_Selector::unify_with(rhs);
|
157
|
+
}
|
158
|
+
|
159
|
+
Compound_Selector* Id_Selector::unify_with(Compound_Selector* rhs)
|
160
|
+
{
|
161
|
+
for (const Simple_Selector_Obj& sel : rhs->elements()) {
|
162
|
+
if (Id_Selector* id_sel = Cast<Id_Selector>(sel)) {
|
163
|
+
if (id_sel->name() != name()) return nullptr;
|
164
|
+
}
|
165
|
+
}
|
166
|
+
rhs->has_line_break(has_line_break());
|
167
|
+
return Simple_Selector::unify_with(rhs);
|
168
|
+
}
|
169
|
+
|
170
|
+
Compound_Selector* Pseudo_Selector::unify_with(Compound_Selector* rhs)
|
171
|
+
{
|
172
|
+
if (is_pseudo_element()) {
|
173
|
+
for (const Simple_Selector_Obj& sel : rhs->elements()) {
|
174
|
+
if (Pseudo_Selector* pseudo_sel = Cast<Pseudo_Selector>(sel)) {
|
175
|
+
if (pseudo_sel->is_pseudo_element() && pseudo_sel->name() != name()) return nullptr;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
}
|
179
|
+
return Simple_Selector::unify_with(rhs);
|
180
|
+
}
|
181
|
+
|
182
|
+
Selector_List* Complex_Selector::unify_with(Complex_Selector* rhs)
|
183
|
+
{
|
184
|
+
#ifdef DEBUG_UNIFY
|
185
|
+
const std::string debug_call = "unify(Complex[" + this->to_string() + "], Complex[" + rhs->to_string() + "])";
|
186
|
+
std::cerr << debug_call << std::endl;
|
187
|
+
#endif
|
188
|
+
|
189
|
+
// get last tails (on the right side)
|
190
|
+
Complex_Selector* l_last = this->mutable_last();
|
191
|
+
Complex_Selector* r_last = rhs->mutable_last();
|
192
|
+
|
193
|
+
// check valid pointers (assertion)
|
194
|
+
SASS_ASSERT(l_last, "lhs is null");
|
195
|
+
SASS_ASSERT(r_last, "rhs is null");
|
196
|
+
|
197
|
+
// Not sure about this check, but closest way I could check
|
198
|
+
// was to see if this is a ruby 'SimpleSequence' equivalent.
|
199
|
+
// It seems to do the job correctly as some specs react to this
|
200
|
+
if (l_last->combinator() != Combinator::ANCESTOR_OF) return nullptr;
|
201
|
+
if (r_last->combinator() != Combinator::ANCESTOR_OF) return nullptr;
|
202
|
+
|
203
|
+
// get the headers for the last tails
|
204
|
+
Compound_Selector* l_last_head = l_last->head();
|
205
|
+
Compound_Selector* r_last_head = r_last->head();
|
206
|
+
|
207
|
+
// check valid head pointers (assertion)
|
208
|
+
SASS_ASSERT(l_last_head, "lhs head is null");
|
209
|
+
SASS_ASSERT(r_last_head, "rhs head is null");
|
210
|
+
|
211
|
+
// get the unification of the last compound selectors
|
212
|
+
Compound_Selector_Obj unified = r_last_head->unify_with(l_last_head);
|
213
|
+
|
214
|
+
// abort if we could not unify heads
|
215
|
+
if (unified == nullptr) return nullptr;
|
216
|
+
|
217
|
+
// move the head
|
218
|
+
if (l_last_head->is_universal()) l_last->head({});
|
219
|
+
r_last->head(unified);
|
220
|
+
|
221
|
+
#ifdef DEBUG_UNIFY
|
222
|
+
std::cerr << "> " << debug_call << " before weave: lhs=" << this->to_string() << " rhs=" << rhs->to_string() << std::endl;
|
223
|
+
#endif
|
224
|
+
|
225
|
+
// create nodes from both selectors
|
226
|
+
Node lhsNode = complexSelectorToNode(this);
|
227
|
+
Node rhsNode = complexSelectorToNode(rhs);
|
228
|
+
|
229
|
+
// Complex_Selector_Obj fake = unified->to_complex();
|
230
|
+
// Node unified_node = complexSelectorToNode(fake);
|
231
|
+
// // add to permutate the list?
|
232
|
+
// rhsNode.plus(unified_node);
|
233
|
+
|
234
|
+
// do some magic we inherit from node and extend
|
235
|
+
Node node = subweave(lhsNode, rhsNode);
|
236
|
+
Selector_List_Obj result = SASS_MEMORY_NEW(Selector_List, pstate(), node.collection()->size());
|
237
|
+
for (auto &item : *node.collection()) {
|
238
|
+
result->append(nodeToComplexSelector(Node::naiveTrim(item)));
|
239
|
+
}
|
240
|
+
|
241
|
+
#ifdef DEBUG_UNIFY
|
242
|
+
std::cerr << "> " << debug_call << " = " << result->to_string() << std::endl;
|
243
|
+
#endif
|
244
|
+
|
245
|
+
// only return if list has some entries
|
246
|
+
return result->length() ? result.detach() : nullptr;
|
247
|
+
}
|
248
|
+
|
249
|
+
Selector_List* Selector_List::unify_with(Selector_List* rhs) {
|
250
|
+
#ifdef DEBUG_UNIFY
|
251
|
+
const std::string debug_call = "unify(List[" + this->to_string() + "], List[" + rhs->to_string() + "])";
|
252
|
+
std::cerr << debug_call << std::endl;
|
253
|
+
#endif
|
254
|
+
|
255
|
+
std::vector<Complex_Selector_Obj> result;
|
256
|
+
// Unify all of children with RHS's children, storing the results in `unified_complex_selectors`
|
257
|
+
for (Complex_Selector_Obj& seq1 : elements()) {
|
258
|
+
for (Complex_Selector_Obj& seq2 : rhs->elements()) {
|
259
|
+
Complex_Selector_Obj seq1_copy = SASS_MEMORY_CLONE(seq1);
|
260
|
+
Complex_Selector_Obj seq2_copy = SASS_MEMORY_CLONE(seq2);
|
261
|
+
Selector_List_Obj unified = seq1_copy->unify_with(seq2_copy);
|
262
|
+
if (unified) {
|
263
|
+
result.reserve(result.size() + unified->length());
|
264
|
+
std::copy(unified->begin(), unified->end(), std::back_inserter(result));
|
265
|
+
}
|
266
|
+
}
|
267
|
+
}
|
268
|
+
|
269
|
+
// Creates the final Selector_List by combining all the complex selectors
|
270
|
+
Selector_List* final_result = SASS_MEMORY_NEW(Selector_List, pstate(), result.size());
|
271
|
+
for (Complex_Selector_Obj& sel : result) {
|
272
|
+
final_result->append(sel);
|
273
|
+
}
|
274
|
+
#ifdef DEBUG_UNIFY
|
275
|
+
std::cerr << "> " << debug_call << " = " << final_result->to_string() << std::endl;
|
276
|
+
#endif
|
277
|
+
return final_result;
|
278
|
+
}
|
279
|
+
|
280
|
+
}
|
@@ -0,0 +1,1475 @@
|
|
1
|
+
#include "sass.hpp"
|
2
|
+
#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 "ast_selectors.hpp"
|
11
|
+
#include <array>
|
12
|
+
#include <set>
|
13
|
+
#include <iomanip>
|
14
|
+
#include <iostream>
|
15
|
+
#include <algorithm>
|
16
|
+
#include <functional>
|
17
|
+
#include <cctype>
|
18
|
+
#include <locale>
|
19
|
+
|
20
|
+
namespace Sass {
|
21
|
+
|
22
|
+
/////////////////////////////////////////////////////////////////////////
|
23
|
+
/////////////////////////////////////////////////////////////////////////
|
24
|
+
|
25
|
+
Selector::Selector(ParserState pstate)
|
26
|
+
: Expression(pstate),
|
27
|
+
has_line_feed_(false),
|
28
|
+
has_line_break_(false),
|
29
|
+
is_optional_(false),
|
30
|
+
media_block_(0),
|
31
|
+
hash_(0)
|
32
|
+
{ concrete_type(SELECTOR); }
|
33
|
+
|
34
|
+
Selector::Selector(const Selector* ptr)
|
35
|
+
: Expression(ptr),
|
36
|
+
has_line_feed_(ptr->has_line_feed_),
|
37
|
+
has_line_break_(ptr->has_line_break_),
|
38
|
+
is_optional_(ptr->is_optional_),
|
39
|
+
media_block_(ptr->media_block_),
|
40
|
+
hash_(ptr->hash_)
|
41
|
+
{ concrete_type(SELECTOR); }
|
42
|
+
|
43
|
+
void Selector::set_media_block(Media_Block* mb)
|
44
|
+
{
|
45
|
+
media_block(mb);
|
46
|
+
}
|
47
|
+
|
48
|
+
bool Selector::has_parent_ref() const
|
49
|
+
{
|
50
|
+
return false;
|
51
|
+
}
|
52
|
+
|
53
|
+
bool Selector::has_real_parent_ref() const
|
54
|
+
{
|
55
|
+
return false;
|
56
|
+
}
|
57
|
+
|
58
|
+
/////////////////////////////////////////////////////////////////////////
|
59
|
+
/////////////////////////////////////////////////////////////////////////
|
60
|
+
|
61
|
+
Selector_Schema::Selector_Schema(ParserState pstate, String_Obj c)
|
62
|
+
: AST_Node(pstate),
|
63
|
+
contents_(c),
|
64
|
+
connect_parent_(true),
|
65
|
+
media_block_(NULL),
|
66
|
+
hash_(0)
|
67
|
+
{ }
|
68
|
+
Selector_Schema::Selector_Schema(const Selector_Schema* ptr)
|
69
|
+
: AST_Node(ptr),
|
70
|
+
contents_(ptr->contents_),
|
71
|
+
connect_parent_(ptr->connect_parent_),
|
72
|
+
media_block_(ptr->media_block_),
|
73
|
+
hash_(ptr->hash_)
|
74
|
+
{ }
|
75
|
+
|
76
|
+
unsigned long Selector_Schema::specificity() const
|
77
|
+
{
|
78
|
+
return 0;
|
79
|
+
}
|
80
|
+
|
81
|
+
size_t Selector_Schema::hash() const {
|
82
|
+
if (hash_ == 0) {
|
83
|
+
hash_combine(hash_, contents_->hash());
|
84
|
+
}
|
85
|
+
return hash_;
|
86
|
+
}
|
87
|
+
|
88
|
+
bool Selector_Schema::has_parent_ref() const
|
89
|
+
{
|
90
|
+
if (String_Schema_Obj schema = Cast<String_Schema>(contents())) {
|
91
|
+
if (schema->empty()) return false;
|
92
|
+
const auto& first = *schema->at(0);
|
93
|
+
return typeid(first) == typeid(Parent_Selector);
|
94
|
+
}
|
95
|
+
return false;
|
96
|
+
}
|
97
|
+
|
98
|
+
bool Selector_Schema::has_real_parent_ref() const
|
99
|
+
{
|
100
|
+
if (String_Schema_Obj schema = Cast<String_Schema>(contents())) {
|
101
|
+
if (schema->empty()) return false;
|
102
|
+
const auto& first = *schema->at(0);
|
103
|
+
return typeid(first) == typeid(Parent_Reference);
|
104
|
+
}
|
105
|
+
return false;
|
106
|
+
}
|
107
|
+
|
108
|
+
/////////////////////////////////////////////////////////////////////////
|
109
|
+
/////////////////////////////////////////////////////////////////////////
|
110
|
+
|
111
|
+
Simple_Selector::Simple_Selector(ParserState pstate, std::string n)
|
112
|
+
: Selector(pstate), ns_(""), name_(n), has_ns_(false)
|
113
|
+
{
|
114
|
+
size_t pos = n.find('|');
|
115
|
+
// found some namespace
|
116
|
+
if (pos != std::string::npos) {
|
117
|
+
has_ns_ = true;
|
118
|
+
ns_ = n.substr(0, pos);
|
119
|
+
name_ = n.substr(pos + 1);
|
120
|
+
}
|
121
|
+
}
|
122
|
+
Simple_Selector::Simple_Selector(const Simple_Selector* ptr)
|
123
|
+
: Selector(ptr),
|
124
|
+
ns_(ptr->ns_),
|
125
|
+
name_(ptr->name_),
|
126
|
+
has_ns_(ptr->has_ns_)
|
127
|
+
{ }
|
128
|
+
|
129
|
+
std::string Simple_Selector::ns_name() const
|
130
|
+
{
|
131
|
+
std::string name("");
|
132
|
+
if (has_ns_)
|
133
|
+
name += ns_ + "|";
|
134
|
+
return name + name_;
|
135
|
+
}
|
136
|
+
|
137
|
+
size_t Simple_Selector::hash() const
|
138
|
+
{
|
139
|
+
if (hash_ == 0) {
|
140
|
+
hash_combine(hash_, std::hash<int>()(SELECTOR));
|
141
|
+
hash_combine(hash_, std::hash<int>()(simple_type()));
|
142
|
+
if (!name_.empty()) hash_combine(hash_, std::hash<std::string>()(name()));
|
143
|
+
if (has_ns_) hash_combine(hash_, std::hash<std::string>()(ns()));
|
144
|
+
}
|
145
|
+
return hash_;
|
146
|
+
}
|
147
|
+
|
148
|
+
bool Simple_Selector::empty() const {
|
149
|
+
return ns().empty() && name().empty();
|
150
|
+
}
|
151
|
+
|
152
|
+
// namespace compare functions
|
153
|
+
bool Simple_Selector::is_ns_eq(const Simple_Selector& r) const
|
154
|
+
{
|
155
|
+
return has_ns_ == r.has_ns_ && ns_ == r.ns_;
|
156
|
+
}
|
157
|
+
|
158
|
+
// namespace query functions
|
159
|
+
bool Simple_Selector::is_universal_ns() const
|
160
|
+
{
|
161
|
+
return has_ns_ && ns_ == "*";
|
162
|
+
}
|
163
|
+
|
164
|
+
bool Simple_Selector::is_empty_ns() const
|
165
|
+
{
|
166
|
+
return !has_ns_ || ns_ == "";
|
167
|
+
}
|
168
|
+
|
169
|
+
bool Simple_Selector::has_empty_ns() const
|
170
|
+
{
|
171
|
+
return has_ns_ && ns_ == "";
|
172
|
+
}
|
173
|
+
|
174
|
+
bool Simple_Selector::has_qualified_ns() const
|
175
|
+
{
|
176
|
+
return has_ns_ && ns_ != "" && ns_ != "*";
|
177
|
+
}
|
178
|
+
|
179
|
+
// name query functions
|
180
|
+
bool Simple_Selector::is_universal() const
|
181
|
+
{
|
182
|
+
return name_ == "*";
|
183
|
+
}
|
184
|
+
|
185
|
+
bool Simple_Selector::has_placeholder()
|
186
|
+
{
|
187
|
+
return false;
|
188
|
+
}
|
189
|
+
|
190
|
+
bool Simple_Selector::has_parent_ref() const
|
191
|
+
{
|
192
|
+
return false;
|
193
|
+
};
|
194
|
+
|
195
|
+
bool Simple_Selector::has_real_parent_ref() const
|
196
|
+
{
|
197
|
+
return false;
|
198
|
+
};
|
199
|
+
|
200
|
+
bool Simple_Selector::is_pseudo_element() const
|
201
|
+
{
|
202
|
+
return false;
|
203
|
+
}
|
204
|
+
|
205
|
+
bool Simple_Selector::is_superselector_of(const Compound_Selector* sub) const
|
206
|
+
{
|
207
|
+
return false;
|
208
|
+
}
|
209
|
+
|
210
|
+
/////////////////////////////////////////////////////////////////////////
|
211
|
+
/////////////////////////////////////////////////////////////////////////
|
212
|
+
|
213
|
+
Parent_Selector::Parent_Selector(ParserState pstate, bool r)
|
214
|
+
: Simple_Selector(pstate, "&"), real_(r)
|
215
|
+
{ simple_type(PARENT_SEL); }
|
216
|
+
Parent_Selector::Parent_Selector(const Parent_Selector* ptr)
|
217
|
+
: Simple_Selector(ptr), real_(ptr->real_)
|
218
|
+
{ simple_type(PARENT_SEL); }
|
219
|
+
|
220
|
+
bool Parent_Selector::has_parent_ref() const
|
221
|
+
{
|
222
|
+
return true;
|
223
|
+
};
|
224
|
+
|
225
|
+
bool Parent_Selector::has_real_parent_ref() const
|
226
|
+
{
|
227
|
+
return real();
|
228
|
+
};
|
229
|
+
|
230
|
+
unsigned long Parent_Selector::specificity() const
|
231
|
+
{
|
232
|
+
return 0;
|
233
|
+
}
|
234
|
+
|
235
|
+
/////////////////////////////////////////////////////////////////////////
|
236
|
+
/////////////////////////////////////////////////////////////////////////
|
237
|
+
|
238
|
+
Placeholder_Selector::Placeholder_Selector(ParserState pstate, std::string n)
|
239
|
+
: Simple_Selector(pstate, n)
|
240
|
+
{ simple_type(PLACEHOLDER_SEL); }
|
241
|
+
Placeholder_Selector::Placeholder_Selector(const Placeholder_Selector* ptr)
|
242
|
+
: Simple_Selector(ptr)
|
243
|
+
{ simple_type(PLACEHOLDER_SEL); }
|
244
|
+
unsigned long Placeholder_Selector::specificity() const
|
245
|
+
{
|
246
|
+
return Constants::Specificity_Base;
|
247
|
+
}
|
248
|
+
bool Placeholder_Selector::has_placeholder() {
|
249
|
+
return true;
|
250
|
+
}
|
251
|
+
|
252
|
+
/////////////////////////////////////////////////////////////////////////
|
253
|
+
/////////////////////////////////////////////////////////////////////////
|
254
|
+
|
255
|
+
Type_Selector::Type_Selector(ParserState pstate, std::string n)
|
256
|
+
: Simple_Selector(pstate, n)
|
257
|
+
{ simple_type(TYPE_SEL); }
|
258
|
+
Type_Selector::Type_Selector(const Type_Selector* ptr)
|
259
|
+
: Simple_Selector(ptr)
|
260
|
+
{ simple_type(TYPE_SEL); }
|
261
|
+
|
262
|
+
unsigned long Type_Selector::specificity() const
|
263
|
+
{
|
264
|
+
if (name() == "*") return 0;
|
265
|
+
else return Constants::Specificity_Element;
|
266
|
+
}
|
267
|
+
|
268
|
+
/////////////////////////////////////////////////////////////////////////
|
269
|
+
/////////////////////////////////////////////////////////////////////////
|
270
|
+
|
271
|
+
Class_Selector::Class_Selector(ParserState pstate, std::string n)
|
272
|
+
: Simple_Selector(pstate, n)
|
273
|
+
{ simple_type(CLASS_SEL); }
|
274
|
+
Class_Selector::Class_Selector(const Class_Selector* ptr)
|
275
|
+
: Simple_Selector(ptr)
|
276
|
+
{ simple_type(CLASS_SEL); }
|
277
|
+
|
278
|
+
unsigned long Class_Selector::specificity() const
|
279
|
+
{
|
280
|
+
return Constants::Specificity_Class;
|
281
|
+
}
|
282
|
+
|
283
|
+
/////////////////////////////////////////////////////////////////////////
|
284
|
+
/////////////////////////////////////////////////////////////////////////
|
285
|
+
|
286
|
+
Id_Selector::Id_Selector(ParserState pstate, std::string n)
|
287
|
+
: Simple_Selector(pstate, n)
|
288
|
+
{ simple_type(ID_SEL); }
|
289
|
+
Id_Selector::Id_Selector(const Id_Selector* ptr)
|
290
|
+
: Simple_Selector(ptr)
|
291
|
+
{ simple_type(ID_SEL); }
|
292
|
+
|
293
|
+
unsigned long Id_Selector::specificity() const
|
294
|
+
{
|
295
|
+
return Constants::Specificity_ID;
|
296
|
+
}
|
297
|
+
|
298
|
+
/////////////////////////////////////////////////////////////////////////
|
299
|
+
/////////////////////////////////////////////////////////////////////////
|
300
|
+
|
301
|
+
Attribute_Selector::Attribute_Selector(ParserState pstate, std::string n, std::string m, String_Obj v, char o)
|
302
|
+
: Simple_Selector(pstate, n), matcher_(m), value_(v), modifier_(o)
|
303
|
+
{ simple_type(ATTRIBUTE_SEL); }
|
304
|
+
Attribute_Selector::Attribute_Selector(const Attribute_Selector* ptr)
|
305
|
+
: Simple_Selector(ptr),
|
306
|
+
matcher_(ptr->matcher_),
|
307
|
+
value_(ptr->value_),
|
308
|
+
modifier_(ptr->modifier_)
|
309
|
+
{ simple_type(ATTRIBUTE_SEL); }
|
310
|
+
|
311
|
+
size_t Attribute_Selector::hash() const
|
312
|
+
{
|
313
|
+
if (hash_ == 0) {
|
314
|
+
hash_combine(hash_, Simple_Selector::hash());
|
315
|
+
hash_combine(hash_, std::hash<std::string>()(matcher()));
|
316
|
+
if (value_) hash_combine(hash_, value_->hash());
|
317
|
+
}
|
318
|
+
return hash_;
|
319
|
+
}
|
320
|
+
|
321
|
+
unsigned long Attribute_Selector::specificity() const
|
322
|
+
{
|
323
|
+
return Constants::Specificity_Attr;
|
324
|
+
}
|
325
|
+
|
326
|
+
/////////////////////////////////////////////////////////////////////////
|
327
|
+
/////////////////////////////////////////////////////////////////////////
|
328
|
+
|
329
|
+
Pseudo_Selector::Pseudo_Selector(ParserState pstate, std::string n, String_Obj expr)
|
330
|
+
: Simple_Selector(pstate, n), expression_(expr)
|
331
|
+
{ simple_type(PSEUDO_SEL); }
|
332
|
+
Pseudo_Selector::Pseudo_Selector(const Pseudo_Selector* ptr)
|
333
|
+
: Simple_Selector(ptr), expression_(ptr->expression_)
|
334
|
+
{ simple_type(PSEUDO_SEL); }
|
335
|
+
|
336
|
+
// A pseudo-element is made of two colons (::) followed by the name.
|
337
|
+
// The `::` notation is introduced by the current document in order to
|
338
|
+
// establish a discrimination between pseudo-classes and pseudo-elements.
|
339
|
+
// For compatibility with existing style sheets, user agents must also
|
340
|
+
// accept the previous one-colon notation for pseudo-elements introduced
|
341
|
+
// in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and
|
342
|
+
// :after). This compatibility is not allowed for the new pseudo-elements
|
343
|
+
// introduced in this specification.
|
344
|
+
bool Pseudo_Selector::is_pseudo_element() const
|
345
|
+
{
|
346
|
+
return (name_[0] == ':' && name_[1] == ':')
|
347
|
+
|| is_pseudo_class_element(name_);
|
348
|
+
}
|
349
|
+
|
350
|
+
size_t Pseudo_Selector::hash() const
|
351
|
+
{
|
352
|
+
if (hash_ == 0) {
|
353
|
+
hash_combine(hash_, Simple_Selector::hash());
|
354
|
+
if (expression_) hash_combine(hash_, expression_->hash());
|
355
|
+
}
|
356
|
+
return hash_;
|
357
|
+
}
|
358
|
+
|
359
|
+
unsigned long Pseudo_Selector::specificity() const
|
360
|
+
{
|
361
|
+
if (is_pseudo_element())
|
362
|
+
return Constants::Specificity_Element;
|
363
|
+
return Constants::Specificity_Pseudo;
|
364
|
+
}
|
365
|
+
|
366
|
+
/////////////////////////////////////////////////////////////////////////
|
367
|
+
/////////////////////////////////////////////////////////////////////////
|
368
|
+
|
369
|
+
Wrapped_Selector::Wrapped_Selector(ParserState pstate, std::string n, Selector_List_Obj sel)
|
370
|
+
: Simple_Selector(pstate, n), selector_(sel)
|
371
|
+
{ simple_type(WRAPPED_SEL); }
|
372
|
+
Wrapped_Selector::Wrapped_Selector(const Wrapped_Selector* ptr)
|
373
|
+
: Simple_Selector(ptr), selector_(ptr->selector_)
|
374
|
+
{ simple_type(WRAPPED_SEL); }
|
375
|
+
|
376
|
+
bool Wrapped_Selector::is_superselector_of(const Wrapped_Selector* sub) const
|
377
|
+
{
|
378
|
+
if (this->name() != sub->name()) return false;
|
379
|
+
if (this->name() == ":current") return false;
|
380
|
+
if (Selector_List_Obj rhs_list = Cast<Selector_List>(sub->selector())) {
|
381
|
+
if (Selector_List_Obj lhs_list = Cast<Selector_List>(selector())) {
|
382
|
+
return lhs_list->is_superselector_of(rhs_list);
|
383
|
+
}
|
384
|
+
}
|
385
|
+
coreError("is_superselector expected a Selector_List", sub->pstate());
|
386
|
+
return false;
|
387
|
+
}
|
388
|
+
|
389
|
+
// Selectors inside the negation pseudo-class are counted like any
|
390
|
+
// other, but the negation itself does not count as a pseudo-class.
|
391
|
+
|
392
|
+
void Wrapped_Selector::cloneChildren()
|
393
|
+
{
|
394
|
+
selector(SASS_MEMORY_CLONE(selector()));
|
395
|
+
}
|
396
|
+
|
397
|
+
size_t Wrapped_Selector::hash() const
|
398
|
+
{
|
399
|
+
if (hash_ == 0) {
|
400
|
+
hash_combine(hash_, Simple_Selector::hash());
|
401
|
+
if (selector_) hash_combine(hash_, selector_->hash());
|
402
|
+
}
|
403
|
+
return hash_;
|
404
|
+
}
|
405
|
+
|
406
|
+
bool Wrapped_Selector::has_parent_ref() const {
|
407
|
+
if (!selector()) return false;
|
408
|
+
return selector()->has_parent_ref();
|
409
|
+
}
|
410
|
+
|
411
|
+
bool Wrapped_Selector::has_real_parent_ref() const {
|
412
|
+
if (!selector()) return false;
|
413
|
+
return selector()->has_real_parent_ref();
|
414
|
+
}
|
415
|
+
|
416
|
+
unsigned long Wrapped_Selector::specificity() const
|
417
|
+
{
|
418
|
+
return selector_ ? selector_->specificity() : 0;
|
419
|
+
}
|
420
|
+
|
421
|
+
bool Wrapped_Selector::find ( bool (*f)(AST_Node_Obj) )
|
422
|
+
{
|
423
|
+
// check children first
|
424
|
+
if (selector_) {
|
425
|
+
if (selector_->find(f)) return true;
|
426
|
+
}
|
427
|
+
// execute last
|
428
|
+
return f(this);
|
429
|
+
}
|
430
|
+
|
431
|
+
/////////////////////////////////////////////////////////////////////////
|
432
|
+
/////////////////////////////////////////////////////////////////////////
|
433
|
+
|
434
|
+
Compound_Selector::Compound_Selector(ParserState pstate, size_t s)
|
435
|
+
: Selector(pstate),
|
436
|
+
Vectorized<Simple_Selector_Obj>(s),
|
437
|
+
extended_(false),
|
438
|
+
has_parent_reference_(false)
|
439
|
+
{ }
|
440
|
+
|
441
|
+
Compound_Selector::Compound_Selector(const Compound_Selector* ptr)
|
442
|
+
: Selector(ptr),
|
443
|
+
Vectorized<Simple_Selector_Obj>(*ptr),
|
444
|
+
extended_(ptr->extended_),
|
445
|
+
has_parent_reference_(ptr->has_parent_reference_)
|
446
|
+
{ }
|
447
|
+
|
448
|
+
bool Compound_Selector::contains_placeholder() {
|
449
|
+
for (size_t i = 0, L = length(); i < L; ++i) {
|
450
|
+
if ((*this)[i]->has_placeholder()) return true;
|
451
|
+
}
|
452
|
+
return false;
|
453
|
+
};
|
454
|
+
|
455
|
+
void Compound_Selector::cloneChildren()
|
456
|
+
{
|
457
|
+
for (size_t i = 0, l = length(); i < l; i++) {
|
458
|
+
at(i) = SASS_MEMORY_CLONE(at(i));
|
459
|
+
}
|
460
|
+
}
|
461
|
+
|
462
|
+
bool Compound_Selector::find ( bool (*f)(AST_Node_Obj) )
|
463
|
+
{
|
464
|
+
// check children first
|
465
|
+
for (Simple_Selector_Obj sel : elements()) {
|
466
|
+
if (sel->find(f)) return true;
|
467
|
+
}
|
468
|
+
// execute last
|
469
|
+
return f(this);
|
470
|
+
}
|
471
|
+
|
472
|
+
bool Compound_Selector::has_parent_ref() const
|
473
|
+
{
|
474
|
+
for (Simple_Selector_Obj s : *this) {
|
475
|
+
if (s && s->has_parent_ref()) return true;
|
476
|
+
}
|
477
|
+
return false;
|
478
|
+
}
|
479
|
+
|
480
|
+
bool Compound_Selector::has_real_parent_ref() const
|
481
|
+
{
|
482
|
+
for (Simple_Selector_Obj s : *this) {
|
483
|
+
if (s && s->has_real_parent_ref()) return true;
|
484
|
+
}
|
485
|
+
return false;
|
486
|
+
}
|
487
|
+
|
488
|
+
bool Compound_Selector::is_superselector_of(const Selector_List* rhs, std::string wrapped) const
|
489
|
+
{
|
490
|
+
for (Complex_Selector_Obj item : rhs->elements()) {
|
491
|
+
if (is_superselector_of(item, wrapped)) return true;
|
492
|
+
}
|
493
|
+
return false;
|
494
|
+
}
|
495
|
+
|
496
|
+
bool Compound_Selector::is_superselector_of(const Complex_Selector* rhs, std::string wrapped) const
|
497
|
+
{
|
498
|
+
if (rhs->head()) return is_superselector_of(rhs->head(), wrapped);
|
499
|
+
return false;
|
500
|
+
}
|
501
|
+
|
502
|
+
bool Compound_Selector::is_superselector_of(const Compound_Selector* rhs, std::string wrapping) const
|
503
|
+
{
|
504
|
+
// Check if pseudo-elements are the same between the selectors
|
505
|
+
{
|
506
|
+
std::array<std::set<std::string>, 2> pseudosets;
|
507
|
+
std::array<const Compound_Selector*, 2> compounds = {{this, rhs}};
|
508
|
+
for (int i = 0; i < 2; ++i) {
|
509
|
+
for (const Simple_Selector_Obj& el : compounds[i]->elements()) {
|
510
|
+
if (el->is_pseudo_element()) {
|
511
|
+
std::string pseudo(el->to_string());
|
512
|
+
// strip off colons to ensure :after matches ::after since ruby sass is forgiving
|
513
|
+
pseudosets[i].insert(pseudo.substr(pseudo.find_first_not_of(":")));
|
514
|
+
}
|
515
|
+
}
|
516
|
+
}
|
517
|
+
if (pseudosets[0] != pseudosets[1]) return false;
|
518
|
+
}
|
519
|
+
|
520
|
+
{
|
521
|
+
const Simple_Selector* lbase = this->base();
|
522
|
+
const Simple_Selector* rbase = rhs->base();
|
523
|
+
if (lbase && rbase) {
|
524
|
+
return *lbase == *rbase &&
|
525
|
+
contains_all(std::unordered_set<const Simple_Selector*, HashPtr, ComparePtrs>(rhs->begin(), rhs->end()),
|
526
|
+
std::unordered_set<const Simple_Selector*, HashPtr, ComparePtrs>(this->begin(), this->end()));
|
527
|
+
}
|
528
|
+
}
|
529
|
+
|
530
|
+
std::unordered_set<const Selector*, HashPtr, ComparePtrs> lset;
|
531
|
+
for (size_t i = 0, iL = length(); i < iL; ++i)
|
532
|
+
{
|
533
|
+
const Selector* wlhs = (*this)[i].ptr();
|
534
|
+
// very special case for wrapped matches selector
|
535
|
+
if (const Wrapped_Selector* wrapped = Cast<Wrapped_Selector>(wlhs)) {
|
536
|
+
if (wrapped->name() == ":not") {
|
537
|
+
if (Selector_List_Obj not_list = Cast<Selector_List>(wrapped->selector())) {
|
538
|
+
if (not_list->is_superselector_of(rhs, wrapped->name())) return false;
|
539
|
+
} else {
|
540
|
+
throw std::runtime_error("wrapped not selector is not a list");
|
541
|
+
}
|
542
|
+
}
|
543
|
+
if (wrapped->name() == ":matches" || wrapped->name() == ":-moz-any") {
|
544
|
+
wlhs = wrapped->selector();
|
545
|
+
if (Selector_List_Obj list = Cast<Selector_List>(wrapped->selector())) {
|
546
|
+
if (const Compound_Selector* comp = Cast<Compound_Selector>(rhs)) {
|
547
|
+
if (!wrapping.empty() && wrapping != wrapped->name()) return false;
|
548
|
+
if (wrapping.empty() || wrapping != wrapped->name()) {;
|
549
|
+
if (list->is_superselector_of(comp, wrapped->name())) return true;
|
550
|
+
}
|
551
|
+
}
|
552
|
+
}
|
553
|
+
}
|
554
|
+
Simple_Selector* rhs_sel = nullptr;
|
555
|
+
if (rhs->elements().size() > i) rhs_sel = (*rhs)[i];
|
556
|
+
if (Wrapped_Selector* wrapped_r = Cast<Wrapped_Selector>(rhs_sel)) {
|
557
|
+
if (wrapped->name() == wrapped_r->name()) {
|
558
|
+
if (wrapped->is_superselector_of(wrapped_r)) {
|
559
|
+
continue;
|
560
|
+
}}
|
561
|
+
}
|
562
|
+
}
|
563
|
+
lset.insert(wlhs);
|
564
|
+
}
|
565
|
+
|
566
|
+
if (lset.empty()) return true;
|
567
|
+
|
568
|
+
std::unordered_set<const Selector*, HashPtr, ComparePtrs> rset;
|
569
|
+
for (size_t n = 0, nL = rhs->length(); n < nL; ++n)
|
570
|
+
{
|
571
|
+
Selector_Obj r = (*rhs)[n];
|
572
|
+
if (Wrapped_Selector_Obj wrapped = Cast<Wrapped_Selector>(r)) {
|
573
|
+
if (wrapped->name() == ":not") {
|
574
|
+
if (Selector_List_Obj ls = Cast<Selector_List>(wrapped->selector())) {
|
575
|
+
ls->remove_parent_selectors(); // unverified
|
576
|
+
if (is_superselector_of(ls, wrapped->name())) return false;
|
577
|
+
}
|
578
|
+
}
|
579
|
+
if (wrapped->name() == ":matches" || wrapped->name() == ":-moz-any") {
|
580
|
+
if (!wrapping.empty()) {
|
581
|
+
if (wrapping != wrapped->name()) return false;
|
582
|
+
}
|
583
|
+
if (Selector_List_Obj ls = Cast<Selector_List>(wrapped->selector())) {
|
584
|
+
ls->remove_parent_selectors(); // unverified
|
585
|
+
return (is_superselector_of(ls, wrapped->name()));
|
586
|
+
}
|
587
|
+
}
|
588
|
+
}
|
589
|
+
rset.insert(r);
|
590
|
+
}
|
591
|
+
|
592
|
+
return contains_all(rset, lset);
|
593
|
+
}
|
594
|
+
|
595
|
+
bool Compound_Selector::is_universal() const
|
596
|
+
{
|
597
|
+
return length() == 1 && (*this)[0]->is_universal();
|
598
|
+
}
|
599
|
+
|
600
|
+
// create complex selector (ancestor of) from compound selector
|
601
|
+
Complex_Selector_Obj Compound_Selector::to_complex()
|
602
|
+
{
|
603
|
+
// create an intermediate complex selector
|
604
|
+
return SASS_MEMORY_NEW(Complex_Selector,
|
605
|
+
pstate(),
|
606
|
+
Complex_Selector::ANCESTOR_OF,
|
607
|
+
this,
|
608
|
+
{});
|
609
|
+
}
|
610
|
+
|
611
|
+
Simple_Selector* Compound_Selector::base() const {
|
612
|
+
if (length() == 0) return 0;
|
613
|
+
// ToDo: why is this needed?
|
614
|
+
if (Cast<Type_Selector>((*this)[0]))
|
615
|
+
return (*this)[0];
|
616
|
+
return 0;
|
617
|
+
}
|
618
|
+
|
619
|
+
size_t Compound_Selector::hash() const
|
620
|
+
{
|
621
|
+
if (Selector::hash_ == 0) {
|
622
|
+
hash_combine(Selector::hash_, std::hash<int>()(SELECTOR));
|
623
|
+
if (length()) hash_combine(Selector::hash_, Vectorized::hash());
|
624
|
+
}
|
625
|
+
return Selector::hash_;
|
626
|
+
}
|
627
|
+
|
628
|
+
unsigned long Compound_Selector::specificity() const
|
629
|
+
{
|
630
|
+
int sum = 0;
|
631
|
+
for (size_t i = 0, L = length(); i < L; ++i)
|
632
|
+
{ sum += (*this)[i]->specificity(); }
|
633
|
+
return sum;
|
634
|
+
}
|
635
|
+
|
636
|
+
bool Compound_Selector::has_placeholder()
|
637
|
+
{
|
638
|
+
if (length() == 0) return false;
|
639
|
+
if (Simple_Selector_Obj ss = elements().front()) {
|
640
|
+
if (ss->has_placeholder()) return true;
|
641
|
+
}
|
642
|
+
return false;
|
643
|
+
}
|
644
|
+
|
645
|
+
bool Compound_Selector::is_empty_reference()
|
646
|
+
{
|
647
|
+
return length() == 1 &&
|
648
|
+
Cast<Parent_Selector>((*this)[0]);
|
649
|
+
}
|
650
|
+
|
651
|
+
void Compound_Selector::append(Simple_Selector_Obj element)
|
652
|
+
{
|
653
|
+
Vectorized<Simple_Selector_Obj>::append(element);
|
654
|
+
pstate_.offset += element->pstate().offset;
|
655
|
+
}
|
656
|
+
|
657
|
+
Compound_Selector* Compound_Selector::minus(Compound_Selector* rhs)
|
658
|
+
{
|
659
|
+
Compound_Selector* result = SASS_MEMORY_NEW(Compound_Selector, pstate());
|
660
|
+
// result->has_parent_reference(has_parent_reference());
|
661
|
+
|
662
|
+
// not very efficient because it needs to preserve order
|
663
|
+
for (size_t i = 0, L = length(); i < L; ++i)
|
664
|
+
{
|
665
|
+
bool found = false;
|
666
|
+
for (size_t j = 0, M = rhs->length(); j < M; ++j)
|
667
|
+
{
|
668
|
+
if (*get(i) == *rhs->get(j))
|
669
|
+
{
|
670
|
+
found = true;
|
671
|
+
break;
|
672
|
+
}
|
673
|
+
}
|
674
|
+
if (!found) result->append(get(i));
|
675
|
+
}
|
676
|
+
|
677
|
+
return result;
|
678
|
+
}
|
679
|
+
|
680
|
+
void Compound_Selector::mergeSources(ComplexSelectorSet& sources)
|
681
|
+
{
|
682
|
+
for (ComplexSelectorSet::iterator iterator = sources.begin(), endIterator = sources.end(); iterator != endIterator; ++iterator) {
|
683
|
+
this->sources_.insert(SASS_MEMORY_CLONE(*iterator));
|
684
|
+
}
|
685
|
+
}
|
686
|
+
|
687
|
+
/////////////////////////////////////////////////////////////////////////
|
688
|
+
/////////////////////////////////////////////////////////////////////////
|
689
|
+
|
690
|
+
Complex_Selector::Complex_Selector(ParserState pstate,
|
691
|
+
Combinator c,
|
692
|
+
Compound_Selector_Obj h,
|
693
|
+
Complex_Selector_Obj t,
|
694
|
+
String_Obj r)
|
695
|
+
: Selector(pstate),
|
696
|
+
combinator_(c),
|
697
|
+
head_(h), tail_(t),
|
698
|
+
reference_(r)
|
699
|
+
{}
|
700
|
+
Complex_Selector::Complex_Selector(const Complex_Selector* ptr)
|
701
|
+
: Selector(ptr),
|
702
|
+
combinator_(ptr->combinator_),
|
703
|
+
head_(ptr->head_), tail_(ptr->tail_),
|
704
|
+
reference_(ptr->reference_)
|
705
|
+
{}
|
706
|
+
|
707
|
+
bool Complex_Selector::empty() const {
|
708
|
+
return (!tail() || tail()->empty())
|
709
|
+
&& (!head() || head()->empty())
|
710
|
+
&& combinator_ == ANCESTOR_OF;
|
711
|
+
}
|
712
|
+
|
713
|
+
Complex_Selector_Obj Complex_Selector::skip_empty_reference()
|
714
|
+
{
|
715
|
+
if ((!head_ || !head_->length() || head_->is_empty_reference()) &&
|
716
|
+
combinator() == Combinator::ANCESTOR_OF)
|
717
|
+
{
|
718
|
+
if (!tail_) return {};
|
719
|
+
tail_->has_line_feed_ = this->has_line_feed_;
|
720
|
+
// tail_->has_line_break_ = this->has_line_break_;
|
721
|
+
return tail_->skip_empty_reference();
|
722
|
+
}
|
723
|
+
return this;
|
724
|
+
}
|
725
|
+
|
726
|
+
bool Complex_Selector::is_empty_ancestor() const
|
727
|
+
{
|
728
|
+
return (!head() || head()->length() == 0) &&
|
729
|
+
combinator() == Combinator::ANCESTOR_OF;
|
730
|
+
}
|
731
|
+
|
732
|
+
size_t Complex_Selector::hash() const
|
733
|
+
{
|
734
|
+
if (hash_ == 0) {
|
735
|
+
if (head_) {
|
736
|
+
hash_combine(hash_, head_->hash());
|
737
|
+
} else {
|
738
|
+
hash_combine(hash_, std::hash<int>()(SELECTOR));
|
739
|
+
}
|
740
|
+
if (tail_) hash_combine(hash_, tail_->hash());
|
741
|
+
if (combinator_ != ANCESTOR_OF) hash_combine(hash_, std::hash<int>()(combinator_));
|
742
|
+
}
|
743
|
+
return hash_;
|
744
|
+
}
|
745
|
+
|
746
|
+
unsigned long Complex_Selector::specificity() const
|
747
|
+
{
|
748
|
+
int sum = 0;
|
749
|
+
if (head()) sum += head()->specificity();
|
750
|
+
if (tail()) sum += tail()->specificity();
|
751
|
+
return sum;
|
752
|
+
}
|
753
|
+
|
754
|
+
void Complex_Selector::set_media_block(Media_Block* mb) {
|
755
|
+
media_block(mb);
|
756
|
+
if (tail_) tail_->set_media_block(mb);
|
757
|
+
if (head_) head_->set_media_block(mb);
|
758
|
+
}
|
759
|
+
|
760
|
+
bool Complex_Selector::has_placeholder() {
|
761
|
+
if (head_ && head_->has_placeholder()) return true;
|
762
|
+
if (tail_ && tail_->has_placeholder()) return true;
|
763
|
+
return false;
|
764
|
+
}
|
765
|
+
|
766
|
+
const ComplexSelectorSet Complex_Selector::sources()
|
767
|
+
{
|
768
|
+
//s = Set.new
|
769
|
+
//seq.map {|sseq_or_op| s.merge sseq_or_op.sources if sseq_or_op.is_a?(SimpleSequence)}
|
770
|
+
//s
|
771
|
+
|
772
|
+
ComplexSelectorSet srcs;
|
773
|
+
|
774
|
+
Compound_Selector_Obj pHead = head();
|
775
|
+
Complex_Selector_Obj pTail = tail();
|
776
|
+
|
777
|
+
if (pHead) {
|
778
|
+
const ComplexSelectorSet& headSources = pHead->sources();
|
779
|
+
srcs.insert(headSources.begin(), headSources.end());
|
780
|
+
}
|
781
|
+
|
782
|
+
if (pTail) {
|
783
|
+
const ComplexSelectorSet& tailSources = pTail->sources();
|
784
|
+
srcs.insert(tailSources.begin(), tailSources.end());
|
785
|
+
}
|
786
|
+
|
787
|
+
return srcs;
|
788
|
+
}
|
789
|
+
|
790
|
+
void Complex_Selector::addSources(ComplexSelectorSet& sources)
|
791
|
+
{
|
792
|
+
// members.map! {|m| m.is_a?(SimpleSequence) ? m.with_more_sources(sources) : m}
|
793
|
+
Complex_Selector* pIter = this;
|
794
|
+
while (pIter) {
|
795
|
+
Compound_Selector* pHead = pIter->head();
|
796
|
+
|
797
|
+
if (pHead) {
|
798
|
+
pHead->mergeSources(sources);
|
799
|
+
}
|
800
|
+
|
801
|
+
pIter = pIter->tail();
|
802
|
+
}
|
803
|
+
}
|
804
|
+
|
805
|
+
void Complex_Selector::clearSources()
|
806
|
+
{
|
807
|
+
Complex_Selector* pIter = this;
|
808
|
+
while (pIter) {
|
809
|
+
Compound_Selector* pHead = pIter->head();
|
810
|
+
|
811
|
+
if (pHead) {
|
812
|
+
pHead->clearSources();
|
813
|
+
}
|
814
|
+
|
815
|
+
pIter = pIter->tail();
|
816
|
+
}
|
817
|
+
}
|
818
|
+
|
819
|
+
bool Complex_Selector::find ( bool (*f)(AST_Node_Obj) )
|
820
|
+
{
|
821
|
+
// check children first
|
822
|
+
if (head_ && head_->find(f)) return true;
|
823
|
+
if (tail_ && tail_->find(f)) return true;
|
824
|
+
// execute last
|
825
|
+
return f(this);
|
826
|
+
}
|
827
|
+
|
828
|
+
bool Complex_Selector::has_parent_ref() const
|
829
|
+
{
|
830
|
+
return (head() && head()->has_parent_ref()) ||
|
831
|
+
(tail() && tail()->has_parent_ref());
|
832
|
+
}
|
833
|
+
|
834
|
+
bool Complex_Selector::has_real_parent_ref() const
|
835
|
+
{
|
836
|
+
return (head() && head()->has_real_parent_ref()) ||
|
837
|
+
(tail() && tail()->has_real_parent_ref());
|
838
|
+
}
|
839
|
+
|
840
|
+
bool Complex_Selector::is_superselector_of(const Compound_Selector* rhs, std::string wrapping) const
|
841
|
+
{
|
842
|
+
return last()->head() && last()->head()->is_superselector_of(rhs, wrapping);
|
843
|
+
}
|
844
|
+
|
845
|
+
bool Complex_Selector::is_superselector_of(const Complex_Selector* rhs, std::string wrapping) const
|
846
|
+
{
|
847
|
+
const Complex_Selector* lhs = this;
|
848
|
+
// check for selectors with leading or trailing combinators
|
849
|
+
if (!lhs->head() || !rhs->head())
|
850
|
+
{ return false; }
|
851
|
+
const Complex_Selector* l_innermost = lhs->last();
|
852
|
+
if (l_innermost->combinator() != Complex_Selector::ANCESTOR_OF)
|
853
|
+
{ return false; }
|
854
|
+
const Complex_Selector* r_innermost = rhs->last();
|
855
|
+
if (r_innermost->combinator() != Complex_Selector::ANCESTOR_OF)
|
856
|
+
{ return false; }
|
857
|
+
// more complex (i.e., longer) selectors are always more specific
|
858
|
+
size_t l_len = lhs->length(), r_len = rhs->length();
|
859
|
+
if (l_len > r_len)
|
860
|
+
{ return false; }
|
861
|
+
|
862
|
+
if (l_len == 1)
|
863
|
+
{ return lhs->head()->is_superselector_of(rhs->last()->head(), wrapping); }
|
864
|
+
|
865
|
+
// we have to look one tail deeper, since we cary the
|
866
|
+
// combinator around for it (which is important here)
|
867
|
+
if (rhs->tail() && lhs->tail() && combinator() != Complex_Selector::ANCESTOR_OF) {
|
868
|
+
Complex_Selector_Obj lhs_tail = lhs->tail();
|
869
|
+
Complex_Selector_Obj rhs_tail = rhs->tail();
|
870
|
+
if (lhs_tail->combinator() != rhs_tail->combinator()) return false;
|
871
|
+
if (lhs_tail->head() && !rhs_tail->head()) return false;
|
872
|
+
if (!lhs_tail->head() && rhs_tail->head()) return false;
|
873
|
+
if (lhs_tail->head() && rhs_tail->head()) {
|
874
|
+
if (!lhs_tail->head()->is_superselector_of(rhs_tail->head())) return false;
|
875
|
+
}
|
876
|
+
}
|
877
|
+
|
878
|
+
bool found = false;
|
879
|
+
const Complex_Selector* marker = rhs;
|
880
|
+
for (size_t i = 0, L = rhs->length(); i < L; ++i) {
|
881
|
+
if (i == L-1)
|
882
|
+
{ return false; }
|
883
|
+
if (lhs->head() && marker->head() && lhs->head()->is_superselector_of(marker->head(), wrapping))
|
884
|
+
{ found = true; break; }
|
885
|
+
marker = marker->tail();
|
886
|
+
}
|
887
|
+
if (!found)
|
888
|
+
{ return false; }
|
889
|
+
|
890
|
+
/*
|
891
|
+
Hmm, I hope I have the logic right:
|
892
|
+
|
893
|
+
if lhs has a combinator:
|
894
|
+
if !(marker has a combinator) return false
|
895
|
+
if !(lhs.combinator == '~' ? marker.combinator != '>' : lhs.combinator == marker.combinator) return false
|
896
|
+
return lhs.tail-without-innermost.is_superselector_of(marker.tail-without-innermost)
|
897
|
+
else if marker has a combinator:
|
898
|
+
if !(marker.combinator == ">") return false
|
899
|
+
return lhs.tail.is_superselector_of(marker.tail)
|
900
|
+
else
|
901
|
+
return lhs.tail.is_superselector_of(marker.tail)
|
902
|
+
*/
|
903
|
+
if (lhs->combinator() != Complex_Selector::ANCESTOR_OF)
|
904
|
+
{
|
905
|
+
if (marker->combinator() == Complex_Selector::ANCESTOR_OF)
|
906
|
+
{ return false; }
|
907
|
+
if (!(lhs->combinator() == Complex_Selector::PRECEDES ? marker->combinator() != Complex_Selector::PARENT_OF : lhs->combinator() == marker->combinator()))
|
908
|
+
{ return false; }
|
909
|
+
return lhs->tail()->is_superselector_of(marker->tail());
|
910
|
+
}
|
911
|
+
else if (marker->combinator() != Complex_Selector::ANCESTOR_OF)
|
912
|
+
{
|
913
|
+
if (marker->combinator() != Complex_Selector::PARENT_OF)
|
914
|
+
{ return false; }
|
915
|
+
return lhs->tail()->is_superselector_of(marker->tail());
|
916
|
+
}
|
917
|
+
return lhs->tail()->is_superselector_of(marker->tail());
|
918
|
+
}
|
919
|
+
|
920
|
+
size_t Complex_Selector::length() const
|
921
|
+
{
|
922
|
+
// TODO: make this iterative
|
923
|
+
if (!tail()) return 1;
|
924
|
+
return 1 + tail()->length();
|
925
|
+
}
|
926
|
+
|
927
|
+
// append another complex selector at the end
|
928
|
+
// check if we need to append some headers
|
929
|
+
// then we need to check for the combinator
|
930
|
+
// only then we can safely set the new tail
|
931
|
+
void Complex_Selector::append(Complex_Selector_Obj ss, Backtraces& traces)
|
932
|
+
{
|
933
|
+
|
934
|
+
Complex_Selector_Obj t = ss->tail();
|
935
|
+
Combinator c = ss->combinator();
|
936
|
+
String_Obj r = ss->reference();
|
937
|
+
Compound_Selector_Obj h = ss->head();
|
938
|
+
|
939
|
+
if (ss->has_line_feed()) has_line_feed(true);
|
940
|
+
if (ss->has_line_break()) has_line_break(true);
|
941
|
+
|
942
|
+
// append old headers
|
943
|
+
if (h && h->length()) {
|
944
|
+
if (last()->combinator() != ANCESTOR_OF && c != ANCESTOR_OF) {
|
945
|
+
traces.push_back(Backtrace(pstate()));
|
946
|
+
throw Exception::InvalidParent(this, traces, ss);
|
947
|
+
} else if (last()->head_ && last()->head_->length()) {
|
948
|
+
Compound_Selector_Obj rh = last()->head();
|
949
|
+
size_t i;
|
950
|
+
size_t L = h->length();
|
951
|
+
if (Cast<Type_Selector>(h->first())) {
|
952
|
+
if (Class_Selector* cs = Cast<Class_Selector>(rh->last())) {
|
953
|
+
Class_Selector* sqs = SASS_MEMORY_COPY(cs);
|
954
|
+
sqs->name(sqs->name() + (*h)[0]->name());
|
955
|
+
sqs->pstate((*h)[0]->pstate());
|
956
|
+
(*rh)[rh->length()-1] = sqs;
|
957
|
+
rh->pstate(h->pstate());
|
958
|
+
for (i = 1; i < L; ++i) rh->append((*h)[i]);
|
959
|
+
} else if (Id_Selector* is = Cast<Id_Selector>(rh->last())) {
|
960
|
+
Id_Selector* sqs = SASS_MEMORY_COPY(is);
|
961
|
+
sqs->name(sqs->name() + (*h)[0]->name());
|
962
|
+
sqs->pstate((*h)[0]->pstate());
|
963
|
+
(*rh)[rh->length()-1] = sqs;
|
964
|
+
rh->pstate(h->pstate());
|
965
|
+
for (i = 1; i < L; ++i) rh->append((*h)[i]);
|
966
|
+
} else if (Type_Selector* ts = Cast<Type_Selector>(rh->last())) {
|
967
|
+
Type_Selector* tss = SASS_MEMORY_COPY(ts);
|
968
|
+
tss->name(tss->name() + (*h)[0]->name());
|
969
|
+
tss->pstate((*h)[0]->pstate());
|
970
|
+
(*rh)[rh->length()-1] = tss;
|
971
|
+
rh->pstate(h->pstate());
|
972
|
+
for (i = 1; i < L; ++i) rh->append((*h)[i]);
|
973
|
+
} else if (Placeholder_Selector* ps = Cast<Placeholder_Selector>(rh->last())) {
|
974
|
+
Placeholder_Selector* pss = SASS_MEMORY_COPY(ps);
|
975
|
+
pss->name(pss->name() + (*h)[0]->name());
|
976
|
+
pss->pstate((*h)[0]->pstate());
|
977
|
+
(*rh)[rh->length()-1] = pss;
|
978
|
+
rh->pstate(h->pstate());
|
979
|
+
for (i = 1; i < L; ++i) rh->append((*h)[i]);
|
980
|
+
} else {
|
981
|
+
last()->head_->concat(h);
|
982
|
+
}
|
983
|
+
} else {
|
984
|
+
last()->head_->concat(h);
|
985
|
+
}
|
986
|
+
} else if (last()->head_) {
|
987
|
+
last()->head_->concat(h);
|
988
|
+
}
|
989
|
+
} else {
|
990
|
+
// std::cerr << "has no or empty head\n";
|
991
|
+
}
|
992
|
+
|
993
|
+
Complex_Selector* last = mutable_last();
|
994
|
+
if (last) {
|
995
|
+
if (last->combinator() != ANCESTOR_OF && c != ANCESTOR_OF) {
|
996
|
+
Complex_Selector* inter = SASS_MEMORY_NEW(Complex_Selector, pstate());
|
997
|
+
inter->reference(r);
|
998
|
+
inter->combinator(c);
|
999
|
+
inter->tail(t);
|
1000
|
+
last->tail(inter);
|
1001
|
+
} else {
|
1002
|
+
if (last->combinator() == ANCESTOR_OF) {
|
1003
|
+
last->combinator(c);
|
1004
|
+
last->reference(r);
|
1005
|
+
}
|
1006
|
+
last->tail(t);
|
1007
|
+
}
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
}
|
1011
|
+
|
1012
|
+
Selector_List* Complex_Selector::resolve_parent_refs(SelectorStack& pstack, Backtraces& traces, bool implicit_parent)
|
1013
|
+
{
|
1014
|
+
Complex_Selector_Obj tail = this->tail();
|
1015
|
+
Compound_Selector_Obj head = this->head();
|
1016
|
+
Selector_List* parents = pstack.back();
|
1017
|
+
|
1018
|
+
if (!this->has_real_parent_ref() && !implicit_parent) {
|
1019
|
+
Selector_List* retval = SASS_MEMORY_NEW(Selector_List, pstate(), 1);
|
1020
|
+
retval->append(this);
|
1021
|
+
return retval;
|
1022
|
+
}
|
1023
|
+
|
1024
|
+
// first resolve_parent_refs the tail (which may return an expanded list)
|
1025
|
+
Selector_List_Obj tails = tail ? tail->resolve_parent_refs(pstack, traces, implicit_parent) : 0;
|
1026
|
+
|
1027
|
+
if (head && head->length() > 0) {
|
1028
|
+
|
1029
|
+
Selector_List_Obj retval;
|
1030
|
+
// we have a parent selector in a simple compound list
|
1031
|
+
// mix parent complex selector into the compound list
|
1032
|
+
if (Cast<Parent_Selector>((*head)[0])) {
|
1033
|
+
retval = SASS_MEMORY_NEW(Selector_List, pstate());
|
1034
|
+
|
1035
|
+
// it turns out that real parent references reach
|
1036
|
+
// across @at-root rules, which comes unexpected
|
1037
|
+
if (parents == NULL && head->has_real_parent_ref()) {
|
1038
|
+
int i = pstack.size() - 1;
|
1039
|
+
while (!parents && i > -1) {
|
1040
|
+
parents = pstack.at(i--);
|
1041
|
+
}
|
1042
|
+
}
|
1043
|
+
|
1044
|
+
if (parents && parents->length()) {
|
1045
|
+
if (tails && tails->length() > 0) {
|
1046
|
+
for (size_t n = 0, nL = tails->length(); n < nL; ++n) {
|
1047
|
+
for (size_t i = 0, iL = parents->length(); i < iL; ++i) {
|
1048
|
+
Complex_Selector_Obj t = (*tails)[n];
|
1049
|
+
Complex_Selector_Obj parent = (*parents)[i];
|
1050
|
+
Complex_Selector_Obj s = SASS_MEMORY_CLONE(parent);
|
1051
|
+
Complex_Selector_Obj ss = SASS_MEMORY_CLONE(this);
|
1052
|
+
ss->tail(t ? SASS_MEMORY_CLONE(t) : NULL);
|
1053
|
+
Compound_Selector_Obj h = SASS_MEMORY_COPY(head_);
|
1054
|
+
// remove parent selector from sequence
|
1055
|
+
if (h->length()) {
|
1056
|
+
h->erase(h->begin());
|
1057
|
+
ss->head(h);
|
1058
|
+
} else {
|
1059
|
+
ss->head({});
|
1060
|
+
}
|
1061
|
+
// adjust for parent selector (1 char)
|
1062
|
+
// if (h->length()) {
|
1063
|
+
// ParserState state(h->at(0)->pstate());
|
1064
|
+
// state.offset.column += 1;
|
1065
|
+
// state.column -= 1;
|
1066
|
+
// (*h)[0]->pstate(state);
|
1067
|
+
// }
|
1068
|
+
// keep old parser state
|
1069
|
+
s->pstate(pstate());
|
1070
|
+
// append new tail
|
1071
|
+
s->append(ss, traces);
|
1072
|
+
retval->append(s);
|
1073
|
+
}
|
1074
|
+
}
|
1075
|
+
}
|
1076
|
+
// have no tails but parents
|
1077
|
+
// loop above is inside out
|
1078
|
+
else {
|
1079
|
+
for (size_t i = 0, iL = parents->length(); i < iL; ++i) {
|
1080
|
+
Complex_Selector_Obj parent = (*parents)[i];
|
1081
|
+
Complex_Selector_Obj s = SASS_MEMORY_CLONE(parent);
|
1082
|
+
Complex_Selector_Obj ss = SASS_MEMORY_CLONE(this);
|
1083
|
+
// this is only if valid if the parent has no trailing op
|
1084
|
+
// otherwise we cannot append more simple selectors to head
|
1085
|
+
if (parent->last()->combinator() != ANCESTOR_OF) {
|
1086
|
+
traces.push_back(Backtrace(pstate()));
|
1087
|
+
throw Exception::InvalidParent(parent, traces, ss);
|
1088
|
+
}
|
1089
|
+
ss->tail(tail ? SASS_MEMORY_CLONE(tail) : NULL);
|
1090
|
+
Compound_Selector_Obj h = SASS_MEMORY_COPY(head_);
|
1091
|
+
// remove parent selector from sequence
|
1092
|
+
if (h->length()) {
|
1093
|
+
h->erase(h->begin());
|
1094
|
+
ss->head(h);
|
1095
|
+
} else {
|
1096
|
+
ss->head({});
|
1097
|
+
}
|
1098
|
+
// \/ IMO ruby sass bug \/
|
1099
|
+
ss->has_line_feed(false);
|
1100
|
+
// adjust for parent selector (1 char)
|
1101
|
+
// if (h->length()) {
|
1102
|
+
// ParserState state(h->at(0)->pstate());
|
1103
|
+
// state.offset.column += 1;
|
1104
|
+
// state.column -= 1;
|
1105
|
+
// (*h)[0]->pstate(state);
|
1106
|
+
// }
|
1107
|
+
// keep old parser state
|
1108
|
+
s->pstate(pstate());
|
1109
|
+
// append new tail
|
1110
|
+
s->append(ss, traces);
|
1111
|
+
retval->append(s);
|
1112
|
+
}
|
1113
|
+
}
|
1114
|
+
}
|
1115
|
+
// have no parent but some tails
|
1116
|
+
else {
|
1117
|
+
if (tails && tails->length() > 0) {
|
1118
|
+
for (size_t n = 0, nL = tails->length(); n < nL; ++n) {
|
1119
|
+
Complex_Selector_Obj cpy = SASS_MEMORY_CLONE(this);
|
1120
|
+
cpy->tail(SASS_MEMORY_CLONE(tails->at(n)));
|
1121
|
+
cpy->head(SASS_MEMORY_NEW(Compound_Selector, head->pstate()));
|
1122
|
+
for (size_t i = 1, L = this->head()->length(); i < L; ++i)
|
1123
|
+
cpy->head()->append((*this->head())[i]);
|
1124
|
+
if (!cpy->head()->length()) cpy->head({});
|
1125
|
+
retval->append(cpy->skip_empty_reference());
|
1126
|
+
}
|
1127
|
+
}
|
1128
|
+
// have no parent nor tails
|
1129
|
+
else {
|
1130
|
+
Complex_Selector_Obj cpy = SASS_MEMORY_CLONE(this);
|
1131
|
+
cpy->head(SASS_MEMORY_NEW(Compound_Selector, head->pstate()));
|
1132
|
+
for (size_t i = 1, L = this->head()->length(); i < L; ++i)
|
1133
|
+
cpy->head()->append((*this->head())[i]);
|
1134
|
+
if (!cpy->head()->length()) cpy->head({});
|
1135
|
+
retval->append(cpy->skip_empty_reference());
|
1136
|
+
}
|
1137
|
+
}
|
1138
|
+
}
|
1139
|
+
// no parent selector in head
|
1140
|
+
else {
|
1141
|
+
retval = this->tails(tails);
|
1142
|
+
}
|
1143
|
+
|
1144
|
+
for (Simple_Selector_Obj ss : head->elements()) {
|
1145
|
+
if (Wrapped_Selector* ws = Cast<Wrapped_Selector>(ss)) {
|
1146
|
+
if (Selector_List* sl = Cast<Selector_List>(ws->selector())) {
|
1147
|
+
if (parents) ws->selector(sl->resolve_parent_refs(pstack, traces, implicit_parent));
|
1148
|
+
}
|
1149
|
+
}
|
1150
|
+
}
|
1151
|
+
|
1152
|
+
return retval.detach();
|
1153
|
+
|
1154
|
+
}
|
1155
|
+
// has no head
|
1156
|
+
return this->tails(tails);
|
1157
|
+
}
|
1158
|
+
|
1159
|
+
Selector_List* Complex_Selector::tails(Selector_List* tails)
|
1160
|
+
{
|
1161
|
+
Selector_List* rv = SASS_MEMORY_NEW(Selector_List, pstate_);
|
1162
|
+
if (tails && tails->length()) {
|
1163
|
+
for (size_t i = 0, iL = tails->length(); i < iL; ++i) {
|
1164
|
+
Complex_Selector_Obj pr = SASS_MEMORY_CLONE(this);
|
1165
|
+
pr->tail(tails->at(i));
|
1166
|
+
rv->append(pr);
|
1167
|
+
}
|
1168
|
+
}
|
1169
|
+
else {
|
1170
|
+
rv->append(this);
|
1171
|
+
}
|
1172
|
+
return rv;
|
1173
|
+
}
|
1174
|
+
|
1175
|
+
// return the last tail that is defined
|
1176
|
+
const Complex_Selector* Complex_Selector::first() const
|
1177
|
+
{
|
1178
|
+
// declare variables used in loop
|
1179
|
+
const Complex_Selector* cur = this;
|
1180
|
+
const Compound_Selector* head;
|
1181
|
+
// processing loop
|
1182
|
+
while (cur)
|
1183
|
+
{
|
1184
|
+
// get the head
|
1185
|
+
head = cur->head_.ptr();
|
1186
|
+
// abort (and return) if it is not a parent selector
|
1187
|
+
if (!head || head->length() != 1 || !Cast<Parent_Selector>((*head)[0])) {
|
1188
|
+
break;
|
1189
|
+
}
|
1190
|
+
// advance to next
|
1191
|
+
cur = cur->tail_;
|
1192
|
+
}
|
1193
|
+
// result
|
1194
|
+
return cur;
|
1195
|
+
}
|
1196
|
+
|
1197
|
+
Complex_Selector* Complex_Selector::mutable_first()
|
1198
|
+
{
|
1199
|
+
return const_cast<Complex_Selector*>(first());
|
1200
|
+
}
|
1201
|
+
|
1202
|
+
// return the last tail that is defined
|
1203
|
+
const Complex_Selector* Complex_Selector::last() const
|
1204
|
+
{
|
1205
|
+
const Complex_Selector* cur = this;
|
1206
|
+
const Complex_Selector* nxt = cur;
|
1207
|
+
// loop until last
|
1208
|
+
while (nxt) {
|
1209
|
+
cur = nxt;
|
1210
|
+
nxt = cur->tail_.ptr();
|
1211
|
+
}
|
1212
|
+
return cur;
|
1213
|
+
}
|
1214
|
+
|
1215
|
+
Complex_Selector* Complex_Selector::mutable_last()
|
1216
|
+
{
|
1217
|
+
return const_cast<Complex_Selector*>(last());
|
1218
|
+
}
|
1219
|
+
|
1220
|
+
Complex_Selector::Combinator Complex_Selector::clear_innermost()
|
1221
|
+
{
|
1222
|
+
Combinator c;
|
1223
|
+
if (!tail() || tail()->tail() == nullptr)
|
1224
|
+
{ c = combinator(); combinator(ANCESTOR_OF); tail({}); }
|
1225
|
+
else
|
1226
|
+
{ c = tail_->clear_innermost(); }
|
1227
|
+
return c;
|
1228
|
+
}
|
1229
|
+
|
1230
|
+
void Complex_Selector::set_innermost(Complex_Selector_Obj val, Combinator c)
|
1231
|
+
{
|
1232
|
+
if (!tail_)
|
1233
|
+
{ tail_ = val; combinator(c); }
|
1234
|
+
else
|
1235
|
+
{ tail_->set_innermost(val, c); }
|
1236
|
+
}
|
1237
|
+
|
1238
|
+
void Complex_Selector::cloneChildren()
|
1239
|
+
{
|
1240
|
+
if (head()) head(SASS_MEMORY_CLONE(head()));
|
1241
|
+
if (tail()) tail(SASS_MEMORY_CLONE(tail()));
|
1242
|
+
}
|
1243
|
+
|
1244
|
+
// it's a superselector if every selector of the right side
|
1245
|
+
// list is a superselector of the given left side selector
|
1246
|
+
bool Complex_Selector::is_superselector_of(const Selector_List* sub, std::string wrapping) const
|
1247
|
+
{
|
1248
|
+
// Check every rhs selector against left hand list
|
1249
|
+
for(size_t i = 0, L = sub->length(); i < L; ++i) {
|
1250
|
+
if (!is_superselector_of((*sub)[i], wrapping)) return false;
|
1251
|
+
}
|
1252
|
+
return true;
|
1253
|
+
}
|
1254
|
+
|
1255
|
+
/////////////////////////////////////////////////////////////////////////
|
1256
|
+
/////////////////////////////////////////////////////////////////////////
|
1257
|
+
|
1258
|
+
Selector_List::Selector_List(ParserState pstate, size_t s)
|
1259
|
+
: Selector(pstate),
|
1260
|
+
Vectorized<Complex_Selector_Obj>(s),
|
1261
|
+
schema_({}),
|
1262
|
+
wspace_(0)
|
1263
|
+
{ }
|
1264
|
+
Selector_List::Selector_List(const Selector_List* ptr)
|
1265
|
+
: Selector(ptr),
|
1266
|
+
Vectorized<Complex_Selector_Obj>(*ptr),
|
1267
|
+
schema_(ptr->schema_),
|
1268
|
+
wspace_(ptr->wspace_)
|
1269
|
+
{ }
|
1270
|
+
|
1271
|
+
bool Selector_List::find ( bool (*f)(AST_Node_Obj) )
|
1272
|
+
{
|
1273
|
+
// check children first
|
1274
|
+
for (Complex_Selector_Obj sel : elements()) {
|
1275
|
+
if (sel->find(f)) return true;
|
1276
|
+
}
|
1277
|
+
// execute last
|
1278
|
+
return f(this);
|
1279
|
+
}
|
1280
|
+
|
1281
|
+
Selector_List_Obj Selector_List::eval(Eval& eval)
|
1282
|
+
{
|
1283
|
+
Selector_List_Obj list = schema() ?
|
1284
|
+
eval(schema()) : eval(this);
|
1285
|
+
list->schema(schema());
|
1286
|
+
return list;
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
Selector_List* Selector_List::resolve_parent_refs(SelectorStack& pstack, Backtraces& traces, bool implicit_parent)
|
1290
|
+
{
|
1291
|
+
if (!this->has_parent_ref()) return this;
|
1292
|
+
Selector_List* ss = SASS_MEMORY_NEW(Selector_List, pstate());
|
1293
|
+
for (size_t si = 0, sL = this->length(); si < sL; ++si) {
|
1294
|
+
Selector_List_Obj rv = at(si)->resolve_parent_refs(pstack, traces, implicit_parent);
|
1295
|
+
ss->concat(rv);
|
1296
|
+
}
|
1297
|
+
return ss;
|
1298
|
+
}
|
1299
|
+
|
1300
|
+
void Selector_List::cloneChildren()
|
1301
|
+
{
|
1302
|
+
for (size_t i = 0, l = length(); i < l; i++) {
|
1303
|
+
at(i) = SASS_MEMORY_CLONE(at(i));
|
1304
|
+
}
|
1305
|
+
}
|
1306
|
+
|
1307
|
+
// remove parent selector references
|
1308
|
+
// basically unwraps parsed selectors
|
1309
|
+
void Selector_List::remove_parent_selectors()
|
1310
|
+
{
|
1311
|
+
// Check every rhs selector against left hand list
|
1312
|
+
for(size_t i = 0, L = length(); i < L; ++i) {
|
1313
|
+
if (!(*this)[i]->head()) continue;
|
1314
|
+
if ((*this)[i]->head()->is_empty_reference()) {
|
1315
|
+
// simply move to the next tail if we have "no" combinator
|
1316
|
+
if ((*this)[i]->combinator() == Complex_Selector::ANCESTOR_OF) {
|
1317
|
+
if ((*this)[i]->tail()) {
|
1318
|
+
if ((*this)[i]->has_line_feed()) {
|
1319
|
+
(*this)[i]->tail()->has_line_feed(true);
|
1320
|
+
}
|
1321
|
+
(*this)[i] = (*this)[i]->tail();
|
1322
|
+
}
|
1323
|
+
}
|
1324
|
+
// otherwise remove the first item from head
|
1325
|
+
else {
|
1326
|
+
(*this)[i]->head()->erase((*this)[i]->head()->begin());
|
1327
|
+
}
|
1328
|
+
}
|
1329
|
+
}
|
1330
|
+
}
|
1331
|
+
|
1332
|
+
bool Selector_List::has_parent_ref() const
|
1333
|
+
{
|
1334
|
+
for (Complex_Selector_Obj s : elements()) {
|
1335
|
+
if (s && s->has_parent_ref()) return true;
|
1336
|
+
}
|
1337
|
+
return false;
|
1338
|
+
}
|
1339
|
+
|
1340
|
+
bool Selector_List::has_real_parent_ref() const
|
1341
|
+
{
|
1342
|
+
for (Complex_Selector_Obj s : elements()) {
|
1343
|
+
if (s && s->has_real_parent_ref()) return true;
|
1344
|
+
}
|
1345
|
+
return false;
|
1346
|
+
}
|
1347
|
+
|
1348
|
+
void Selector_List::adjust_after_pushing(Complex_Selector_Obj c)
|
1349
|
+
{
|
1350
|
+
// if (c->has_reference()) has_reference(true);
|
1351
|
+
}
|
1352
|
+
|
1353
|
+
// it's a superselector if every selector of the right side
|
1354
|
+
// list is a superselector of the given left side selector
|
1355
|
+
bool Selector_List::is_superselector_of(const Selector_List* sub, std::string wrapping) const
|
1356
|
+
{
|
1357
|
+
// Check every rhs selector against left hand list
|
1358
|
+
for(size_t i = 0, L = sub->length(); i < L; ++i) {
|
1359
|
+
if (!is_superselector_of((*sub)[i], wrapping)) return false;
|
1360
|
+
}
|
1361
|
+
return true;
|
1362
|
+
}
|
1363
|
+
|
1364
|
+
// it's a superselector if every selector on the right side
|
1365
|
+
// is a superselector of any one of the left side selectors
|
1366
|
+
bool Selector_List::is_superselector_of(const Compound_Selector* sub, std::string wrapping) const
|
1367
|
+
{
|
1368
|
+
// Check every lhs selector against right hand
|
1369
|
+
for(size_t i = 0, L = length(); i < L; ++i) {
|
1370
|
+
if ((*this)[i]->is_superselector_of(sub, wrapping)) return true;
|
1371
|
+
}
|
1372
|
+
return false;
|
1373
|
+
}
|
1374
|
+
|
1375
|
+
// it's a superselector if every selector on the right side
|
1376
|
+
// is a superselector of any one of the left side selectors
|
1377
|
+
bool Selector_List::is_superselector_of(const Complex_Selector* sub, std::string wrapping) const
|
1378
|
+
{
|
1379
|
+
// Check every lhs selector against right hand
|
1380
|
+
for(size_t i = 0, L = length(); i < L; ++i) {
|
1381
|
+
if ((*this)[i]->is_superselector_of(sub)) return true;
|
1382
|
+
}
|
1383
|
+
return false;
|
1384
|
+
}
|
1385
|
+
|
1386
|
+
void Selector_List::populate_extends(Selector_List_Obj extendee, Subset_Map& extends)
|
1387
|
+
{
|
1388
|
+
|
1389
|
+
Selector_List* extender = this;
|
1390
|
+
for (auto complex_sel : extendee->elements()) {
|
1391
|
+
Complex_Selector_Obj c = complex_sel;
|
1392
|
+
|
1393
|
+
|
1394
|
+
// Ignore any parent selectors, until we find the first non Selectorerence head
|
1395
|
+
Compound_Selector_Obj compound_sel = c->head();
|
1396
|
+
Complex_Selector_Obj pIter = complex_sel;
|
1397
|
+
while (pIter) {
|
1398
|
+
Compound_Selector_Obj pHead = pIter->head();
|
1399
|
+
if (pHead && Cast<Parent_Selector>(pHead->elements()[0]) == NULL) {
|
1400
|
+
compound_sel = pHead;
|
1401
|
+
break;
|
1402
|
+
}
|
1403
|
+
|
1404
|
+
pIter = pIter->tail();
|
1405
|
+
}
|
1406
|
+
|
1407
|
+
if (!pIter->head() || pIter->tail()) {
|
1408
|
+
coreError("nested selectors may not be extended", c->pstate());
|
1409
|
+
}
|
1410
|
+
|
1411
|
+
compound_sel->is_optional(extendee->is_optional());
|
1412
|
+
|
1413
|
+
for (size_t i = 0, L = extender->length(); i < L; ++i) {
|
1414
|
+
extends.put(compound_sel, std::make_pair((*extender)[i], compound_sel));
|
1415
|
+
}
|
1416
|
+
}
|
1417
|
+
};
|
1418
|
+
|
1419
|
+
size_t Selector_List::hash() const
|
1420
|
+
{
|
1421
|
+
if (Selector::hash_ == 0) {
|
1422
|
+
if (empty()) {
|
1423
|
+
hash_combine(Selector::hash_, std::hash<int>()(SELECTOR));
|
1424
|
+
} else {
|
1425
|
+
hash_combine(Selector::hash_, Vectorized::hash());
|
1426
|
+
}
|
1427
|
+
}
|
1428
|
+
return Selector::hash_;
|
1429
|
+
}
|
1430
|
+
|
1431
|
+
unsigned long Selector_List::specificity() const
|
1432
|
+
{
|
1433
|
+
unsigned long sum = 0;
|
1434
|
+
unsigned long specificity;
|
1435
|
+
for (size_t i = 0, L = length(); i < L; ++i)
|
1436
|
+
{
|
1437
|
+
specificity = (*this)[i]->specificity();
|
1438
|
+
if (sum < specificity) sum = specificity;
|
1439
|
+
}
|
1440
|
+
return sum;
|
1441
|
+
}
|
1442
|
+
|
1443
|
+
void Selector_List::set_media_block(Media_Block* mb)
|
1444
|
+
{
|
1445
|
+
media_block(mb);
|
1446
|
+
for (Complex_Selector_Obj cs : elements()) {
|
1447
|
+
cs->set_media_block(mb);
|
1448
|
+
}
|
1449
|
+
}
|
1450
|
+
|
1451
|
+
bool Selector_List::has_placeholder()
|
1452
|
+
{
|
1453
|
+
for (Complex_Selector_Obj cs : elements()) {
|
1454
|
+
if (cs->has_placeholder()) return true;
|
1455
|
+
}
|
1456
|
+
return false;
|
1457
|
+
}
|
1458
|
+
|
1459
|
+
/////////////////////////////////////////////////////////////////////////
|
1460
|
+
/////////////////////////////////////////////////////////////////////////
|
1461
|
+
|
1462
|
+
IMPLEMENT_AST_OPERATORS(Selector_Schema);
|
1463
|
+
IMPLEMENT_AST_OPERATORS(Placeholder_Selector);
|
1464
|
+
IMPLEMENT_AST_OPERATORS(Parent_Selector);
|
1465
|
+
IMPLEMENT_AST_OPERATORS(Attribute_Selector);
|
1466
|
+
IMPLEMENT_AST_OPERATORS(Compound_Selector);
|
1467
|
+
IMPLEMENT_AST_OPERATORS(Complex_Selector);
|
1468
|
+
IMPLEMENT_AST_OPERATORS(Type_Selector);
|
1469
|
+
IMPLEMENT_AST_OPERATORS(Class_Selector);
|
1470
|
+
IMPLEMENT_AST_OPERATORS(Id_Selector);
|
1471
|
+
IMPLEMENT_AST_OPERATORS(Pseudo_Selector);
|
1472
|
+
IMPLEMENT_AST_OPERATORS(Wrapped_Selector);
|
1473
|
+
IMPLEMENT_AST_OPERATORS(Selector_List);
|
1474
|
+
|
1475
|
+
}
|