sassc 2.0.0 → 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.
Files changed (260) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.gitmodules +1 -1
  4. data/.travis.yml +9 -3
  5. data/CHANGELOG.md +36 -0
  6. data/CODE_OF_CONDUCT.md +1 -1
  7. data/README.md +1 -1
  8. data/Rakefile +43 -7
  9. data/ext/depend +4 -0
  10. data/ext/extconf.rb +92 -0
  11. data/ext/libsass/VERSION +1 -0
  12. data/ext/libsass/include/sass/base.h +9 -1
  13. data/ext/libsass/include/sass/context.h +5 -1
  14. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  15. data/ext/libsass/src/ast.cpp +755 -2028
  16. data/ext/libsass/src/ast.hpp +492 -2477
  17. data/ext/libsass/src/{to_c.cpp → ast2c.cpp} +22 -16
  18. data/ext/libsass/src/ast2c.hpp +39 -0
  19. data/ext/libsass/src/ast_def_macros.hpp +70 -10
  20. data/ext/libsass/src/ast_fwd_decl.cpp +5 -3
  21. data/ext/libsass/src/ast_fwd_decl.hpp +107 -296
  22. data/ext/libsass/src/ast_helpers.hpp +292 -0
  23. data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
  24. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  25. data/ext/libsass/src/ast_sel_unify.cpp +275 -0
  26. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  27. data/ext/libsass/src/ast_selectors.cpp +1043 -0
  28. data/ext/libsass/src/ast_selectors.hpp +522 -0
  29. data/ext/libsass/src/ast_supports.cpp +114 -0
  30. data/ext/libsass/src/ast_supports.hpp +121 -0
  31. data/ext/libsass/src/ast_values.cpp +1154 -0
  32. data/ext/libsass/src/ast_values.hpp +498 -0
  33. data/ext/libsass/src/backtrace.cpp +11 -7
  34. data/ext/libsass/src/backtrace.hpp +5 -5
  35. data/ext/libsass/src/base64vlq.cpp +5 -2
  36. data/ext/libsass/src/base64vlq.hpp +1 -1
  37. data/ext/libsass/src/bind.cpp +35 -34
  38. data/ext/libsass/src/bind.hpp +3 -1
  39. data/ext/libsass/src/c2ast.cpp +64 -0
  40. data/ext/libsass/src/c2ast.hpp +14 -0
  41. data/ext/libsass/src/cencode.c +4 -6
  42. data/ext/libsass/src/check_nesting.cpp +83 -88
  43. data/ext/libsass/src/check_nesting.hpp +39 -34
  44. data/ext/libsass/src/color_maps.cpp +168 -164
  45. data/ext/libsass/src/color_maps.hpp +152 -160
  46. data/ext/libsass/src/constants.cpp +20 -0
  47. data/ext/libsass/src/constants.hpp +19 -0
  48. data/ext/libsass/src/context.cpp +104 -121
  49. data/ext/libsass/src/context.hpp +43 -55
  50. data/ext/libsass/src/cssize.cpp +103 -188
  51. data/ext/libsass/src/cssize.hpp +45 -51
  52. data/ext/libsass/src/dart_helpers.hpp +199 -0
  53. data/ext/libsass/src/debugger.hpp +524 -361
  54. data/ext/libsass/src/emitter.cpp +26 -26
  55. data/ext/libsass/src/emitter.hpp +20 -18
  56. data/ext/libsass/src/environment.cpp +41 -27
  57. data/ext/libsass/src/environment.hpp +33 -22
  58. data/ext/libsass/src/error_handling.cpp +92 -94
  59. data/ext/libsass/src/error_handling.hpp +73 -50
  60. data/ext/libsass/src/eval.cpp +380 -515
  61. data/ext/libsass/src/eval.hpp +64 -57
  62. data/ext/libsass/src/eval_selectors.cpp +75 -0
  63. data/ext/libsass/src/expand.cpp +322 -263
  64. data/ext/libsass/src/expand.hpp +55 -39
  65. data/ext/libsass/src/extender.cpp +1188 -0
  66. data/ext/libsass/src/extender.hpp +399 -0
  67. data/ext/libsass/src/extension.cpp +43 -0
  68. data/ext/libsass/src/extension.hpp +89 -0
  69. data/ext/libsass/src/file.cpp +134 -88
  70. data/ext/libsass/src/file.hpp +28 -37
  71. data/ext/libsass/src/fn_colors.cpp +596 -0
  72. data/ext/libsass/src/fn_colors.hpp +85 -0
  73. data/ext/libsass/src/fn_lists.cpp +285 -0
  74. data/ext/libsass/src/fn_lists.hpp +34 -0
  75. data/ext/libsass/src/fn_maps.cpp +94 -0
  76. data/ext/libsass/src/fn_maps.hpp +30 -0
  77. data/ext/libsass/src/fn_miscs.cpp +244 -0
  78. data/ext/libsass/src/fn_miscs.hpp +40 -0
  79. data/ext/libsass/src/fn_numbers.cpp +227 -0
  80. data/ext/libsass/src/fn_numbers.hpp +45 -0
  81. data/ext/libsass/src/fn_selectors.cpp +205 -0
  82. data/ext/libsass/src/fn_selectors.hpp +35 -0
  83. data/ext/libsass/src/fn_strings.cpp +268 -0
  84. data/ext/libsass/src/fn_strings.hpp +34 -0
  85. data/ext/libsass/src/fn_utils.cpp +158 -0
  86. data/ext/libsass/src/fn_utils.hpp +62 -0
  87. data/ext/libsass/src/inspect.cpp +253 -266
  88. data/ext/libsass/src/inspect.hpp +72 -74
  89. data/ext/libsass/src/json.cpp +2 -2
  90. data/ext/libsass/src/lexer.cpp +25 -84
  91. data/ext/libsass/src/lexer.hpp +5 -16
  92. data/ext/libsass/src/listize.cpp +27 -43
  93. data/ext/libsass/src/listize.hpp +14 -11
  94. data/ext/libsass/src/mapping.hpp +1 -0
  95. data/ext/libsass/src/memory.hpp +12 -0
  96. data/ext/libsass/src/memory/allocator.cpp +48 -0
  97. data/ext/libsass/src/memory/allocator.hpp +138 -0
  98. data/ext/libsass/src/memory/config.hpp +20 -0
  99. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  100. data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
  101. data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
  102. data/ext/libsass/src/operation.hpp +193 -143
  103. data/ext/libsass/src/operators.cpp +56 -29
  104. data/ext/libsass/src/operators.hpp +11 -11
  105. data/ext/libsass/src/ordered_map.hpp +112 -0
  106. data/ext/libsass/src/output.cpp +59 -75
  107. data/ext/libsass/src/output.hpp +15 -22
  108. data/ext/libsass/src/parser.cpp +662 -818
  109. data/ext/libsass/src/parser.hpp +96 -100
  110. data/ext/libsass/src/parser_selectors.cpp +189 -0
  111. data/ext/libsass/src/permutate.hpp +164 -0
  112. data/ext/libsass/src/plugins.cpp +12 -8
  113. data/ext/libsass/src/plugins.hpp +8 -8
  114. data/ext/libsass/src/position.cpp +10 -26
  115. data/ext/libsass/src/position.hpp +44 -21
  116. data/ext/libsass/src/prelexer.cpp +14 -8
  117. data/ext/libsass/src/prelexer.hpp +9 -9
  118. data/ext/libsass/src/remove_placeholders.cpp +59 -57
  119. data/ext/libsass/src/remove_placeholders.hpp +20 -18
  120. data/ext/libsass/src/sass.cpp +25 -18
  121. data/ext/libsass/src/sass.hpp +22 -14
  122. data/ext/libsass/src/sass2scss.cpp +49 -18
  123. data/ext/libsass/src/sass_context.cpp +104 -132
  124. data/ext/libsass/src/sass_context.hpp +2 -2
  125. data/ext/libsass/src/sass_functions.cpp +7 -4
  126. data/ext/libsass/src/sass_functions.hpp +1 -1
  127. data/ext/libsass/src/sass_values.cpp +26 -21
  128. data/ext/libsass/src/settings.hpp +19 -0
  129. data/ext/libsass/src/source.cpp +69 -0
  130. data/ext/libsass/src/source.hpp +95 -0
  131. data/ext/libsass/src/source_data.hpp +32 -0
  132. data/ext/libsass/src/source_map.cpp +27 -20
  133. data/ext/libsass/src/source_map.hpp +14 -11
  134. data/ext/libsass/src/stylesheet.cpp +22 -0
  135. data/ext/libsass/src/stylesheet.hpp +57 -0
  136. data/ext/libsass/src/to_value.cpp +24 -22
  137. data/ext/libsass/src/to_value.hpp +18 -22
  138. data/ext/libsass/src/units.cpp +28 -22
  139. data/ext/libsass/src/units.hpp +9 -8
  140. data/ext/libsass/src/utf8/checked.h +12 -10
  141. data/ext/libsass/src/utf8/core.h +3 -0
  142. data/ext/libsass/src/utf8_string.cpp +12 -10
  143. data/ext/libsass/src/utf8_string.hpp +7 -6
  144. data/ext/libsass/src/util.cpp +97 -107
  145. data/ext/libsass/src/util.hpp +74 -30
  146. data/ext/libsass/src/util_string.cpp +125 -0
  147. data/ext/libsass/src/util_string.hpp +73 -0
  148. data/ext/libsass/src/values.cpp +33 -24
  149. data/ext/libsass/src/values.hpp +2 -2
  150. data/lib/sassc.rb +24 -0
  151. data/lib/sassc/engine.rb +7 -5
  152. data/lib/sassc/functions_handler.rb +11 -13
  153. data/lib/sassc/native.rb +10 -9
  154. data/lib/sassc/native/native_functions_api.rb +0 -5
  155. data/lib/sassc/script.rb +4 -6
  156. data/lib/sassc/version.rb +1 -1
  157. data/sassc.gemspec +32 -12
  158. data/test/engine_test.rb +32 -2
  159. data/test/functions_test.rb +38 -1
  160. data/test/native_test.rb +4 -4
  161. metadata +95 -109
  162. data/ext/Rakefile +0 -3
  163. data/ext/libsass/.editorconfig +0 -15
  164. data/ext/libsass/.gitattributes +0 -2
  165. data/ext/libsass/.github/CONTRIBUTING.md +0 -65
  166. data/ext/libsass/.github/ISSUE_TEMPLATE.md +0 -54
  167. data/ext/libsass/.gitignore +0 -85
  168. data/ext/libsass/.travis.yml +0 -64
  169. data/ext/libsass/COPYING +0 -25
  170. data/ext/libsass/GNUmakefile.am +0 -88
  171. data/ext/libsass/INSTALL +0 -1
  172. data/ext/libsass/LICENSE +0 -25
  173. data/ext/libsass/Makefile +0 -351
  174. data/ext/libsass/Makefile.conf +0 -55
  175. data/ext/libsass/Readme.md +0 -104
  176. data/ext/libsass/SECURITY.md +0 -10
  177. data/ext/libsass/appveyor.yml +0 -91
  178. data/ext/libsass/configure.ac +0 -138
  179. data/ext/libsass/contrib/libsass.spec +0 -66
  180. data/ext/libsass/docs/README.md +0 -20
  181. data/ext/libsass/docs/api-context-example.md +0 -45
  182. data/ext/libsass/docs/api-context-internal.md +0 -163
  183. data/ext/libsass/docs/api-context.md +0 -295
  184. data/ext/libsass/docs/api-doc.md +0 -215
  185. data/ext/libsass/docs/api-function-example.md +0 -67
  186. data/ext/libsass/docs/api-function-internal.md +0 -8
  187. data/ext/libsass/docs/api-function.md +0 -74
  188. data/ext/libsass/docs/api-importer-example.md +0 -112
  189. data/ext/libsass/docs/api-importer-internal.md +0 -20
  190. data/ext/libsass/docs/api-importer.md +0 -86
  191. data/ext/libsass/docs/api-value-example.md +0 -55
  192. data/ext/libsass/docs/api-value-internal.md +0 -76
  193. data/ext/libsass/docs/api-value.md +0 -154
  194. data/ext/libsass/docs/build-on-darwin.md +0 -27
  195. data/ext/libsass/docs/build-on-gentoo.md +0 -55
  196. data/ext/libsass/docs/build-on-windows.md +0 -139
  197. data/ext/libsass/docs/build-shared-library.md +0 -35
  198. data/ext/libsass/docs/build-with-autotools.md +0 -78
  199. data/ext/libsass/docs/build-with-makefiles.md +0 -68
  200. data/ext/libsass/docs/build-with-mingw.md +0 -107
  201. data/ext/libsass/docs/build-with-visual-studio.md +0 -90
  202. data/ext/libsass/docs/build.md +0 -97
  203. data/ext/libsass/docs/compatibility-plan.md +0 -48
  204. data/ext/libsass/docs/contributing.md +0 -17
  205. data/ext/libsass/docs/custom-functions-internal.md +0 -122
  206. data/ext/libsass/docs/dev-ast-memory.md +0 -223
  207. data/ext/libsass/docs/implementations.md +0 -56
  208. data/ext/libsass/docs/plugins.md +0 -47
  209. data/ext/libsass/docs/setup-environment.md +0 -68
  210. data/ext/libsass/docs/source-map-internals.md +0 -51
  211. data/ext/libsass/docs/trace.md +0 -26
  212. data/ext/libsass/docs/triage.md +0 -17
  213. data/ext/libsass/docs/unicode.md +0 -39
  214. data/ext/libsass/extconf.rb +0 -6
  215. data/ext/libsass/include/sass/version.h.in +0 -12
  216. data/ext/libsass/m4/.gitkeep +0 -0
  217. data/ext/libsass/m4/m4-ax_cxx_compile_stdcxx_11.m4 +0 -167
  218. data/ext/libsass/res/resource.rc +0 -35
  219. data/ext/libsass/script/bootstrap +0 -13
  220. data/ext/libsass/script/branding +0 -10
  221. data/ext/libsass/script/ci-build-libsass +0 -134
  222. data/ext/libsass/script/ci-build-plugin +0 -62
  223. data/ext/libsass/script/ci-install-compiler +0 -6
  224. data/ext/libsass/script/ci-install-deps +0 -20
  225. data/ext/libsass/script/ci-report-coverage +0 -42
  226. data/ext/libsass/script/spec +0 -5
  227. data/ext/libsass/script/tap-driver +0 -652
  228. data/ext/libsass/script/tap-runner +0 -1
  229. data/ext/libsass/script/test-leaks.pl +0 -103
  230. data/ext/libsass/src/GNUmakefile.am +0 -54
  231. data/ext/libsass/src/extend.cpp +0 -2130
  232. data/ext/libsass/src/extend.hpp +0 -86
  233. data/ext/libsass/src/functions.cpp +0 -2234
  234. data/ext/libsass/src/functions.hpp +0 -198
  235. data/ext/libsass/src/memory/SharedPtr.cpp +0 -114
  236. data/ext/libsass/src/memory/SharedPtr.hpp +0 -206
  237. data/ext/libsass/src/node.cpp +0 -319
  238. data/ext/libsass/src/node.hpp +0 -118
  239. data/ext/libsass/src/paths.hpp +0 -71
  240. data/ext/libsass/src/sass_util.cpp +0 -149
  241. data/ext/libsass/src/sass_util.hpp +0 -256
  242. data/ext/libsass/src/subset_map.cpp +0 -55
  243. data/ext/libsass/src/subset_map.hpp +0 -76
  244. data/ext/libsass/src/support/libsass.pc.in +0 -11
  245. data/ext/libsass/src/to_c.hpp +0 -39
  246. data/ext/libsass/test/test_node.cpp +0 -94
  247. data/ext/libsass/test/test_paths.cpp +0 -28
  248. data/ext/libsass/test/test_selector_difference.cpp +0 -25
  249. data/ext/libsass/test/test_specificity.cpp +0 -25
  250. data/ext/libsass/test/test_subset_map.cpp +0 -472
  251. data/ext/libsass/test/test_superselector.cpp +0 -69
  252. data/ext/libsass/test/test_unification.cpp +0 -31
  253. data/ext/libsass/version.sh +0 -10
  254. data/ext/libsass/win/libsass.sln +0 -39
  255. data/ext/libsass/win/libsass.sln.DotSettings +0 -9
  256. data/ext/libsass/win/libsass.targets +0 -118
  257. data/ext/libsass/win/libsass.vcxproj +0 -188
  258. data/ext/libsass/win/libsass.vcxproj.filters +0 -357
  259. data/lib/sassc/native/lib_c.rb +0 -21
  260. data/lib/tasks/libsass.rb +0 -33
@@ -0,0 +1,275 @@
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
+
7
+ namespace Sass {
8
+
9
+ // ##########################################################################
10
+ // Returns the contents of a [SelectorList] that matches only
11
+ // elements that are matched by both [complex1] and [complex2].
12
+ // If no such list can be produced, returns `null`.
13
+ // ##########################################################################
14
+ // ToDo: fine-tune API to avoid unnecessary wrapper allocations
15
+ // ##########################################################################
16
+ sass::vector<sass::vector<SelectorComponentObj>> unifyComplex(
17
+ const sass::vector<sass::vector<SelectorComponentObj>>& complexes)
18
+ {
19
+
20
+ SASS_ASSERT(!complexes.empty(), "Can't unify empty list");
21
+ if (complexes.size() == 1) return complexes;
22
+
23
+ CompoundSelectorObj unifiedBase = SASS_MEMORY_NEW(CompoundSelector, SourceSpan("[phony]"));
24
+ for (auto complex : complexes) {
25
+ SelectorComponentObj base = complex.back();
26
+ if (CompoundSelector * comp = base->getCompound()) {
27
+ if (unifiedBase->empty()) {
28
+ unifiedBase->concat(comp);
29
+ }
30
+ else {
31
+ for (SimpleSelectorObj simple : comp->elements()) {
32
+ unifiedBase = simple->unifyWith(unifiedBase);
33
+ if (unifiedBase.isNull()) return {};
34
+ }
35
+ }
36
+ }
37
+ else {
38
+ return {};
39
+ }
40
+ }
41
+
42
+ sass::vector<sass::vector<SelectorComponentObj>> complexesWithoutBases;
43
+ for (size_t i = 0; i < complexes.size(); i += 1) {
44
+ sass::vector<SelectorComponentObj> sel = complexes[i];
45
+ sel.pop_back(); // remove last item (base) from the list
46
+ complexesWithoutBases.push_back(std::move(sel));
47
+ }
48
+
49
+ complexesWithoutBases.back().push_back(unifiedBase);
50
+
51
+ return weave(complexesWithoutBases);
52
+
53
+ }
54
+ // EO unifyComplex
55
+
56
+ // ##########################################################################
57
+ // Returns a [CompoundSelector] that matches only elements
58
+ // that are matched by both [compound1] and [compound2].
59
+ // If no such selector can be produced, returns `null`.
60
+ // ##########################################################################
61
+ CompoundSelector* CompoundSelector::unifyWith(CompoundSelector* rhs)
62
+ {
63
+ if (empty()) return rhs;
64
+ CompoundSelectorObj unified = SASS_MEMORY_COPY(rhs);
65
+ for (const SimpleSelectorObj& sel : elements()) {
66
+ unified = sel->unifyWith(unified);
67
+ if (unified.isNull()) break;
68
+ }
69
+ return unified.detach();
70
+ }
71
+ // EO CompoundSelector::unifyWith(CompoundSelector*)
72
+
73
+ // ##########################################################################
74
+ // Returns the compoments of a [CompoundSelector] that matches only elements
75
+ // matched by both this and [compound]. By default, this just returns a copy
76
+ // of [compound] with this selector added to the end, or returns the original
77
+ // array if this selector already exists in it. Returns `null` if unification
78
+ // is impossible—for example, if there are multiple ID selectors.
79
+ // ##########################################################################
80
+ // This is implemented in `selector/simple.dart` as `SimpleSelector::unify`
81
+ // ##########################################################################
82
+ CompoundSelector* SimpleSelector::unifyWith(CompoundSelector* rhs)
83
+ {
84
+
85
+ if (rhs->length() == 1) {
86
+ if (rhs->get(0)->is_universal()) {
87
+ CompoundSelector* this_compound = SASS_MEMORY_NEW(CompoundSelector, pstate());
88
+ this_compound->append(SASS_MEMORY_COPY(this));
89
+ CompoundSelector* unified = rhs->get(0)->unifyWith(this_compound);
90
+ if (unified == nullptr || unified != this_compound) delete this_compound;
91
+ return unified;
92
+ }
93
+ }
94
+ for (const SimpleSelectorObj& sel : rhs->elements()) {
95
+ if (*this == *sel) {
96
+ return rhs;
97
+ }
98
+ }
99
+
100
+ CompoundSelectorObj result = SASS_MEMORY_NEW(CompoundSelector, rhs->pstate());
101
+
102
+ bool addedThis = false;
103
+ for (auto simple : rhs->elements()) {
104
+ // Make sure pseudo selectors always come last.
105
+ if (!addedThis && simple->getPseudoSelector()) {
106
+ result->append(this);
107
+ addedThis = true;
108
+ }
109
+ result->append(simple);
110
+ }
111
+
112
+ if (!addedThis) {
113
+ result->append(this);
114
+ }
115
+ return result.detach();
116
+
117
+ }
118
+ // EO SimpleSelector::unifyWith(CompoundSelector*)
119
+
120
+ // ##########################################################################
121
+ // This is implemented in `selector/type.dart` as `PseudoSelector::unify`
122
+ // ##########################################################################
123
+ CompoundSelector* TypeSelector::unifyWith(CompoundSelector* rhs)
124
+ {
125
+ if (rhs->empty()) {
126
+ rhs->append(this);
127
+ return rhs;
128
+ }
129
+ TypeSelector* type = Cast<TypeSelector>(rhs->at(0));
130
+ if (type != nullptr) {
131
+ SimpleSelector* unified = unifyWith(type);
132
+ if (unified == nullptr) {
133
+ return nullptr;
134
+ }
135
+ rhs->elements()[0] = unified;
136
+ }
137
+ else if (!is_universal() || (has_ns_ && ns_ != "*")) {
138
+ rhs->insert(rhs->begin(), this);
139
+ }
140
+ return rhs;
141
+ }
142
+
143
+ // ##########################################################################
144
+ // This is implemented in `selector/id.dart` as `PseudoSelector::unify`
145
+ // ##########################################################################
146
+ CompoundSelector* IDSelector::unifyWith(CompoundSelector* rhs)
147
+ {
148
+ for (const SimpleSelector* sel : rhs->elements()) {
149
+ if (const IDSelector* id_sel = Cast<IDSelector>(sel)) {
150
+ if (id_sel->name() != name()) return nullptr;
151
+ }
152
+ }
153
+ return SimpleSelector::unifyWith(rhs);
154
+ }
155
+
156
+ // ##########################################################################
157
+ // This is implemented in `selector/pseudo.dart` as `PseudoSelector::unify`
158
+ // ##########################################################################
159
+ CompoundSelector* PseudoSelector::unifyWith(CompoundSelector* compound)
160
+ {
161
+
162
+ if (compound->length() == 1 && compound->first()->is_universal()) {
163
+ // std::cerr << "implement universal pseudo\n";
164
+ }
165
+
166
+ for (const SimpleSelectorObj& sel : compound->elements()) {
167
+ if (*this == *sel) {
168
+ return compound;
169
+ }
170
+ }
171
+
172
+ CompoundSelectorObj result = SASS_MEMORY_NEW(CompoundSelector, compound->pstate());
173
+
174
+ bool addedThis = false;
175
+ for (auto simple : compound->elements()) {
176
+ // Make sure pseudo selectors always come last.
177
+ if (PseudoSelectorObj pseudo = simple->getPseudoSelector()) {
178
+ if (pseudo->isElement()) {
179
+ // A given compound selector may only contain one pseudo element. If
180
+ // [compound] has a different one than [this], unification fails.
181
+ if (isElement()) {
182
+ return {};
183
+ }
184
+ // Otherwise, this is a pseudo selector and
185
+ // should come before pseduo elements.
186
+ result->append(this);
187
+ addedThis = true;
188
+ }
189
+ }
190
+ result->append(simple);
191
+ }
192
+
193
+ if (!addedThis) {
194
+ result->append(this);
195
+ }
196
+
197
+ return result.detach();
198
+
199
+ }
200
+ // EO PseudoSelector::unifyWith(CompoundSelector*
201
+
202
+ // ##########################################################################
203
+ // This is implemented in `extend/functions.dart` as `unifyUniversalAndElement`
204
+ // Returns a [SimpleSelector] that matches only elements that are matched by
205
+ // both [selector1] and [selector2], which must both be either [UniversalSelector]s
206
+ // or [TypeSelector]s. If no such selector can be produced, returns `null`.
207
+ // Note: libsass handles universal selector directly within the type selector
208
+ // ##########################################################################
209
+ SimpleSelector* TypeSelector::unifyWith(const SimpleSelector* rhs)
210
+ {
211
+ bool rhs_ns = false;
212
+ if (!(is_ns_eq(*rhs) || rhs->is_universal_ns())) {
213
+ if (!is_universal_ns()) {
214
+ return nullptr;
215
+ }
216
+ rhs_ns = true;
217
+ }
218
+ bool rhs_name = false;
219
+ if (!(name_ == rhs->name() || rhs->is_universal())) {
220
+ if (!(is_universal())) {
221
+ return nullptr;
222
+ }
223
+ rhs_name = true;
224
+ }
225
+ if (rhs_ns) {
226
+ ns(rhs->ns());
227
+ has_ns(rhs->has_ns());
228
+ }
229
+ if (rhs_name) name(rhs->name());
230
+ return this;
231
+ }
232
+ // EO TypeSelector::unifyWith(const SimpleSelector*)
233
+
234
+ // ##########################################################################
235
+ // Unify two complex selectors. Internally calls `unifyComplex`
236
+ // and then wraps the result in newly create ComplexSelectors.
237
+ // ##########################################################################
238
+ SelectorList* ComplexSelector::unifyWith(ComplexSelector* rhs)
239
+ {
240
+ SelectorListObj list = SASS_MEMORY_NEW(SelectorList, pstate());
241
+ sass::vector<sass::vector<SelectorComponentObj>> rv =
242
+ unifyComplex({ elements(), rhs->elements() });
243
+ for (sass::vector<SelectorComponentObj> items : rv) {
244
+ ComplexSelectorObj sel = SASS_MEMORY_NEW(ComplexSelector, pstate());
245
+ sel->elements() = std::move(items);
246
+ list->append(sel);
247
+ }
248
+ return list.detach();
249
+ }
250
+ // EO ComplexSelector::unifyWith(ComplexSelector*)
251
+
252
+ // ##########################################################################
253
+ // only called from the sass function `selector-unify`
254
+ // ##########################################################################
255
+ SelectorList* SelectorList::unifyWith(SelectorList* rhs)
256
+ {
257
+ SelectorList* slist = SASS_MEMORY_NEW(SelectorList, pstate());
258
+ // Unify all of children with RHS's children,
259
+ // storing the results in `unified_complex_selectors`
260
+ for (ComplexSelectorObj& seq1 : elements()) {
261
+ for (ComplexSelectorObj& seq2 : rhs->elements()) {
262
+ if (SelectorListObj unified = seq1->unifyWith(seq2)) {
263
+ std::move(unified->begin(), unified->end(),
264
+ std::inserter(slist->elements(), slist->end()));
265
+ }
266
+ }
267
+ }
268
+ return slist;
269
+ }
270
+ // EO SelectorList::unifyWith(SelectorList*)
271
+
272
+ // ##########################################################################
273
+ // ##########################################################################
274
+
275
+ }
@@ -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
+ }