sassc 2.2.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/CHANGELOG.md +18 -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 +4 -0
- data/ext/libsass/src/MurmurHash2.hpp +91 -0
- data/ext/libsass/src/ast.cpp +158 -168
- data/ext/libsass/src/ast.hpp +389 -230
- data/ext/libsass/src/ast_def_macros.hpp +18 -10
- data/ext/libsass/src/ast_fwd_decl.cpp +4 -3
- data/ext/libsass/src/ast_fwd_decl.hpp +98 -165
- data/ext/libsass/src/ast_helpers.hpp +292 -0
- data/ext/libsass/src/ast_sel_cmp.cpp +219 -732
- 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 +594 -1026
- data/ext/libsass/src/ast_selectors.hpp +339 -385
- data/ext/libsass/src/ast_supports.cpp +36 -52
- data/ext/libsass/src/ast_supports.hpp +29 -29
- data/ext/libsass/src/ast_values.cpp +271 -84
- data/ext/libsass/src/ast_values.hpp +116 -107
- data/ext/libsass/src/backtrace.cpp +9 -9
- data/ext/libsass/src/backtrace.hpp +5 -5
- data/ext/libsass/src/base64vlq.cpp +2 -2
- data/ext/libsass/src/base64vlq.hpp +1 -1
- data/ext/libsass/src/bind.cpp +18 -18
- data/ext/libsass/src/bind.hpp +1 -1
- data/ext/libsass/src/c2ast.cpp +3 -3
- data/ext/libsass/src/c2ast.hpp +1 -1
- data/ext/libsass/src/cencode.c +4 -6
- data/ext/libsass/src/check_nesting.cpp +40 -41
- data/ext/libsass/src/check_nesting.hpp +6 -2
- data/ext/libsass/src/color_maps.cpp +14 -13
- data/ext/libsass/src/color_maps.hpp +1 -9
- data/ext/libsass/src/constants.cpp +5 -0
- data/ext/libsass/src/constants.hpp +6 -0
- data/ext/libsass/src/context.cpp +92 -119
- data/ext/libsass/src/context.hpp +41 -53
- data/ext/libsass/src/cssize.cpp +66 -149
- data/ext/libsass/src/cssize.hpp +17 -23
- data/ext/libsass/src/dart_helpers.hpp +199 -0
- data/ext/libsass/src/debugger.hpp +451 -295
- data/ext/libsass/src/emitter.cpp +15 -16
- data/ext/libsass/src/emitter.hpp +10 -12
- data/ext/libsass/src/environment.cpp +27 -27
- data/ext/libsass/src/environment.hpp +29 -24
- data/ext/libsass/src/error_handling.cpp +62 -41
- data/ext/libsass/src/error_handling.hpp +61 -51
- data/ext/libsass/src/eval.cpp +167 -281
- data/ext/libsass/src/eval.hpp +27 -29
- data/ext/libsass/src/eval_selectors.cpp +75 -0
- data/ext/libsass/src/expand.cpp +275 -222
- data/ext/libsass/src/expand.hpp +36 -16
- data/ext/libsass/src/extender.cpp +1188 -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 +81 -72
- data/ext/libsass/src/file.hpp +28 -37
- data/ext/libsass/src/fn_colors.cpp +20 -18
- data/ext/libsass/src/fn_lists.cpp +30 -29
- data/ext/libsass/src/fn_maps.cpp +3 -3
- data/ext/libsass/src/fn_miscs.cpp +34 -46
- data/ext/libsass/src/fn_numbers.cpp +20 -13
- data/ext/libsass/src/fn_selectors.cpp +98 -128
- data/ext/libsass/src/fn_strings.cpp +47 -33
- data/ext/libsass/src/fn_utils.cpp +31 -29
- data/ext/libsass/src/fn_utils.hpp +17 -11
- data/ext/libsass/src/inspect.cpp +186 -148
- data/ext/libsass/src/inspect.hpp +31 -29
- data/ext/libsass/src/lexer.cpp +20 -82
- data/ext/libsass/src/lexer.hpp +5 -16
- data/ext/libsass/src/listize.cpp +23 -37
- data/ext/libsass/src/listize.hpp +8 -9
- data/ext/libsass/src/mapping.hpp +1 -0
- data/ext/libsass/src/memory/allocator.cpp +48 -0
- data/ext/libsass/src/memory/allocator.hpp +138 -0
- data/ext/libsass/src/memory/config.hpp +20 -0
- data/ext/libsass/src/memory/memory_pool.hpp +186 -0
- data/ext/libsass/src/memory/{SharedPtr.cpp → shared_ptr.cpp} +2 -2
- data/ext/libsass/src/memory/{SharedPtr.hpp → shared_ptr.hpp} +55 -9
- data/ext/libsass/src/memory.hpp +12 -0
- data/ext/libsass/src/operation.hpp +71 -61
- data/ext/libsass/src/operators.cpp +19 -18
- data/ext/libsass/src/operators.hpp +11 -11
- data/ext/libsass/src/ordered_map.hpp +112 -0
- data/ext/libsass/src/output.cpp +45 -64
- data/ext/libsass/src/output.hpp +6 -6
- data/ext/libsass/src/parser.cpp +512 -700
- data/ext/libsass/src/parser.hpp +89 -97
- data/ext/libsass/src/parser_selectors.cpp +189 -0
- data/ext/libsass/src/permutate.hpp +164 -0
- data/ext/libsass/src/plugins.cpp +7 -7
- data/ext/libsass/src/plugins.hpp +8 -8
- data/ext/libsass/src/position.cpp +7 -26
- data/ext/libsass/src/position.hpp +44 -21
- 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.cpp +16 -15
- data/ext/libsass/src/sass.hpp +10 -5
- data/ext/libsass/src/sass2scss.cpp +4 -4
- data/ext/libsass/src/sass_context.cpp +91 -122
- 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 +8 -11
- data/ext/libsass/src/settings.hpp +19 -0
- data/ext/libsass/src/source.cpp +69 -0
- data/ext/libsass/src/source.hpp +95 -0
- data/ext/libsass/src/source_data.hpp +32 -0
- data/ext/libsass/src/source_map.cpp +22 -18
- data/ext/libsass/src/source_map.hpp +12 -9
- 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 +24 -22
- data/ext/libsass/src/units.hpp +8 -8
- data/ext/libsass/src/utf8_string.cpp +9 -10
- data/ext/libsass/src/utf8_string.hpp +7 -6
- data/ext/libsass/src/util.cpp +48 -50
- data/ext/libsass/src/util.hpp +20 -21
- data/ext/libsass/src/util_string.cpp +111 -61
- data/ext/libsass/src/util_string.hpp +62 -8
- data/ext/libsass/src/values.cpp +12 -12
- data/lib/sassc/engine.rb +5 -3
- data/lib/sassc/functions_handler.rb +8 -8
- data/lib/sassc/native.rb +4 -6
- 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 +4 -4
- metadata +29 -15
- 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
- data/lib/sassc/native/lib_c.rb +0 -21
@@ -0,0 +1,616 @@
|
|
1
|
+
// sass.hpp must go before all system headers to get the
|
2
|
+
// __EXTENSIONS__ fix on Solaris.
|
3
|
+
#include "sass.hpp"
|
4
|
+
|
5
|
+
#include "ast.hpp"
|
6
|
+
#include "permutate.hpp"
|
7
|
+
#include "dart_helpers.hpp"
|
8
|
+
|
9
|
+
namespace Sass {
|
10
|
+
|
11
|
+
// ##########################################################################
|
12
|
+
// Returns whether or not [compound] contains a `::root` selector.
|
13
|
+
// ##########################################################################
|
14
|
+
bool hasRoot(const CompoundSelector* compound)
|
15
|
+
{
|
16
|
+
// Libsass does not yet know the root selector
|
17
|
+
return false;
|
18
|
+
}
|
19
|
+
// EO hasRoot
|
20
|
+
|
21
|
+
// ##########################################################################
|
22
|
+
// Returns whether a [CompoundSelector] may contain only
|
23
|
+
// one simple selector of the same type as [simple].
|
24
|
+
// ##########################################################################
|
25
|
+
bool isUnique(const SimpleSelector* simple)
|
26
|
+
{
|
27
|
+
if (Cast<IDSelector>(simple)) return true;
|
28
|
+
if (const PseudoSelector * pseudo = Cast<PseudoSelector>(simple)) {
|
29
|
+
if (pseudo->is_pseudo_element()) return true;
|
30
|
+
}
|
31
|
+
return false;
|
32
|
+
}
|
33
|
+
// EO isUnique
|
34
|
+
|
35
|
+
// ##########################################################################
|
36
|
+
// Returns whether [complex1] and [complex2] need to be unified to
|
37
|
+
// produce a valid combined selector. This is necessary when both
|
38
|
+
// selectors contain the same unique simple selector, such as an ID.
|
39
|
+
// ##########################################################################
|
40
|
+
bool mustUnify(
|
41
|
+
const sass::vector<SelectorComponentObj>& complex1,
|
42
|
+
const sass::vector<SelectorComponentObj>& complex2)
|
43
|
+
{
|
44
|
+
|
45
|
+
sass::vector<const SimpleSelector*> uniqueSelectors1;
|
46
|
+
for (const SelectorComponent* component : complex1) {
|
47
|
+
if (const CompoundSelector * compound = component->getCompound()) {
|
48
|
+
for (const SimpleSelector* sel : compound->elements()) {
|
49
|
+
if (isUnique(sel)) {
|
50
|
+
uniqueSelectors1.push_back(sel);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
if (uniqueSelectors1.empty()) return false;
|
56
|
+
|
57
|
+
// ToDo: unsure if this is correct
|
58
|
+
for (const SelectorComponent* component : complex2) {
|
59
|
+
if (const CompoundSelector * compound = component->getCompound()) {
|
60
|
+
for (const SimpleSelector* sel : compound->elements()) {
|
61
|
+
if (isUnique(sel)) {
|
62
|
+
for (auto check : uniqueSelectors1) {
|
63
|
+
if (*check == *sel) return true;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
return false;
|
71
|
+
|
72
|
+
}
|
73
|
+
// EO isUnique
|
74
|
+
|
75
|
+
// ##########################################################################
|
76
|
+
// Helper function used by `weaveParents`
|
77
|
+
// ##########################################################################
|
78
|
+
bool cmpGroups(
|
79
|
+
const sass::vector<SelectorComponentObj>& group1,
|
80
|
+
const sass::vector<SelectorComponentObj>& group2,
|
81
|
+
sass::vector<SelectorComponentObj>& select)
|
82
|
+
{
|
83
|
+
|
84
|
+
if (group1.size() == group2.size() && std::equal(group1.begin(), group1.end(), group2.begin(), PtrObjEqualityFn<SelectorComponent>)) {
|
85
|
+
select = group1;
|
86
|
+
return true;
|
87
|
+
}
|
88
|
+
|
89
|
+
if (!Cast<CompoundSelector>(group1.front())) {
|
90
|
+
select = {};
|
91
|
+
return false;
|
92
|
+
}
|
93
|
+
if (!Cast<CompoundSelector>(group2.front())) {
|
94
|
+
select = {};
|
95
|
+
return false;
|
96
|
+
}
|
97
|
+
|
98
|
+
if (complexIsParentSuperselector(group1, group2)) {
|
99
|
+
select = group2;
|
100
|
+
return true;
|
101
|
+
}
|
102
|
+
if (complexIsParentSuperselector(group2, group1)) {
|
103
|
+
select = group1;
|
104
|
+
return true;
|
105
|
+
}
|
106
|
+
|
107
|
+
if (!mustUnify(group1, group2)) {
|
108
|
+
select = {};
|
109
|
+
return false;
|
110
|
+
}
|
111
|
+
|
112
|
+
sass::vector<sass::vector<SelectorComponentObj>> unified
|
113
|
+
= unifyComplex({ group1, group2 });
|
114
|
+
if (unified.empty()) return false;
|
115
|
+
if (unified.size() > 1) return false;
|
116
|
+
select = unified.front();
|
117
|
+
return true;
|
118
|
+
}
|
119
|
+
// EO cmpGroups
|
120
|
+
|
121
|
+
// ##########################################################################
|
122
|
+
// Helper function used by `weaveParents`
|
123
|
+
// ##########################################################################
|
124
|
+
template <class T>
|
125
|
+
bool checkForEmptyChild(const T& item) {
|
126
|
+
return item.empty();
|
127
|
+
}
|
128
|
+
// EO checkForEmptyChild
|
129
|
+
|
130
|
+
// ##########################################################################
|
131
|
+
// Helper function used by `weaveParents`
|
132
|
+
// ##########################################################################
|
133
|
+
bool cmpChunkForEmptySequence(
|
134
|
+
const sass::vector<sass::vector<SelectorComponentObj>>& seq,
|
135
|
+
const sass::vector<SelectorComponentObj>& group)
|
136
|
+
{
|
137
|
+
return seq.empty();
|
138
|
+
}
|
139
|
+
// EO cmpChunkForEmptySequence
|
140
|
+
|
141
|
+
// ##########################################################################
|
142
|
+
// Helper function used by `weaveParents`
|
143
|
+
// ##########################################################################
|
144
|
+
bool cmpChunkForParentSuperselector(
|
145
|
+
const sass::vector<sass::vector<SelectorComponentObj>>& seq,
|
146
|
+
const sass::vector<SelectorComponentObj>& group)
|
147
|
+
{
|
148
|
+
return seq.empty() || complexIsParentSuperselector(seq.front(), group);
|
149
|
+
}
|
150
|
+
// EO cmpChunkForParentSuperselector
|
151
|
+
|
152
|
+
// ##########################################################################
|
153
|
+
// Returns all orderings of initial subseqeuences of [queue1] and [queue2].
|
154
|
+
// The [done] callback is used to determine the extent of the initial
|
155
|
+
// subsequences. It's called with each queue until it returns `true`.
|
156
|
+
// Destructively removes the initial subsequences of [queue1] and [queue2].
|
157
|
+
// For example, given `(A B C | D E)` and `(1 2 | 3 4 5)` (with `|` denoting
|
158
|
+
// the boundary of the initial subsequence), this would return `[(A B C 1 2),
|
159
|
+
// (1 2 A B C)]`. The queues would then contain `(D E)` and `(3 4 5)`.
|
160
|
+
// ##########################################################################
|
161
|
+
template <class T>
|
162
|
+
sass::vector<sass::vector<T>> getChunks(
|
163
|
+
sass::vector<T>& queue1, sass::vector<T>& queue2,
|
164
|
+
const T& group, bool(*done)(const sass::vector<T>&, const T&)
|
165
|
+
) {
|
166
|
+
|
167
|
+
sass::vector<T> chunk1;
|
168
|
+
while (!done(queue1, group)) {
|
169
|
+
chunk1.push_back(queue1.front());
|
170
|
+
queue1.erase(queue1.begin());
|
171
|
+
}
|
172
|
+
|
173
|
+
sass::vector<T> chunk2;
|
174
|
+
while (!done(queue2, group)) {
|
175
|
+
chunk2.push_back(queue2.front());
|
176
|
+
queue2.erase(queue2.begin());
|
177
|
+
}
|
178
|
+
|
179
|
+
if (chunk1.empty() && chunk2.empty()) return {};
|
180
|
+
else if (chunk1.empty()) return { chunk2 };
|
181
|
+
else if (chunk2.empty()) return { chunk1 };
|
182
|
+
|
183
|
+
sass::vector<T> choice1(chunk1), choice2(chunk2);
|
184
|
+
std::move(std::begin(chunk2), std::end(chunk2),
|
185
|
+
std::inserter(choice1, std::end(choice1)));
|
186
|
+
std::move(std::begin(chunk1), std::end(chunk1),
|
187
|
+
std::inserter(choice2, std::end(choice2)));
|
188
|
+
return { choice1, choice2 };
|
189
|
+
}
|
190
|
+
// EO getChunks
|
191
|
+
|
192
|
+
// ##########################################################################
|
193
|
+
// If the first element of [queue] has a `::root`
|
194
|
+
// selector, removes and returns that element.
|
195
|
+
// ##########################################################################
|
196
|
+
CompoundSelectorObj getFirstIfRoot(sass::vector<SelectorComponentObj>& queue) {
|
197
|
+
if (queue.empty()) return {};
|
198
|
+
SelectorComponent* first = queue.front();
|
199
|
+
if (CompoundSelector* sel = Cast<CompoundSelector>(first)) {
|
200
|
+
if (!hasRoot(sel)) return {};
|
201
|
+
queue.erase(queue.begin());
|
202
|
+
return sel;
|
203
|
+
}
|
204
|
+
return {};
|
205
|
+
}
|
206
|
+
// EO getFirstIfRoot
|
207
|
+
|
208
|
+
// ##########################################################################
|
209
|
+
// Returns [complex], grouped into sub-lists such that no sub-list
|
210
|
+
// contains two adjacent [ComplexSelector]s. For example,
|
211
|
+
// `(A B > C D + E ~ > G)` is grouped into `[(A) (B > C) (D + E ~ > G)]`.
|
212
|
+
// ##########################################################################
|
213
|
+
sass::vector<sass::vector<SelectorComponentObj>> groupSelectors(
|
214
|
+
const sass::vector<SelectorComponentObj>& components)
|
215
|
+
{
|
216
|
+
bool lastWasCompound = false;
|
217
|
+
sass::vector<SelectorComponentObj> group;
|
218
|
+
sass::vector<sass::vector<SelectorComponentObj>> groups;
|
219
|
+
for (size_t i = 0; i < components.size(); i += 1) {
|
220
|
+
if (CompoundSelector* compound = components[i]->getCompound()) {
|
221
|
+
if (lastWasCompound) {
|
222
|
+
groups.push_back(group);
|
223
|
+
group.clear();
|
224
|
+
}
|
225
|
+
group.push_back(compound);
|
226
|
+
lastWasCompound = true;
|
227
|
+
}
|
228
|
+
else if (SelectorCombinator* combinator = components[i]->getCombinator()) {
|
229
|
+
group.push_back(combinator);
|
230
|
+
lastWasCompound = false;
|
231
|
+
}
|
232
|
+
}
|
233
|
+
if (!group.empty()) {
|
234
|
+
groups.push_back(group);
|
235
|
+
}
|
236
|
+
return groups;
|
237
|
+
}
|
238
|
+
// EO groupSelectors
|
239
|
+
|
240
|
+
// ##########################################################################
|
241
|
+
// Extracts leading [Combinator]s from [components1] and [components2]
|
242
|
+
// and merges them together into a single list of combinators.
|
243
|
+
// If there are no combinators to be merged, returns an empty list.
|
244
|
+
// If the combinators can't be merged, returns `null`.
|
245
|
+
// ##########################################################################
|
246
|
+
bool mergeInitialCombinators(
|
247
|
+
sass::vector<SelectorComponentObj>& components1,
|
248
|
+
sass::vector<SelectorComponentObj>& components2,
|
249
|
+
sass::vector<SelectorComponentObj>& result)
|
250
|
+
{
|
251
|
+
|
252
|
+
sass::vector<SelectorComponentObj> combinators1;
|
253
|
+
while (!components1.empty() && Cast<SelectorCombinator>(components1.front())) {
|
254
|
+
SelectorCombinatorObj front = Cast<SelectorCombinator>(components1.front());
|
255
|
+
components1.erase(components1.begin());
|
256
|
+
combinators1.push_back(front);
|
257
|
+
}
|
258
|
+
|
259
|
+
sass::vector<SelectorComponentObj> combinators2;
|
260
|
+
while (!components2.empty() && Cast<SelectorCombinator>(components2.front())) {
|
261
|
+
SelectorCombinatorObj front = Cast<SelectorCombinator>(components2.front());
|
262
|
+
components2.erase(components2.begin());
|
263
|
+
combinators2.push_back(front);
|
264
|
+
}
|
265
|
+
|
266
|
+
// If neither sequence of combinators is a subsequence
|
267
|
+
// of the other, they cannot be merged successfully.
|
268
|
+
sass::vector<SelectorComponentObj> LCS = lcs<SelectorComponentObj>(combinators1, combinators2);
|
269
|
+
|
270
|
+
if (ListEquality(LCS, combinators1, PtrObjEqualityFn<SelectorComponent>)) {
|
271
|
+
result = combinators2;
|
272
|
+
return true;
|
273
|
+
}
|
274
|
+
if (ListEquality(LCS, combinators2, PtrObjEqualityFn<SelectorComponent>)) {
|
275
|
+
result = combinators1;
|
276
|
+
return true;
|
277
|
+
}
|
278
|
+
|
279
|
+
return false;
|
280
|
+
|
281
|
+
}
|
282
|
+
// EO mergeInitialCombinators
|
283
|
+
|
284
|
+
// ##########################################################################
|
285
|
+
// Extracts trailing [Combinator]s, and the selectors to which they apply,
|
286
|
+
// from [components1] and [components2] and merges them together into a
|
287
|
+
// single list. If there are no combinators to be merged, returns an
|
288
|
+
// empty list. If the sequences can't be merged, returns `null`.
|
289
|
+
// ##########################################################################
|
290
|
+
bool mergeFinalCombinators(
|
291
|
+
sass::vector<SelectorComponentObj>& components1,
|
292
|
+
sass::vector<SelectorComponentObj>& components2,
|
293
|
+
sass::vector<sass::vector<sass::vector<SelectorComponentObj>>>& result)
|
294
|
+
{
|
295
|
+
|
296
|
+
if (components1.empty() || !Cast<SelectorCombinator>(components1.back())) {
|
297
|
+
if (components2.empty() || !Cast<SelectorCombinator>(components2.back())) {
|
298
|
+
return true;
|
299
|
+
}
|
300
|
+
}
|
301
|
+
|
302
|
+
sass::vector<SelectorComponentObj> combinators1;
|
303
|
+
while (!components1.empty() && Cast<SelectorCombinator>(components1.back())) {
|
304
|
+
SelectorCombinatorObj back = Cast<SelectorCombinator>(components1.back());
|
305
|
+
components1.erase(components1.end() - 1);
|
306
|
+
combinators1.push_back(back);
|
307
|
+
}
|
308
|
+
|
309
|
+
sass::vector<SelectorComponentObj> combinators2;
|
310
|
+
while (!components2.empty() && Cast<SelectorCombinator>(components2.back())) {
|
311
|
+
SelectorCombinatorObj back = Cast<SelectorCombinator>(components2.back());
|
312
|
+
components2.erase(components2.end() - 1);
|
313
|
+
combinators2.push_back(back);
|
314
|
+
}
|
315
|
+
|
316
|
+
// reverse now as we used push_back (faster than new alloc)
|
317
|
+
std::reverse(combinators1.begin(), combinators1.end());
|
318
|
+
std::reverse(combinators2.begin(), combinators2.end());
|
319
|
+
|
320
|
+
if (combinators1.size() > 1 || combinators2.size() > 1) {
|
321
|
+
// If there are multiple combinators, something hacky's going on. If one
|
322
|
+
// is a supersequence of the other, use that, otherwise give up.
|
323
|
+
auto LCS = lcs<SelectorComponentObj>(combinators1, combinators2);
|
324
|
+
if (ListEquality(LCS, combinators1, PtrObjEqualityFn<SelectorComponent>)) {
|
325
|
+
result.push_back({ combinators2 });
|
326
|
+
}
|
327
|
+
else if (ListEquality(LCS, combinators2, PtrObjEqualityFn<SelectorComponent>)) {
|
328
|
+
result.push_back({ combinators1 });
|
329
|
+
}
|
330
|
+
else {
|
331
|
+
return false;
|
332
|
+
}
|
333
|
+
return true;
|
334
|
+
}
|
335
|
+
|
336
|
+
// This code looks complicated, but it's actually just a bunch of special
|
337
|
+
// cases for interactions between different combinators.
|
338
|
+
SelectorCombinatorObj combinator1, combinator2;
|
339
|
+
if (!combinators1.empty()) combinator1 = combinators1.back();
|
340
|
+
if (!combinators2.empty()) combinator2 = combinators2.back();
|
341
|
+
|
342
|
+
if (!combinator1.isNull() && !combinator2.isNull()) {
|
343
|
+
|
344
|
+
CompoundSelector* compound1 = Cast<CompoundSelector>(components1.back());
|
345
|
+
CompoundSelector* compound2 = Cast<CompoundSelector>(components2.back());
|
346
|
+
|
347
|
+
components1.pop_back();
|
348
|
+
components2.pop_back();
|
349
|
+
|
350
|
+
if (combinator1->isGeneralCombinator() && combinator2->isGeneralCombinator()) {
|
351
|
+
|
352
|
+
if (compound1->isSuperselectorOf(compound2)) {
|
353
|
+
result.push_back({ { compound2, combinator2 } });
|
354
|
+
}
|
355
|
+
else if (compound2->isSuperselectorOf(compound1)) {
|
356
|
+
result.push_back({ { compound1, combinator1 } });
|
357
|
+
}
|
358
|
+
else {
|
359
|
+
sass::vector<sass::vector<SelectorComponentObj>> choices;
|
360
|
+
choices.push_back({ compound1, combinator1, compound2, combinator2 });
|
361
|
+
choices.push_back({ compound2, combinator2, compound1, combinator1 });
|
362
|
+
if (CompoundSelector* unified = compound1->unifyWith(compound2)) {
|
363
|
+
choices.push_back({ unified, combinator1 });
|
364
|
+
}
|
365
|
+
result.push_back(choices);
|
366
|
+
}
|
367
|
+
}
|
368
|
+
else if ((combinator1->isGeneralCombinator() && combinator2->isAdjacentCombinator()) ||
|
369
|
+
(combinator1->isAdjacentCombinator() && combinator2->isGeneralCombinator())) {
|
370
|
+
|
371
|
+
CompoundSelector* followingSiblingSelector = combinator1->isGeneralCombinator() ? compound1 : compound2;
|
372
|
+
CompoundSelector* nextSiblingSelector = combinator1->isGeneralCombinator() ? compound2 : compound1;
|
373
|
+
SelectorCombinator* followingSiblingCombinator = combinator1->isGeneralCombinator() ? combinator1 : combinator2;
|
374
|
+
SelectorCombinator* nextSiblingCombinator = combinator1->isGeneralCombinator() ? combinator2 : combinator1;
|
375
|
+
|
376
|
+
if (followingSiblingSelector->isSuperselectorOf(nextSiblingSelector)) {
|
377
|
+
result.push_back({ { nextSiblingSelector, nextSiblingCombinator } });
|
378
|
+
}
|
379
|
+
else {
|
380
|
+
CompoundSelectorObj unified = compound1->unifyWith(compound2);
|
381
|
+
sass::vector<sass::vector<SelectorComponentObj>> items;
|
382
|
+
|
383
|
+
if (!unified.isNull()) {
|
384
|
+
items.push_back({
|
385
|
+
unified, nextSiblingCombinator
|
386
|
+
});
|
387
|
+
}
|
388
|
+
|
389
|
+
items.insert(items.begin(), {
|
390
|
+
followingSiblingSelector,
|
391
|
+
followingSiblingCombinator,
|
392
|
+
nextSiblingSelector,
|
393
|
+
nextSiblingCombinator,
|
394
|
+
});
|
395
|
+
|
396
|
+
result.push_back(items);
|
397
|
+
}
|
398
|
+
|
399
|
+
}
|
400
|
+
else if (combinator1->isChildCombinator() && (combinator2->isAdjacentCombinator() || combinator2->isGeneralCombinator())) {
|
401
|
+
result.push_back({ { compound2, combinator2 } });
|
402
|
+
components1.push_back(compound1);
|
403
|
+
components1.push_back(combinator1);
|
404
|
+
}
|
405
|
+
else if (combinator2->isChildCombinator() && (combinator1->isAdjacentCombinator() || combinator1->isGeneralCombinator())) {
|
406
|
+
result.push_back({ { compound1, combinator1 } });
|
407
|
+
components2.push_back(compound2);
|
408
|
+
components2.push_back(combinator2);
|
409
|
+
}
|
410
|
+
else if (*combinator1 == *combinator2) {
|
411
|
+
CompoundSelectorObj unified = compound1->unifyWith(compound2);
|
412
|
+
if (unified.isNull()) return false;
|
413
|
+
result.push_back({ { unified, combinator1 } });
|
414
|
+
}
|
415
|
+
else {
|
416
|
+
return false;
|
417
|
+
}
|
418
|
+
|
419
|
+
return mergeFinalCombinators(components1, components2, result);
|
420
|
+
|
421
|
+
}
|
422
|
+
else if (!combinator1.isNull()) {
|
423
|
+
|
424
|
+
if (combinator1->isChildCombinator() && !components2.empty()) {
|
425
|
+
const CompoundSelector* back1 = Cast<CompoundSelector>(components1.back());
|
426
|
+
const CompoundSelector* back2 = Cast<CompoundSelector>(components2.back());
|
427
|
+
if (back1 && back2 && back2->isSuperselectorOf(back1)) {
|
428
|
+
components2.pop_back();
|
429
|
+
}
|
430
|
+
}
|
431
|
+
|
432
|
+
result.push_back({ { components1.back(), combinator1 } });
|
433
|
+
|
434
|
+
components1.pop_back();
|
435
|
+
|
436
|
+
return mergeFinalCombinators(components1, components2, result);
|
437
|
+
|
438
|
+
}
|
439
|
+
|
440
|
+
if (combinator2->isChildCombinator() && !components1.empty()) {
|
441
|
+
const CompoundSelector* back1 = Cast<CompoundSelector>(components1.back());
|
442
|
+
const CompoundSelector* back2 = Cast<CompoundSelector>(components2.back());
|
443
|
+
if (back1 && back2 && back1->isSuperselectorOf(back2)) {
|
444
|
+
components1.pop_back();
|
445
|
+
}
|
446
|
+
}
|
447
|
+
|
448
|
+
result.push_back({ { components2.back(), combinator2 } });
|
449
|
+
|
450
|
+
components2.pop_back();
|
451
|
+
|
452
|
+
return mergeFinalCombinators(components1, components2, result);
|
453
|
+
|
454
|
+
}
|
455
|
+
// EO mergeFinalCombinators
|
456
|
+
|
457
|
+
// ##########################################################################
|
458
|
+
// Expands "parenthesized selectors" in [complexes]. That is, if
|
459
|
+
// we have `.A .B {@extend .C}` and `.D .C {...}`, this conceptually
|
460
|
+
// expands into `.D .C, .D (.A .B)`, and this function translates
|
461
|
+
// `.D (.A .B)` into `.D .A .B, .A .D .B`. For thoroughness, `.A.D .B`
|
462
|
+
// would also be required, but including merged selectors results in
|
463
|
+
// exponential output for very little gain. The selector `.D (.A .B)`
|
464
|
+
// is represented as the list `[[.D], [.A, .B]]`.
|
465
|
+
// ##########################################################################
|
466
|
+
sass::vector<sass::vector<SelectorComponentObj>> weave(
|
467
|
+
const sass::vector<sass::vector<SelectorComponentObj>>& complexes) {
|
468
|
+
|
469
|
+
sass::vector<sass::vector<SelectorComponentObj>> prefixes;
|
470
|
+
|
471
|
+
prefixes.push_back(complexes.at(0));
|
472
|
+
|
473
|
+
for (size_t i = 1; i < complexes.size(); i += 1) {
|
474
|
+
|
475
|
+
if (complexes[i].empty()) {
|
476
|
+
continue;
|
477
|
+
}
|
478
|
+
const sass::vector<SelectorComponentObj>& complex = complexes[i];
|
479
|
+
SelectorComponent* target = complex.back();
|
480
|
+
if (complex.size() == 1) {
|
481
|
+
for (auto& prefix : prefixes) {
|
482
|
+
prefix.push_back(target);
|
483
|
+
}
|
484
|
+
continue;
|
485
|
+
}
|
486
|
+
|
487
|
+
sass::vector<SelectorComponentObj> parents(complex);
|
488
|
+
|
489
|
+
parents.pop_back();
|
490
|
+
|
491
|
+
sass::vector<sass::vector<SelectorComponentObj>> newPrefixes;
|
492
|
+
for (sass::vector<SelectorComponentObj> prefix : prefixes) {
|
493
|
+
sass::vector<sass::vector<SelectorComponentObj>>
|
494
|
+
parentPrefixes = weaveParents(prefix, parents);
|
495
|
+
if (parentPrefixes.empty()) continue;
|
496
|
+
for (auto& parentPrefix : parentPrefixes) {
|
497
|
+
parentPrefix.push_back(target);
|
498
|
+
newPrefixes.push_back(parentPrefix);
|
499
|
+
}
|
500
|
+
}
|
501
|
+
prefixes = newPrefixes;
|
502
|
+
|
503
|
+
}
|
504
|
+
return prefixes;
|
505
|
+
|
506
|
+
}
|
507
|
+
// EO weave
|
508
|
+
|
509
|
+
// ##########################################################################
|
510
|
+
// Interweaves [parents1] and [parents2] as parents of the same target
|
511
|
+
// selector. Returns all possible orderings of the selectors in the
|
512
|
+
// inputs (including using unification) that maintain the relative
|
513
|
+
// ordering of the input. For example, given `.foo .bar` and `.baz .bang`,
|
514
|
+
// this would return `.foo .bar .baz .bang`, `.foo .bar.baz .bang`,
|
515
|
+
// `.foo .baz .bar .bang`, `.foo .baz .bar.bang`, `.foo .baz .bang .bar`,
|
516
|
+
// and so on until `.baz .bang .foo .bar`. Semantically, for selectors A
|
517
|
+
// and B, this returns all selectors `AB_i` such that the union over all i
|
518
|
+
// of elements matched by `AB_i X` is identical to the intersection of all
|
519
|
+
// elements matched by `A X` and all elements matched by `B X`. Some `AB_i`
|
520
|
+
// are elided to reduce the size of the output.
|
521
|
+
// ##########################################################################
|
522
|
+
sass::vector<sass::vector<SelectorComponentObj>> weaveParents(
|
523
|
+
sass::vector<SelectorComponentObj> queue1,
|
524
|
+
sass::vector<SelectorComponentObj> queue2)
|
525
|
+
{
|
526
|
+
|
527
|
+
sass::vector<SelectorComponentObj> leads;
|
528
|
+
sass::vector<sass::vector<sass::vector<SelectorComponentObj>>> trails;
|
529
|
+
if (!mergeInitialCombinators(queue1, queue2, leads)) return {};
|
530
|
+
if (!mergeFinalCombinators(queue1, queue2, trails)) return {};
|
531
|
+
// list comes out in reverse order for performance
|
532
|
+
std::reverse(trails.begin(), trails.end());
|
533
|
+
|
534
|
+
// Make sure there's at most one `:root` in the output.
|
535
|
+
// Note: does not yet do anything in libsass (no root selector)
|
536
|
+
CompoundSelectorObj root1 = getFirstIfRoot(queue1);
|
537
|
+
CompoundSelectorObj root2 = getFirstIfRoot(queue2);
|
538
|
+
|
539
|
+
if (!root1.isNull() && !root2.isNull()) {
|
540
|
+
CompoundSelectorObj root = root1->unifyWith(root2);
|
541
|
+
if (root.isNull()) return {}; // null
|
542
|
+
queue1.insert(queue1.begin(), root);
|
543
|
+
queue2.insert(queue2.begin(), root);
|
544
|
+
}
|
545
|
+
else if (!root1.isNull()) {
|
546
|
+
queue2.insert(queue2.begin(), root1);
|
547
|
+
}
|
548
|
+
else if (!root2.isNull()) {
|
549
|
+
queue1.insert(queue1.begin(), root2);
|
550
|
+
}
|
551
|
+
|
552
|
+
// group into sub-lists so no sub-list contains two adjacent ComplexSelectors.
|
553
|
+
sass::vector<sass::vector<SelectorComponentObj>> groups1 = groupSelectors(queue1);
|
554
|
+
sass::vector<sass::vector<SelectorComponentObj>> groups2 = groupSelectors(queue2);
|
555
|
+
|
556
|
+
// The main array to store our choices that will be permutated
|
557
|
+
sass::vector<sass::vector<sass::vector<SelectorComponentObj>>> choices;
|
558
|
+
|
559
|
+
// append initial combinators
|
560
|
+
choices.push_back({ leads });
|
561
|
+
|
562
|
+
sass::vector<sass::vector<SelectorComponentObj>> LCS =
|
563
|
+
lcs<sass::vector<SelectorComponentObj>>(groups1, groups2, cmpGroups);
|
564
|
+
|
565
|
+
for (auto group : LCS) {
|
566
|
+
|
567
|
+
// Create junks from groups1 and groups2
|
568
|
+
sass::vector<sass::vector<sass::vector<SelectorComponentObj>>>
|
569
|
+
chunks = getChunks<sass::vector<SelectorComponentObj>>(
|
570
|
+
groups1, groups2, group, cmpChunkForParentSuperselector);
|
571
|
+
|
572
|
+
// Create expanded array by flattening chunks2 inner
|
573
|
+
sass::vector<sass::vector<SelectorComponentObj>>
|
574
|
+
expanded = flattenInner(chunks);
|
575
|
+
|
576
|
+
// Prepare data structures
|
577
|
+
choices.push_back(expanded);
|
578
|
+
choices.push_back({ group });
|
579
|
+
if (!groups1.empty()) {
|
580
|
+
groups1.erase(groups1.begin());
|
581
|
+
}
|
582
|
+
if (!groups2.empty()) {
|
583
|
+
groups2.erase(groups2.begin());
|
584
|
+
}
|
585
|
+
|
586
|
+
}
|
587
|
+
|
588
|
+
// Create junks from groups1 and groups2
|
589
|
+
sass::vector<sass::vector<sass::vector<SelectorComponentObj>>>
|
590
|
+
chunks = getChunks<sass::vector<SelectorComponentObj>>(
|
591
|
+
groups1, groups2, {}, cmpChunkForEmptySequence);
|
592
|
+
|
593
|
+
// Append chunks with inner arrays flattened
|
594
|
+
choices.emplace_back(flattenInner(chunks));
|
595
|
+
|
596
|
+
// append all trailing selectors to choices
|
597
|
+
std::move(std::begin(trails), std::end(trails),
|
598
|
+
std::inserter(choices, std::end(choices)));
|
599
|
+
|
600
|
+
// move all non empty items to the front, then erase the trailing ones
|
601
|
+
choices.erase(std::remove_if(choices.begin(), choices.end(), checkForEmptyChild
|
602
|
+
<sass::vector<sass::vector<SelectorComponentObj>>>), choices.end());
|
603
|
+
|
604
|
+
// permutate all possible paths through selectors
|
605
|
+
sass::vector<sass::vector<SelectorComponentObj>>
|
606
|
+
results = flattenInner(permutate(choices));
|
607
|
+
|
608
|
+
return results;
|
609
|
+
|
610
|
+
}
|
611
|
+
// EO weaveParents
|
612
|
+
|
613
|
+
// ##########################################################################
|
614
|
+
// ##########################################################################
|
615
|
+
|
616
|
+
}
|