sassc4 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +16 -0
  5. data/CHANGELOG.md +97 -0
  6. data/CODE_OF_CONDUCT.md +10 -0
  7. data/Gemfile +2 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +80 -0
  10. data/Rakefile +51 -0
  11. data/ext/depend +4 -0
  12. data/ext/extconf.rb +92 -0
  13. data/ext/libsass/VERSION +1 -0
  14. data/ext/libsass/contrib/plugin.cpp +60 -0
  15. data/ext/libsass/include/sass/base.h +97 -0
  16. data/ext/libsass/include/sass/context.h +174 -0
  17. data/ext/libsass/include/sass/functions.h +139 -0
  18. data/ext/libsass/include/sass/values.h +145 -0
  19. data/ext/libsass/include/sass/version.h +12 -0
  20. data/ext/libsass/include/sass.h +15 -0
  21. data/ext/libsass/include/sass2scss.h +120 -0
  22. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  23. data/ext/libsass/src/ast.cpp +953 -0
  24. data/ext/libsass/src/ast.hpp +1064 -0
  25. data/ext/libsass/src/ast2c.cpp +80 -0
  26. data/ext/libsass/src/ast2c.hpp +39 -0
  27. data/ext/libsass/src/ast_def_macros.hpp +140 -0
  28. data/ext/libsass/src/ast_fwd_decl.cpp +31 -0
  29. data/ext/libsass/src/ast_fwd_decl.hpp +274 -0
  30. data/ext/libsass/src/ast_helpers.hpp +316 -0
  31. data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
  32. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  33. data/ext/libsass/src/ast_sel_unify.cpp +275 -0
  34. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  35. data/ext/libsass/src/ast_selectors.cpp +1070 -0
  36. data/ext/libsass/src/ast_selectors.hpp +523 -0
  37. data/ext/libsass/src/ast_supports.cpp +114 -0
  38. data/ext/libsass/src/ast_supports.hpp +121 -0
  39. data/ext/libsass/src/ast_values.cpp +1154 -0
  40. data/ext/libsass/src/ast_values.hpp +498 -0
  41. data/ext/libsass/src/b64/cencode.h +32 -0
  42. data/ext/libsass/src/b64/encode.h +79 -0
  43. data/ext/libsass/src/backtrace.cpp +50 -0
  44. data/ext/libsass/src/backtrace.hpp +29 -0
  45. data/ext/libsass/src/base64vlq.cpp +47 -0
  46. data/ext/libsass/src/base64vlq.hpp +30 -0
  47. data/ext/libsass/src/bind.cpp +312 -0
  48. data/ext/libsass/src/bind.hpp +15 -0
  49. data/ext/libsass/src/c2ast.cpp +64 -0
  50. data/ext/libsass/src/c2ast.hpp +14 -0
  51. data/ext/libsass/src/c99func.c +54 -0
  52. data/ext/libsass/src/cencode.c +106 -0
  53. data/ext/libsass/src/check_nesting.cpp +393 -0
  54. data/ext/libsass/src/check_nesting.hpp +70 -0
  55. data/ext/libsass/src/color_maps.cpp +652 -0
  56. data/ext/libsass/src/color_maps.hpp +323 -0
  57. data/ext/libsass/src/color_spaces.cpp +241 -0
  58. data/ext/libsass/src/color_spaces.hpp +227 -0
  59. data/ext/libsass/src/constants.cpp +199 -0
  60. data/ext/libsass/src/constants.hpp +200 -0
  61. data/ext/libsass/src/context.cpp +870 -0
  62. data/ext/libsass/src/context.hpp +140 -0
  63. data/ext/libsass/src/cssize.cpp +521 -0
  64. data/ext/libsass/src/cssize.hpp +71 -0
  65. data/ext/libsass/src/dart_helpers.hpp +199 -0
  66. data/ext/libsass/src/debug.hpp +43 -0
  67. data/ext/libsass/src/debugger.hpp +964 -0
  68. data/ext/libsass/src/emitter.cpp +297 -0
  69. data/ext/libsass/src/emitter.hpp +101 -0
  70. data/ext/libsass/src/environment.cpp +260 -0
  71. data/ext/libsass/src/environment.hpp +124 -0
  72. data/ext/libsass/src/error_handling.cpp +239 -0
  73. data/ext/libsass/src/error_handling.hpp +248 -0
  74. data/ext/libsass/src/eval.cpp +1543 -0
  75. data/ext/libsass/src/eval.hpp +110 -0
  76. data/ext/libsass/src/eval_selectors.cpp +75 -0
  77. data/ext/libsass/src/expand.cpp +875 -0
  78. data/ext/libsass/src/expand.hpp +98 -0
  79. data/ext/libsass/src/extender.cpp +1226 -0
  80. data/ext/libsass/src/extender.hpp +399 -0
  81. data/ext/libsass/src/extension.cpp +43 -0
  82. data/ext/libsass/src/extension.hpp +89 -0
  83. data/ext/libsass/src/file.cpp +531 -0
  84. data/ext/libsass/src/file.hpp +124 -0
  85. data/ext/libsass/src/fn_colors.cpp +836 -0
  86. data/ext/libsass/src/fn_colors.hpp +99 -0
  87. data/ext/libsass/src/fn_lists.cpp +285 -0
  88. data/ext/libsass/src/fn_lists.hpp +34 -0
  89. data/ext/libsass/src/fn_maps.cpp +94 -0
  90. data/ext/libsass/src/fn_maps.hpp +30 -0
  91. data/ext/libsass/src/fn_miscs.cpp +248 -0
  92. data/ext/libsass/src/fn_miscs.hpp +40 -0
  93. data/ext/libsass/src/fn_numbers.cpp +246 -0
  94. data/ext/libsass/src/fn_numbers.hpp +45 -0
  95. data/ext/libsass/src/fn_selectors.cpp +205 -0
  96. data/ext/libsass/src/fn_selectors.hpp +35 -0
  97. data/ext/libsass/src/fn_strings.cpp +268 -0
  98. data/ext/libsass/src/fn_strings.hpp +34 -0
  99. data/ext/libsass/src/fn_utils.cpp +159 -0
  100. data/ext/libsass/src/fn_utils.hpp +62 -0
  101. data/ext/libsass/src/inspect.cpp +1126 -0
  102. data/ext/libsass/src/inspect.hpp +101 -0
  103. data/ext/libsass/src/json.cpp +1436 -0
  104. data/ext/libsass/src/json.hpp +117 -0
  105. data/ext/libsass/src/kwd_arg_macros.hpp +28 -0
  106. data/ext/libsass/src/lexer.cpp +122 -0
  107. data/ext/libsass/src/lexer.hpp +304 -0
  108. data/ext/libsass/src/listize.cpp +70 -0
  109. data/ext/libsass/src/listize.hpp +37 -0
  110. data/ext/libsass/src/mapping.hpp +19 -0
  111. data/ext/libsass/src/memory/allocator.cpp +48 -0
  112. data/ext/libsass/src/memory/allocator.hpp +138 -0
  113. data/ext/libsass/src/memory/config.hpp +20 -0
  114. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  115. data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
  116. data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
  117. data/ext/libsass/src/memory.hpp +12 -0
  118. data/ext/libsass/src/operation.hpp +223 -0
  119. data/ext/libsass/src/operators.cpp +267 -0
  120. data/ext/libsass/src/operators.hpp +30 -0
  121. data/ext/libsass/src/ordered_map.hpp +112 -0
  122. data/ext/libsass/src/output.cpp +320 -0
  123. data/ext/libsass/src/output.hpp +47 -0
  124. data/ext/libsass/src/parser.cpp +3059 -0
  125. data/ext/libsass/src/parser.hpp +395 -0
  126. data/ext/libsass/src/parser_selectors.cpp +189 -0
  127. data/ext/libsass/src/permutate.hpp +164 -0
  128. data/ext/libsass/src/plugins.cpp +188 -0
  129. data/ext/libsass/src/plugins.hpp +57 -0
  130. data/ext/libsass/src/position.cpp +163 -0
  131. data/ext/libsass/src/position.hpp +147 -0
  132. data/ext/libsass/src/prelexer.cpp +1780 -0
  133. data/ext/libsass/src/prelexer.hpp +484 -0
  134. data/ext/libsass/src/remove_placeholders.cpp +86 -0
  135. data/ext/libsass/src/remove_placeholders.hpp +37 -0
  136. data/ext/libsass/src/sass.cpp +156 -0
  137. data/ext/libsass/src/sass.hpp +147 -0
  138. data/ext/libsass/src/sass2scss.cpp +895 -0
  139. data/ext/libsass/src/sass_context.cpp +742 -0
  140. data/ext/libsass/src/sass_context.hpp +129 -0
  141. data/ext/libsass/src/sass_functions.cpp +210 -0
  142. data/ext/libsass/src/sass_functions.hpp +50 -0
  143. data/ext/libsass/src/sass_values.cpp +362 -0
  144. data/ext/libsass/src/sass_values.hpp +82 -0
  145. data/ext/libsass/src/settings.hpp +19 -0
  146. data/ext/libsass/src/source.cpp +69 -0
  147. data/ext/libsass/src/source.hpp +95 -0
  148. data/ext/libsass/src/source_data.hpp +32 -0
  149. data/ext/libsass/src/source_map.cpp +202 -0
  150. data/ext/libsass/src/source_map.hpp +65 -0
  151. data/ext/libsass/src/stylesheet.cpp +22 -0
  152. data/ext/libsass/src/stylesheet.hpp +57 -0
  153. data/ext/libsass/src/to_value.cpp +114 -0
  154. data/ext/libsass/src/to_value.hpp +46 -0
  155. data/ext/libsass/src/units.cpp +507 -0
  156. data/ext/libsass/src/units.hpp +110 -0
  157. data/ext/libsass/src/utf8/checked.h +336 -0
  158. data/ext/libsass/src/utf8/core.h +332 -0
  159. data/ext/libsass/src/utf8/unchecked.h +235 -0
  160. data/ext/libsass/src/utf8.h +34 -0
  161. data/ext/libsass/src/utf8_string.cpp +104 -0
  162. data/ext/libsass/src/utf8_string.hpp +38 -0
  163. data/ext/libsass/src/util.cpp +723 -0
  164. data/ext/libsass/src/util.hpp +105 -0
  165. data/ext/libsass/src/util_string.cpp +125 -0
  166. data/ext/libsass/src/util_string.hpp +73 -0
  167. data/ext/libsass/src/values.cpp +140 -0
  168. data/ext/libsass/src/values.hpp +12 -0
  169. data/lib/sassc/dependency.rb +17 -0
  170. data/lib/sassc/engine.rb +141 -0
  171. data/lib/sassc/error.rb +37 -0
  172. data/lib/sassc/functions_handler.rb +73 -0
  173. data/lib/sassc/import_handler.rb +50 -0
  174. data/lib/sassc/importer.rb +31 -0
  175. data/lib/sassc/native/native_context_api.rb +147 -0
  176. data/lib/sassc/native/native_functions_api.rb +159 -0
  177. data/lib/sassc/native/sass2scss_api.rb +10 -0
  178. data/lib/sassc/native/sass_input_style.rb +13 -0
  179. data/lib/sassc/native/sass_output_style.rb +12 -0
  180. data/lib/sassc/native/sass_value.rb +97 -0
  181. data/lib/sassc/native/string_list.rb +10 -0
  182. data/lib/sassc/native.rb +64 -0
  183. data/lib/sassc/sass_2_scss.rb +9 -0
  184. data/lib/sassc/script/functions.rb +8 -0
  185. data/lib/sassc/script/value/bool.rb +32 -0
  186. data/lib/sassc/script/value/color.rb +95 -0
  187. data/lib/sassc/script/value/list.rb +136 -0
  188. data/lib/sassc/script/value/map.rb +69 -0
  189. data/lib/sassc/script/value/number.rb +389 -0
  190. data/lib/sassc/script/value/string.rb +96 -0
  191. data/lib/sassc/script/value.rb +137 -0
  192. data/lib/sassc/script/value_conversion/base.rb +13 -0
  193. data/lib/sassc/script/value_conversion/bool.rb +13 -0
  194. data/lib/sassc/script/value_conversion/color.rb +18 -0
  195. data/lib/sassc/script/value_conversion/list.rb +25 -0
  196. data/lib/sassc/script/value_conversion/map.rb +21 -0
  197. data/lib/sassc/script/value_conversion/number.rb +13 -0
  198. data/lib/sassc/script/value_conversion/string.rb +17 -0
  199. data/lib/sassc/script/value_conversion.rb +69 -0
  200. data/lib/sassc/script.rb +17 -0
  201. data/lib/sassc/util/normalized_map.rb +117 -0
  202. data/lib/sassc/util.rb +231 -0
  203. data/lib/sassc/version.rb +5 -0
  204. data/lib/sassc.rb +57 -0
  205. data/sassc.gemspec +69 -0
  206. data/test/css_color_level4_test.rb +168 -0
  207. data/test/custom_importer_test.rb +127 -0
  208. data/test/engine_test.rb +314 -0
  209. data/test/error_test.rb +29 -0
  210. data/test/fixtures/paths.scss +10 -0
  211. data/test/functions_test.rb +340 -0
  212. data/test/native_test.rb +213 -0
  213. data/test/output_style_test.rb +107 -0
  214. data/test/sass_2_scss_test.rb +14 -0
  215. data/test/test_helper.rb +45 -0
  216. metadata +396 -0
@@ -0,0 +1,1126 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
3
+ #include "sass.hpp"
4
+
5
+ #include <cmath>
6
+ #include <string>
7
+ #include <iostream>
8
+ #include <iomanip>
9
+ #include <stdint.h>
10
+ #include <stdint.h>
11
+
12
+ #include "ast.hpp"
13
+ #include "inspect.hpp"
14
+ #include "context.hpp"
15
+ #include "listize.hpp"
16
+ #include "color_maps.hpp"
17
+ #include "utf8/checked.h"
18
+
19
+ namespace Sass {
20
+
21
+ Inspect::Inspect(const Emitter& emi)
22
+ : Emitter(emi)
23
+ { }
24
+ Inspect::~Inspect() { }
25
+
26
+ // statements
27
+ void Inspect::operator()(Block* block)
28
+ {
29
+ if (!block->is_root()) {
30
+ add_open_mapping(block);
31
+ append_scope_opener();
32
+ }
33
+ if (output_style() == NESTED) indentation += block->tabs();
34
+ for (size_t i = 0, L = block->length(); i < L; ++i) {
35
+ (*block)[i]->perform(this);
36
+ }
37
+ if (output_style() == NESTED) indentation -= block->tabs();
38
+ if (!block->is_root()) {
39
+ append_scope_closer();
40
+ add_close_mapping(block);
41
+ }
42
+
43
+ }
44
+
45
+ void Inspect::operator()(StyleRule* ruleset)
46
+ {
47
+ if (ruleset->selector()) {
48
+ ruleset->selector()->perform(this);
49
+ }
50
+ if (ruleset->block()) {
51
+ ruleset->block()->perform(this);
52
+ }
53
+ }
54
+
55
+ void Inspect::operator()(Keyframe_Rule* rule)
56
+ {
57
+ if (rule->name()) rule->name()->perform(this);
58
+ if (rule->block()) rule->block()->perform(this);
59
+ }
60
+
61
+ void Inspect::operator()(Bubble* bubble)
62
+ {
63
+ append_indentation();
64
+ append_token("::BUBBLE", bubble);
65
+ append_scope_opener();
66
+ bubble->node()->perform(this);
67
+ append_scope_closer();
68
+ }
69
+
70
+ void Inspect::operator()(MediaRule* rule)
71
+ {
72
+ append_indentation();
73
+ append_token("@media", rule);
74
+ append_mandatory_space();
75
+ if (rule->block()) {
76
+ rule->block()->perform(this);
77
+ }
78
+ }
79
+
80
+ void Inspect::operator()(CssMediaRule* rule)
81
+ {
82
+ if (output_style() == NESTED)
83
+ indentation += rule->tabs();
84
+ append_indentation();
85
+ append_token("@media", rule);
86
+ append_mandatory_space();
87
+ in_media_block = true;
88
+ bool joinIt = false;
89
+ for (auto query : rule->elements()) {
90
+ if (joinIt) {
91
+ append_comma_separator();
92
+ append_optional_space();
93
+ }
94
+ operator()(query);
95
+ joinIt = true;
96
+ }
97
+ if (rule->block()) {
98
+ rule->block()->perform(this);
99
+ }
100
+ in_media_block = false;
101
+ if (output_style() == NESTED)
102
+ indentation -= rule->tabs();
103
+ }
104
+
105
+ void Inspect::operator()(CssMediaQuery* query)
106
+ {
107
+ bool joinIt = false;
108
+ if (!query->modifier().empty()) {
109
+ append_string(query->modifier());
110
+ append_mandatory_space();
111
+ }
112
+ if (!query->type().empty()) {
113
+ append_string(query->type());
114
+ joinIt = true;
115
+ }
116
+ for (auto feature : query->features()) {
117
+ if (joinIt) {
118
+ append_mandatory_space();
119
+ append_string("and");
120
+ append_mandatory_space();
121
+ }
122
+ append_string(feature);
123
+ joinIt = true;
124
+ }
125
+ }
126
+
127
+ void Inspect::operator()(SupportsRule* feature_block)
128
+ {
129
+ append_indentation();
130
+ append_token("@supports", feature_block);
131
+ append_mandatory_space();
132
+ feature_block->condition()->perform(this);
133
+ feature_block->block()->perform(this);
134
+ }
135
+
136
+ void Inspect::operator()(AtRootRule* at_root_block)
137
+ {
138
+ append_indentation();
139
+ append_token("@at-root ", at_root_block);
140
+ append_mandatory_space();
141
+ if(at_root_block->expression()) at_root_block->expression()->perform(this);
142
+ if(at_root_block->block()) at_root_block->block()->perform(this);
143
+ }
144
+
145
+ void Inspect::operator()(AtRule* at_rule)
146
+ {
147
+ append_indentation();
148
+ append_token(at_rule->keyword(), at_rule);
149
+ if (at_rule->selector()) {
150
+ append_mandatory_space();
151
+ bool was_wrapped = in_wrapped;
152
+ in_wrapped = true;
153
+ at_rule->selector()->perform(this);
154
+ in_wrapped = was_wrapped;
155
+ }
156
+ if (at_rule->value()) {
157
+ append_mandatory_space();
158
+ at_rule->value()->perform(this);
159
+ }
160
+ if (at_rule->block()) {
161
+ at_rule->block()->perform(this);
162
+ }
163
+ else {
164
+ append_delimiter();
165
+ }
166
+ }
167
+
168
+ void Inspect::operator()(Declaration* dec)
169
+ {
170
+ if (dec->value()->concrete_type() == Expression::NULL_VAL) return;
171
+ bool was_decl = in_declaration;
172
+ in_declaration = true;
173
+ LOCAL_FLAG(in_custom_property, dec->is_custom_property());
174
+
175
+ if (output_style() == NESTED)
176
+ indentation += dec->tabs();
177
+ append_indentation();
178
+ if (dec->property())
179
+ dec->property()->perform(this);
180
+ append_colon_separator();
181
+
182
+ if (dec->value()->concrete_type() == Expression::SELECTOR) {
183
+ ExpressionObj ls = Listize::perform(dec->value());
184
+ ls->perform(this);
185
+ } else {
186
+ dec->value()->perform(this);
187
+ }
188
+
189
+ if (dec->is_important()) {
190
+ append_optional_space();
191
+ append_string("!important");
192
+ }
193
+ append_delimiter();
194
+ if (output_style() == NESTED)
195
+ indentation -= dec->tabs();
196
+ in_declaration = was_decl;
197
+ }
198
+
199
+ void Inspect::operator()(Assignment* assn)
200
+ {
201
+ append_token(assn->variable(), assn);
202
+ append_colon_separator();
203
+ assn->value()->perform(this);
204
+ if (assn->is_default()) {
205
+ append_optional_space();
206
+ append_string("!default");
207
+ }
208
+ append_delimiter();
209
+ }
210
+
211
+ void Inspect::operator()(Import* import)
212
+ {
213
+ if (!import->urls().empty()) {
214
+ append_token("@import", import);
215
+ append_mandatory_space();
216
+
217
+ import->urls().front()->perform(this);
218
+ if (import->urls().size() == 1) {
219
+ if (import->import_queries()) {
220
+ append_mandatory_space();
221
+ import->import_queries()->perform(this);
222
+ }
223
+ }
224
+ append_delimiter();
225
+ for (size_t i = 1, S = import->urls().size(); i < S; ++i) {
226
+ append_mandatory_linefeed();
227
+ append_token("@import", import);
228
+ append_mandatory_space();
229
+
230
+ import->urls()[i]->perform(this);
231
+ if (import->urls().size() - 1 == i) {
232
+ if (import->import_queries()) {
233
+ append_mandatory_space();
234
+ import->import_queries()->perform(this);
235
+ }
236
+ }
237
+ append_delimiter();
238
+ }
239
+ }
240
+ }
241
+
242
+ void Inspect::operator()(Import_Stub* import)
243
+ {
244
+ append_indentation();
245
+ append_token("@import", import);
246
+ append_mandatory_space();
247
+ append_string(import->imp_path());
248
+ append_delimiter();
249
+ }
250
+
251
+ void Inspect::operator()(WarningRule* warning)
252
+ {
253
+ append_indentation();
254
+ append_token("@warn", warning);
255
+ append_mandatory_space();
256
+ warning->message()->perform(this);
257
+ append_delimiter();
258
+ }
259
+
260
+ void Inspect::operator()(ErrorRule* error)
261
+ {
262
+ append_indentation();
263
+ append_token("@error", error);
264
+ append_mandatory_space();
265
+ error->message()->perform(this);
266
+ append_delimiter();
267
+ }
268
+
269
+ void Inspect::operator()(DebugRule* debug)
270
+ {
271
+ append_indentation();
272
+ append_token("@debug", debug);
273
+ append_mandatory_space();
274
+ debug->value()->perform(this);
275
+ append_delimiter();
276
+ }
277
+
278
+ void Inspect::operator()(Comment* comment)
279
+ {
280
+ in_comment = true;
281
+ comment->text()->perform(this);
282
+ in_comment = false;
283
+ }
284
+
285
+ void Inspect::operator()(If* cond)
286
+ {
287
+ append_indentation();
288
+ append_token("@if", cond);
289
+ append_mandatory_space();
290
+ cond->predicate()->perform(this);
291
+ cond->block()->perform(this);
292
+ if (cond->alternative()) {
293
+ append_optional_linefeed();
294
+ append_indentation();
295
+ append_string("else");
296
+ cond->alternative()->perform(this);
297
+ }
298
+ }
299
+
300
+ void Inspect::operator()(ForRule* loop)
301
+ {
302
+ append_indentation();
303
+ append_token("@for", loop);
304
+ append_mandatory_space();
305
+ append_string(loop->variable());
306
+ append_string(" from ");
307
+ loop->lower_bound()->perform(this);
308
+ append_string(loop->is_inclusive() ? " through " : " to ");
309
+ loop->upper_bound()->perform(this);
310
+ loop->block()->perform(this);
311
+ }
312
+
313
+ void Inspect::operator()(EachRule* loop)
314
+ {
315
+ append_indentation();
316
+ append_token("@each", loop);
317
+ append_mandatory_space();
318
+ append_string(loop->variables()[0]);
319
+ for (size_t i = 1, L = loop->variables().size(); i < L; ++i) {
320
+ append_comma_separator();
321
+ append_string(loop->variables()[i]);
322
+ }
323
+ append_string(" in ");
324
+ loop->list()->perform(this);
325
+ loop->block()->perform(this);
326
+ }
327
+
328
+ void Inspect::operator()(WhileRule* loop)
329
+ {
330
+ append_indentation();
331
+ append_token("@while", loop);
332
+ append_mandatory_space();
333
+ loop->predicate()->perform(this);
334
+ loop->block()->perform(this);
335
+ }
336
+
337
+ void Inspect::operator()(Return* ret)
338
+ {
339
+ append_indentation();
340
+ append_token("@return", ret);
341
+ append_mandatory_space();
342
+ ret->value()->perform(this);
343
+ append_delimiter();
344
+ }
345
+
346
+ void Inspect::operator()(ExtendRule* extend)
347
+ {
348
+ append_indentation();
349
+ append_token("@extend", extend);
350
+ append_mandatory_space();
351
+ extend->selector()->perform(this);
352
+ append_delimiter();
353
+ }
354
+
355
+ void Inspect::operator()(Definition* def)
356
+ {
357
+ append_indentation();
358
+ if (def->type() == Definition::MIXIN) {
359
+ append_token("@mixin", def);
360
+ append_mandatory_space();
361
+ } else {
362
+ append_token("@function", def);
363
+ append_mandatory_space();
364
+ }
365
+ append_string(def->name());
366
+ def->parameters()->perform(this);
367
+ def->block()->perform(this);
368
+ }
369
+
370
+ void Inspect::operator()(Mixin_Call* call)
371
+ {
372
+ append_indentation();
373
+ append_token("@include", call);
374
+ append_mandatory_space();
375
+ append_string(call->name());
376
+ if (call->arguments()) {
377
+ call->arguments()->perform(this);
378
+ }
379
+ if (call->block()) {
380
+ append_optional_space();
381
+ call->block()->perform(this);
382
+ }
383
+ if (!call->block()) append_delimiter();
384
+ }
385
+
386
+ void Inspect::operator()(Content* content)
387
+ {
388
+ append_indentation();
389
+ append_token("@content", content);
390
+ append_delimiter();
391
+ }
392
+
393
+ void Inspect::operator()(Map* map)
394
+ {
395
+ if (output_style() == TO_SASS && map->empty()) {
396
+ append_string("()");
397
+ return;
398
+ }
399
+ if (map->empty()) return;
400
+ if (map->is_invisible()) return;
401
+ bool items_output = false;
402
+ append_string("(");
403
+ for (auto key : map->keys()) {
404
+ if (items_output) append_comma_separator();
405
+ key->perform(this);
406
+ append_colon_separator();
407
+ LOCAL_FLAG(in_space_array, true);
408
+ LOCAL_FLAG(in_comma_array, true);
409
+ map->at(key)->perform(this);
410
+ items_output = true;
411
+ }
412
+ append_string(")");
413
+ }
414
+
415
+ sass::string Inspect::lbracket(List* list) {
416
+ return list->is_bracketed() ? "[" : "(";
417
+ }
418
+
419
+ sass::string Inspect::rbracket(List* list) {
420
+ return list->is_bracketed() ? "]" : ")";
421
+ }
422
+
423
+ void Inspect::operator()(List* list)
424
+ {
425
+ if (list->empty() && (output_style() == TO_SASS || list->is_bracketed())) {
426
+ append_string(lbracket(list));
427
+ append_string(rbracket(list));
428
+ return;
429
+ }
430
+ sass::string sep(list->separator() == SASS_SPACE ? " " : ",");
431
+ if ((output_style() != COMPRESSED) && sep == ",") sep += " ";
432
+ else if (in_media_block && sep != " ") sep += " "; // verified
433
+ if (list->empty()) return;
434
+ bool items_output = false;
435
+
436
+ bool was_space_array = in_space_array;
437
+ bool was_comma_array = in_comma_array;
438
+ // if the list is bracketed, always include the left bracket
439
+ if (list->is_bracketed()) {
440
+ append_string(lbracket(list));
441
+ }
442
+ // probably ruby sass equivalent of element_needs_parens
443
+ else if (output_style() == TO_SASS &&
444
+ list->length() == 1 &&
445
+ !list->from_selector() &&
446
+ !Cast<List>(list->at(0)) &&
447
+ !Cast<SelectorList>(list->at(0))
448
+ ) {
449
+ append_string(lbracket(list));
450
+ }
451
+ else if (!in_declaration && (list->separator() == SASS_HASH ||
452
+ (list->separator() == SASS_SPACE && in_space_array) ||
453
+ (list->separator() == SASS_COMMA && in_comma_array)
454
+ )) {
455
+ append_string(lbracket(list));
456
+ }
457
+
458
+ if (list->separator() == SASS_SPACE) in_space_array = true;
459
+ else if (list->separator() == SASS_COMMA) in_comma_array = true;
460
+
461
+ for (size_t i = 0, L = list->size(); i < L; ++i) {
462
+ if (list->separator() == SASS_HASH)
463
+ { sep[0] = i % 2 ? ':' : ','; }
464
+ ExpressionObj list_item = list->at(i);
465
+ if (output_style() != TO_SASS) {
466
+ if (list_item == nullptr) continue;
467
+ if (list_item->is_invisible()) {
468
+ // this fixes an issue with "" in a list
469
+ if (!Cast<String_Constant>(list_item)) {
470
+ continue;
471
+ }
472
+ }
473
+ }
474
+ if (items_output) {
475
+ append_string(sep);
476
+ }
477
+ if (items_output && sep != " ")
478
+ append_optional_space();
479
+ list_item->perform(this);
480
+ items_output = true;
481
+ }
482
+
483
+ in_comma_array = was_comma_array;
484
+ in_space_array = was_space_array;
485
+
486
+ // if the list is bracketed, always include the right bracket
487
+ if (list->is_bracketed()) {
488
+ if (list->separator() == SASS_COMMA && list->size() == 1) {
489
+ append_string(",");
490
+ }
491
+ append_string(rbracket(list));
492
+ }
493
+ // probably ruby sass equivalent of element_needs_parens
494
+ else if (output_style() == TO_SASS &&
495
+ list->length() == 1 &&
496
+ !list->from_selector() &&
497
+ !Cast<List>(list->at(0)) &&
498
+ !Cast<SelectorList>(list->at(0))
499
+ ) {
500
+ append_string(",");
501
+ append_string(rbracket(list));
502
+ }
503
+ else if (!in_declaration && (list->separator() == SASS_HASH ||
504
+ (list->separator() == SASS_SPACE && in_space_array) ||
505
+ (list->separator() == SASS_COMMA && in_comma_array)
506
+ )) {
507
+ append_string(rbracket(list));
508
+ }
509
+
510
+ }
511
+
512
+ void Inspect::operator()(Binary_Expression* expr)
513
+ {
514
+ expr->left()->perform(this);
515
+ if ( in_media_block ||
516
+ (output_style() == INSPECT) || (
517
+ expr->op().ws_before
518
+ && (!expr->is_interpolant())
519
+ && (expr->is_left_interpolant() ||
520
+ expr->is_right_interpolant())
521
+
522
+ )) append_string(" ");
523
+ switch (expr->optype()) {
524
+ case Sass_OP::AND: append_string("&&"); break;
525
+ case Sass_OP::OR: append_string("||"); break;
526
+ case Sass_OP::EQ: append_string("=="); break;
527
+ case Sass_OP::NEQ: append_string("!="); break;
528
+ case Sass_OP::GT: append_string(">"); break;
529
+ case Sass_OP::GTE: append_string(">="); break;
530
+ case Sass_OP::LT: append_string("<"); break;
531
+ case Sass_OP::LTE: append_string("<="); break;
532
+ case Sass_OP::ADD: append_string("+"); break;
533
+ case Sass_OP::SUB: append_string("-"); break;
534
+ case Sass_OP::MUL: append_string("*"); break;
535
+ case Sass_OP::DIV: append_string("/"); break;
536
+ case Sass_OP::MOD: append_string("%"); break;
537
+ default: break; // shouldn't get here
538
+ }
539
+ if ( in_media_block ||
540
+ (output_style() == INSPECT) || (
541
+ expr->op().ws_after
542
+ && (!expr->is_interpolant())
543
+ && (expr->is_left_interpolant() ||
544
+ expr->is_right_interpolant())
545
+ )) append_string(" ");
546
+ expr->right()->perform(this);
547
+ }
548
+
549
+ void Inspect::operator()(Unary_Expression* expr)
550
+ {
551
+ if (expr->optype() == Unary_Expression::PLUS) append_string("+");
552
+ else if (expr->optype() == Unary_Expression::SLASH) append_string("/");
553
+ else append_string("-");
554
+ expr->operand()->perform(this);
555
+ }
556
+
557
+ void Inspect::operator()(Function_Call* call)
558
+ {
559
+ append_token(call->name(), call);
560
+ call->arguments()->perform(this);
561
+ }
562
+
563
+ void Inspect::operator()(Variable* var)
564
+ {
565
+ append_token(var->name(), var);
566
+ }
567
+
568
+ void Inspect::operator()(Number* n)
569
+ {
570
+
571
+ // reduce units
572
+ n->reduce();
573
+
574
+ sass::ostream ss;
575
+ ss.precision(opt.precision);
576
+ ss << std::fixed << n->value();
577
+
578
+ sass::string res = ss.str();
579
+ size_t s = res.length();
580
+
581
+ // delete trailing zeros
582
+ for(s = s - 1; s > 0; --s)
583
+ {
584
+ if(res[s] == '0') {
585
+ res.erase(s, 1);
586
+ }
587
+ else break;
588
+ }
589
+
590
+ // delete trailing decimal separator
591
+ if(res[s] == '.') res.erase(s, 1);
592
+
593
+ // some final cosmetics
594
+ if (res == "0.0") res = "0";
595
+ else if (res == "") res = "0";
596
+ else if (res == "-0") res = "0";
597
+ else if (res == "-0.0") res = "0";
598
+ else if (opt.output_style == COMPRESSED)
599
+ {
600
+ if (n->zero()) {
601
+ // check if handling negative nr
602
+ size_t off = res[0] == '-' ? 1 : 0;
603
+ // remove leading zero from floating point in compressed mode
604
+ if (res[off] == '0' && res[off+1] == '.') res.erase(off, 1);
605
+ }
606
+ }
607
+
608
+ // add unit now
609
+ res += n->unit();
610
+
611
+ if (opt.output_style == TO_CSS && !n->is_valid_css_unit()) {
612
+ // traces.push_back(Backtrace(nr->pstate()));
613
+ throw Exception::InvalidValue({}, *n);
614
+ }
615
+
616
+ // output the final token
617
+ append_token(res, n);
618
+ }
619
+
620
+ // helper function for serializing colors
621
+ template <size_t range>
622
+ static double cap_channel(double c) {
623
+ if (c > range) return range;
624
+ else if (c < 0) return 0;
625
+ else return c;
626
+ }
627
+
628
+ void Inspect::operator()(Color_RGBA* c)
629
+ {
630
+ // output the final token
631
+ sass::ostream ss;
632
+
633
+ // original color name
634
+ // maybe an unknown token
635
+ sass::string name = c->disp();
636
+
637
+ // resolved color
638
+ sass::string res_name = name;
639
+
640
+ double r = Sass::round(cap_channel<0xff>(c->r()), opt.precision);
641
+ double g = Sass::round(cap_channel<0xff>(c->g()), opt.precision);
642
+ double b = Sass::round(cap_channel<0xff>(c->b()), opt.precision);
643
+ double a = cap_channel<1> (c->a());
644
+
645
+ // get color from given name (if one was given at all)
646
+ if (name != "" && name_to_color(name)) {
647
+ const Color_RGBA* n = name_to_color(name);
648
+ r = Sass::round(cap_channel<0xff>(n->r()), opt.precision);
649
+ g = Sass::round(cap_channel<0xff>(n->g()), opt.precision);
650
+ b = Sass::round(cap_channel<0xff>(n->b()), opt.precision);
651
+ a = cap_channel<1> (n->a());
652
+ }
653
+ // otherwise get the possible resolved color name
654
+ else {
655
+ double numval = r * 0x10000 + g * 0x100 + b;
656
+ if (color_to_name(numval))
657
+ res_name = color_to_name(numval);
658
+ }
659
+
660
+ sass::ostream hexlet;
661
+ // dart sass compressed all colors in regular css always
662
+ // ruby sass and libsass does it only when not delayed
663
+ // since color math is going to be removed, this can go too
664
+ bool compressed = opt.output_style == COMPRESSED;
665
+ hexlet << '#' << std::setw(1) << std::setfill('0');
666
+ // create a short color hexlet if there is any need for it
667
+ if (compressed && is_color_doublet(r, g, b) && a == 1) {
668
+ hexlet << std::hex << std::setw(1) << (static_cast<unsigned long>(r) >> 4);
669
+ hexlet << std::hex << std::setw(1) << (static_cast<unsigned long>(g) >> 4);
670
+ hexlet << std::hex << std::setw(1) << (static_cast<unsigned long>(b) >> 4);
671
+ } else {
672
+ hexlet << std::hex << std::setw(2) << static_cast<unsigned long>(r);
673
+ hexlet << std::hex << std::setw(2) << static_cast<unsigned long>(g);
674
+ hexlet << std::hex << std::setw(2) << static_cast<unsigned long>(b);
675
+ }
676
+
677
+ if (compressed && !c->is_delayed()) name = "";
678
+ if (opt.output_style == INSPECT && a >= 1) {
679
+ append_token(hexlet.str(), c);
680
+ return;
681
+ }
682
+
683
+ // retain the originally specified color definition if unchanged
684
+ // but only if alpha is 1 (opaque)
685
+ if (name != "" && a >= 1) {
686
+ ss << name;
687
+ }
688
+ else if (a >= 1) {
689
+ if (res_name != "") {
690
+ if (compressed && hexlet.str().size() < res_name.size()) {
691
+ ss << hexlet.str();
692
+ } else {
693
+ ss << res_name;
694
+ }
695
+ }
696
+ else {
697
+ ss << hexlet.str();
698
+ }
699
+ }
700
+ else {
701
+ ss << "rgba(";
702
+ ss << static_cast<unsigned long>(r) << ",";
703
+ if (!compressed) ss << " ";
704
+ ss << static_cast<unsigned long>(g) << ",";
705
+ if (!compressed) ss << " ";
706
+ ss << static_cast<unsigned long>(b) << ",";
707
+ if (!compressed) ss << " ";
708
+ ss << a << ')';
709
+ }
710
+
711
+ append_token(ss.str(), c);
712
+
713
+ }
714
+
715
+ void Inspect::operator()(Color_HSLA* c)
716
+ {
717
+ Color_RGBA_Obj rgba = c->toRGBA();
718
+ operator()(rgba);
719
+ }
720
+
721
+ void Inspect::operator()(Boolean* b)
722
+ {
723
+ // output the final token
724
+ append_token(b->value() ? "true" : "false", b);
725
+ }
726
+
727
+ void Inspect::operator()(String_Schema* ss)
728
+ {
729
+ // Evaluation should turn these into String_Constants,
730
+ // so this method is only for inspection purposes.
731
+ for (size_t i = 0, L = ss->length(); i < L; ++i) {
732
+ if ((*ss)[i]->is_interpolant()) append_string("#{");
733
+ (*ss)[i]->perform(this);
734
+ if ((*ss)[i]->is_interpolant()) append_string("}");
735
+ }
736
+ }
737
+
738
+ void Inspect::operator()(String_Constant* s)
739
+ {
740
+ append_token(s->value(), s);
741
+ }
742
+
743
+ void Inspect::operator()(String_Quoted* s)
744
+ {
745
+ if (const char q = s->quote_mark()) {
746
+ append_token(quote(s->value(), q), s);
747
+ } else {
748
+ append_token(s->value(), s);
749
+ }
750
+ }
751
+
752
+ void Inspect::operator()(Custom_Error* e)
753
+ {
754
+ append_token(e->message(), e);
755
+ }
756
+
757
+ void Inspect::operator()(Custom_Warning* w)
758
+ {
759
+ append_token(w->message(), w);
760
+ }
761
+
762
+ void Inspect::operator()(SupportsOperation* so)
763
+ {
764
+
765
+ if (so->needs_parens(so->left())) append_string("(");
766
+ so->left()->perform(this);
767
+ if (so->needs_parens(so->left())) append_string(")");
768
+
769
+ if (so->operand() == SupportsOperation::AND) {
770
+ append_mandatory_space();
771
+ append_token("and", so);
772
+ append_mandatory_space();
773
+ } else if (so->operand() == SupportsOperation::OR) {
774
+ append_mandatory_space();
775
+ append_token("or", so);
776
+ append_mandatory_space();
777
+ }
778
+
779
+ if (so->needs_parens(so->right())) append_string("(");
780
+ so->right()->perform(this);
781
+ if (so->needs_parens(so->right())) append_string(")");
782
+ }
783
+
784
+ void Inspect::operator()(SupportsNegation* sn)
785
+ {
786
+ append_token("not", sn);
787
+ append_mandatory_space();
788
+ if (sn->needs_parens(sn->condition())) append_string("(");
789
+ sn->condition()->perform(this);
790
+ if (sn->needs_parens(sn->condition())) append_string(")");
791
+ }
792
+
793
+ void Inspect::operator()(SupportsDeclaration* sd)
794
+ {
795
+ append_string("(");
796
+ sd->feature()->perform(this);
797
+ append_string(": ");
798
+ sd->value()->perform(this);
799
+ append_string(")");
800
+ }
801
+
802
+ void Inspect::operator()(Supports_Interpolation* sd)
803
+ {
804
+ sd->value()->perform(this);
805
+ }
806
+
807
+ void Inspect::operator()(Media_Query* mq)
808
+ {
809
+ size_t i = 0;
810
+ if (mq->media_type()) {
811
+ if (mq->is_negated()) append_string("not ");
812
+ else if (mq->is_restricted()) append_string("only ");
813
+ mq->media_type()->perform(this);
814
+ }
815
+ else {
816
+ (*mq)[i++]->perform(this);
817
+ }
818
+ for (size_t L = mq->length(); i < L; ++i) {
819
+ append_string(" and ");
820
+ (*mq)[i]->perform(this);
821
+ }
822
+ }
823
+
824
+ void Inspect::operator()(Media_Query_Expression* mqe)
825
+ {
826
+ if (mqe->is_interpolated()) {
827
+ mqe->feature()->perform(this);
828
+ }
829
+ else {
830
+ append_string("(");
831
+ mqe->feature()->perform(this);
832
+ if (mqe->value()) {
833
+ append_string(": "); // verified
834
+ mqe->value()->perform(this);
835
+ }
836
+ append_string(")");
837
+ }
838
+ }
839
+
840
+ void Inspect::operator()(At_Root_Query* ae)
841
+ {
842
+ if (ae->feature()) {
843
+ append_string("(");
844
+ ae->feature()->perform(this);
845
+ if (ae->value()) {
846
+ append_colon_separator();
847
+ ae->value()->perform(this);
848
+ }
849
+ append_string(")");
850
+ }
851
+ }
852
+
853
+ void Inspect::operator()(Function* f)
854
+ {
855
+ append_token("get-function", f);
856
+ append_string("(");
857
+ append_string(quote(f->name()));
858
+ append_string(")");
859
+ }
860
+
861
+ void Inspect::operator()(Null* n)
862
+ {
863
+ // output the final token
864
+ append_token("null", n);
865
+ }
866
+
867
+ // parameters and arguments
868
+ void Inspect::operator()(Parameter* p)
869
+ {
870
+ append_token(p->name(), p);
871
+ if (p->default_value()) {
872
+ append_colon_separator();
873
+ p->default_value()->perform(this);
874
+ }
875
+ else if (p->is_rest_parameter()) {
876
+ append_string("...");
877
+ }
878
+ }
879
+
880
+ void Inspect::operator()(Parameters* p)
881
+ {
882
+ append_string("(");
883
+ if (!p->empty()) {
884
+ (*p)[0]->perform(this);
885
+ for (size_t i = 1, L = p->length(); i < L; ++i) {
886
+ append_comma_separator();
887
+ (*p)[i]->perform(this);
888
+ }
889
+ }
890
+ append_string(")");
891
+ }
892
+
893
+ void Inspect::operator()(Argument* a)
894
+ {
895
+ if (!a->name().empty()) {
896
+ append_token(a->name(), a);
897
+ append_colon_separator();
898
+ }
899
+ if (!a->value()) return;
900
+ // Special case: argument nulls can be ignored
901
+ if (a->value()->concrete_type() == Expression::NULL_VAL) {
902
+ return;
903
+ }
904
+ if (a->value()->concrete_type() == Expression::STRING) {
905
+ String_Constant* s = Cast<String_Constant>(a->value());
906
+ if (s) s->perform(this);
907
+ } else {
908
+ a->value()->perform(this);
909
+ }
910
+ if (a->is_rest_argument()) {
911
+ append_string("...");
912
+ }
913
+ }
914
+
915
+ void Inspect::operator()(Arguments* a)
916
+ {
917
+ append_string("(");
918
+ if (!a->empty()) {
919
+ (*a)[0]->perform(this);
920
+ for (size_t i = 1, L = a->length(); i < L; ++i) {
921
+ append_string(", "); // verified
922
+ // Sass Bug? append_comma_separator();
923
+ (*a)[i]->perform(this);
924
+ }
925
+ }
926
+ append_string(")");
927
+ }
928
+
929
+ void Inspect::operator()(Selector_Schema* s)
930
+ {
931
+ s->contents()->perform(this);
932
+ }
933
+
934
+ void Inspect::operator()(Parent_Reference* p)
935
+ {
936
+ append_string("&");
937
+ }
938
+
939
+ void Inspect::operator()(PlaceholderSelector* s)
940
+ {
941
+ append_token(s->name(), s);
942
+
943
+ }
944
+
945
+ void Inspect::operator()(TypeSelector* s)
946
+ {
947
+ append_token(s->ns_name(), s);
948
+ }
949
+
950
+ void Inspect::operator()(ClassSelector* s)
951
+ {
952
+ append_token(s->ns_name(), s);
953
+ }
954
+
955
+ void Inspect::operator()(IDSelector* s)
956
+ {
957
+ append_token(s->ns_name(), s);
958
+ }
959
+
960
+ void Inspect::operator()(AttributeSelector* s)
961
+ {
962
+ append_string("[");
963
+ add_open_mapping(s);
964
+ append_token(s->ns_name(), s);
965
+ if (!s->matcher().empty()) {
966
+ append_string(s->matcher());
967
+ if (s->value() && *s->value()) {
968
+ s->value()->perform(this);
969
+ }
970
+ }
971
+ add_close_mapping(s);
972
+ if (s->modifier() != 0) {
973
+ append_mandatory_space();
974
+ append_char(s->modifier());
975
+ }
976
+ append_string("]");
977
+ }
978
+
979
+ void Inspect::operator()(PseudoSelector* s)
980
+ {
981
+
982
+ if (s->name() != "") {
983
+ append_string(":");
984
+ if (s->isSyntacticElement()) {
985
+ append_string(":");
986
+ }
987
+ append_token(s->ns_name(), s);
988
+ if (s->selector() || s->argument()) {
989
+ bool was = in_wrapped;
990
+ in_wrapped = true;
991
+ append_string("(");
992
+ if (s->argument()) {
993
+ s->argument()->perform(this);
994
+ }
995
+ if (s->selector() && s->argument()) {
996
+ append_mandatory_space();
997
+ }
998
+ bool was_comma_array = in_comma_array;
999
+ in_comma_array = false;
1000
+ if (s->selector()) {
1001
+ s->selector()->perform(this);
1002
+ }
1003
+ in_comma_array = was_comma_array;
1004
+ append_string(")");
1005
+ in_wrapped = was;
1006
+ }
1007
+ }
1008
+ }
1009
+
1010
+ void Inspect::operator()(SelectorList* g)
1011
+ {
1012
+
1013
+ if (g->empty()) {
1014
+ if (output_style() == TO_SASS) {
1015
+ append_token("()", g);
1016
+ }
1017
+ return;
1018
+ }
1019
+
1020
+
1021
+ bool was_comma_array = in_comma_array;
1022
+ // probably ruby sass equivalent of element_needs_parens
1023
+ if (output_style() == TO_SASS && g->length() == 1 &&
1024
+ (!Cast<List>((*g)[0]) &&
1025
+ !Cast<SelectorList>((*g)[0]))) {
1026
+ append_string("(");
1027
+ }
1028
+ else if (!in_declaration && in_comma_array) {
1029
+ append_string("(");
1030
+ }
1031
+
1032
+ if (in_declaration) in_comma_array = true;
1033
+
1034
+ for (size_t i = 0, L = g->length(); i < L; ++i) {
1035
+
1036
+ if (!in_wrapped && i == 0) append_indentation();
1037
+ if ((*g)[i] == nullptr) continue;
1038
+ if (g->at(i)->length() == 0) continue;
1039
+ schedule_mapping(g->at(i)->last());
1040
+ // add_open_mapping((*g)[i]->last());
1041
+ (*g)[i]->perform(this);
1042
+ // add_close_mapping((*g)[i]->last());
1043
+ if (i < L - 1) {
1044
+ scheduled_space = 0;
1045
+ append_comma_separator();
1046
+ }
1047
+ }
1048
+
1049
+ in_comma_array = was_comma_array;
1050
+ // probably ruby sass equivalent of element_needs_parens
1051
+ if (output_style() == TO_SASS && g->length() == 1 &&
1052
+ (!Cast<List>((*g)[0]) &&
1053
+ !Cast<SelectorList>((*g)[0]))) {
1054
+ append_string(",)");
1055
+ }
1056
+ else if (!in_declaration && in_comma_array) {
1057
+ append_string(")");
1058
+ }
1059
+
1060
+ }
1061
+ void Inspect::operator()(ComplexSelector* sel)
1062
+ {
1063
+ if (sel->hasPreLineFeed()) {
1064
+ append_optional_linefeed();
1065
+ if (!in_wrapped && output_style() == NESTED) {
1066
+ append_indentation();
1067
+ }
1068
+ }
1069
+ const SelectorComponent* prev = nullptr;
1070
+ for (auto& item : sel->elements()) {
1071
+ if (prev != nullptr) {
1072
+ if (item->getCombinator() || prev->getCombinator()) {
1073
+ append_optional_space();
1074
+ } else {
1075
+ append_mandatory_space();
1076
+ }
1077
+ }
1078
+ item->perform(this);
1079
+ prev = item.ptr();
1080
+ }
1081
+ }
1082
+
1083
+ void Inspect::operator()(SelectorComponent* sel)
1084
+ {
1085
+ // You should probably never call this method directly
1086
+ // But in case anyone does, we will do the up-casting
1087
+ if (auto comp = Cast<CompoundSelector>(sel)) operator()(comp);
1088
+ if (auto comb = Cast<SelectorCombinator>(sel)) operator()(comb);
1089
+ }
1090
+
1091
+ void Inspect::operator()(CompoundSelector* sel)
1092
+ {
1093
+ if (sel->hasRealParent() /* || sel->has_real_parent_ref() */) {
1094
+ append_string("&");
1095
+ }
1096
+ for (auto& item : sel->elements()) {
1097
+ item->perform(this);
1098
+ }
1099
+ // Add the post line break (from ruby sass)
1100
+ // Dart sass uses another logic for newlines
1101
+ if (sel->hasPostLineBreak()) {
1102
+ if (output_style() != COMPACT) {
1103
+ append_optional_linefeed();
1104
+ }
1105
+ }
1106
+ }
1107
+
1108
+ void Inspect::operator()(SelectorCombinator* sel)
1109
+ {
1110
+ append_optional_space();
1111
+ switch (sel->combinator()) {
1112
+ case SelectorCombinator::Combinator::CHILD: append_string(">"); break;
1113
+ case SelectorCombinator::Combinator::GENERAL: append_string("~"); break;
1114
+ case SelectorCombinator::Combinator::ADJACENT: append_string("+"); break;
1115
+ }
1116
+ append_optional_space();
1117
+ // Add the post line break (from ruby sass)
1118
+ // Dart sass uses another logic for newlines
1119
+ if (sel->hasPostLineBreak()) {
1120
+ if (output_style() != COMPACT) {
1121
+ // append_optional_linefeed();
1122
+ }
1123
+ }
1124
+ }
1125
+
1126
+ }