sassc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +9 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +24 -0
  8. data/Rakefile +21 -0
  9. data/ext/libsass/.editorconfig +15 -0
  10. data/ext/libsass/.gitattributes +2 -0
  11. data/ext/libsass/.gitignore +61 -0
  12. data/ext/libsass/.travis.yml +38 -0
  13. data/ext/libsass/COPYING +25 -0
  14. data/ext/libsass/INSTALL +1 -0
  15. data/ext/libsass/LICENSE +25 -0
  16. data/ext/libsass/Makefile +223 -0
  17. data/ext/libsass/Makefile.am +145 -0
  18. data/ext/libsass/Readme.md +93 -0
  19. data/ext/libsass/appveyor.yml +76 -0
  20. data/ext/libsass/ast.cpp +581 -0
  21. data/ext/libsass/ast.hpp +1949 -0
  22. data/ext/libsass/ast_def_macros.hpp +16 -0
  23. data/ext/libsass/ast_factory.hpp +87 -0
  24. data/ext/libsass/ast_fwd_decl.hpp +72 -0
  25. data/ext/libsass/b64/cencode.h +32 -0
  26. data/ext/libsass/b64/encode.h +77 -0
  27. data/ext/libsass/backtrace.hpp +81 -0
  28. data/ext/libsass/base64vlq.cpp +43 -0
  29. data/ext/libsass/base64vlq.hpp +28 -0
  30. data/ext/libsass/bind.cpp +187 -0
  31. data/ext/libsass/bind.hpp +18 -0
  32. data/ext/libsass/cencode.c +102 -0
  33. data/ext/libsass/color_names.hpp +324 -0
  34. data/ext/libsass/configure.ac +130 -0
  35. data/ext/libsass/constants.cpp +144 -0
  36. data/ext/libsass/constants.hpp +145 -0
  37. data/ext/libsass/context.cpp +507 -0
  38. data/ext/libsass/context.hpp +150 -0
  39. data/ext/libsass/contextualize.cpp +157 -0
  40. data/ext/libsass/contextualize.hpp +65 -0
  41. data/ext/libsass/copy_c_str.cpp +13 -0
  42. data/ext/libsass/copy_c_str.hpp +5 -0
  43. data/ext/libsass/debug.hpp +39 -0
  44. data/ext/libsass/environment.hpp +75 -0
  45. data/ext/libsass/error_handling.cpp +28 -0
  46. data/ext/libsass/error_handling.hpp +28 -0
  47. data/ext/libsass/eval.cpp +1149 -0
  48. data/ext/libsass/eval.hpp +80 -0
  49. data/ext/libsass/expand.cpp +430 -0
  50. data/ext/libsass/expand.hpp +77 -0
  51. data/ext/libsass/extconf.rb +6 -0
  52. data/ext/libsass/extend.cpp +1962 -0
  53. data/ext/libsass/extend.hpp +50 -0
  54. data/ext/libsass/file.cpp +291 -0
  55. data/ext/libsass/file.hpp +18 -0
  56. data/ext/libsass/functions.cpp +1565 -0
  57. data/ext/libsass/functions.hpp +187 -0
  58. data/ext/libsass/inspect.cpp +727 -0
  59. data/ext/libsass/inspect.hpp +108 -0
  60. data/ext/libsass/json.cpp +1411 -0
  61. data/ext/libsass/json.hpp +117 -0
  62. data/ext/libsass/kwd_arg_macros.hpp +23 -0
  63. data/ext/libsass/m4/.gitkeep +0 -0
  64. data/ext/libsass/mapping.hpp +17 -0
  65. data/ext/libsass/memory_manager.hpp +54 -0
  66. data/ext/libsass/node.cpp +251 -0
  67. data/ext/libsass/node.hpp +122 -0
  68. data/ext/libsass/operation.hpp +153 -0
  69. data/ext/libsass/output_compressed.cpp +401 -0
  70. data/ext/libsass/output_compressed.hpp +95 -0
  71. data/ext/libsass/output_nested.cpp +364 -0
  72. data/ext/libsass/output_nested.hpp +108 -0
  73. data/ext/libsass/parser.cpp +2016 -0
  74. data/ext/libsass/parser.hpp +264 -0
  75. data/ext/libsass/paths.hpp +69 -0
  76. data/ext/libsass/position.hpp +22 -0
  77. data/ext/libsass/posix/getopt.c +562 -0
  78. data/ext/libsass/posix/getopt.h +95 -0
  79. data/ext/libsass/prelexer.cpp +688 -0
  80. data/ext/libsass/prelexer.hpp +513 -0
  81. data/ext/libsass/remove_placeholders.cpp +59 -0
  82. data/ext/libsass/remove_placeholders.hpp +43 -0
  83. data/ext/libsass/res/resource.rc +35 -0
  84. data/ext/libsass/sass.cpp +33 -0
  85. data/ext/libsass/sass.h +60 -0
  86. data/ext/libsass/sass2scss.cpp +834 -0
  87. data/ext/libsass/sass2scss.h +110 -0
  88. data/ext/libsass/sass_context.cpp +709 -0
  89. data/ext/libsass/sass_context.h +120 -0
  90. data/ext/libsass/sass_functions.cpp +137 -0
  91. data/ext/libsass/sass_functions.h +90 -0
  92. data/ext/libsass/sass_interface.cpp +277 -0
  93. data/ext/libsass/sass_interface.h +97 -0
  94. data/ext/libsass/sass_util.cpp +136 -0
  95. data/ext/libsass/sass_util.hpp +259 -0
  96. data/ext/libsass/sass_values.cpp +337 -0
  97. data/ext/libsass/sass_values.h +124 -0
  98. data/ext/libsass/script/bootstrap +10 -0
  99. data/ext/libsass/script/branding +10 -0
  100. data/ext/libsass/script/ci-build-libsass +72 -0
  101. data/ext/libsass/script/ci-install-compiler +4 -0
  102. data/ext/libsass/script/ci-install-deps +19 -0
  103. data/ext/libsass/script/ci-report-coverage +25 -0
  104. data/ext/libsass/script/coveralls-debug +32 -0
  105. data/ext/libsass/script/spec +5 -0
  106. data/ext/libsass/script/tap-driver +652 -0
  107. data/ext/libsass/script/tap-runner +1 -0
  108. data/ext/libsass/source_map.cpp +133 -0
  109. data/ext/libsass/source_map.hpp +46 -0
  110. data/ext/libsass/subset_map.hpp +145 -0
  111. data/ext/libsass/support/libsass.pc.in +11 -0
  112. data/ext/libsass/test-driver +127 -0
  113. data/ext/libsass/test/test_node.cpp +98 -0
  114. data/ext/libsass/test/test_paths.cpp +29 -0
  115. data/ext/libsass/test/test_selector_difference.cpp +28 -0
  116. data/ext/libsass/test/test_specificity.cpp +28 -0
  117. data/ext/libsass/test/test_subset_map.cpp +472 -0
  118. data/ext/libsass/test/test_superselector.cpp +71 -0
  119. data/ext/libsass/test/test_unification.cpp +33 -0
  120. data/ext/libsass/to_c.cpp +61 -0
  121. data/ext/libsass/to_c.hpp +44 -0
  122. data/ext/libsass/to_string.cpp +29 -0
  123. data/ext/libsass/to_string.hpp +32 -0
  124. data/ext/libsass/token.hpp +32 -0
  125. data/ext/libsass/units.cpp +54 -0
  126. data/ext/libsass/units.hpp +10 -0
  127. data/ext/libsass/utf8.h +34 -0
  128. data/ext/libsass/utf8/checked.h +327 -0
  129. data/ext/libsass/utf8/core.h +329 -0
  130. data/ext/libsass/utf8/unchecked.h +228 -0
  131. data/ext/libsass/utf8_string.cpp +102 -0
  132. data/ext/libsass/utf8_string.hpp +36 -0
  133. data/ext/libsass/util.cpp +189 -0
  134. data/ext/libsass/util.hpp +26 -0
  135. data/ext/libsass/win/libsass.filters +291 -0
  136. data/ext/libsass/win/libsass.sln +28 -0
  137. data/ext/libsass/win/libsass.vcxproj +255 -0
  138. data/lib/sassc.rb +6 -0
  139. data/lib/sassc/engine.rb +13 -0
  140. data/lib/sassc/native.rb +44 -0
  141. data/lib/sassc/native/native_context_api.rb +140 -0
  142. data/lib/sassc/native/native_functions_api.rb +41 -0
  143. data/lib/sassc/native/sass_input_style.rb +11 -0
  144. data/lib/sassc/native/sass_output_style.rb +10 -0
  145. data/lib/sassc/native/sass_value.rb +95 -0
  146. data/lib/sassc/native/string_list.rb +8 -0
  147. data/lib/sassc/version.rb +3 -0
  148. data/sassc.gemspec +43 -0
  149. data/test/smoke_test.rb +171 -0
  150. data/test/test_helper.rb +4 -0
  151. metadata +281 -0
@@ -0,0 +1,187 @@
1
+ #define SASS_FUNCTIONS
2
+
3
+ #include <string>
4
+
5
+ #ifndef SASS_ENVIRONMENT
6
+ #include "environment.hpp"
7
+ #endif
8
+
9
+ #ifndef SASS_POSITION
10
+ #include "position.hpp"
11
+ #endif
12
+
13
+ #include "sass_functions.h"
14
+
15
+ #define BUILT_IN(name) Expression*\
16
+ name(Env& env, Env& d_env, Context& ctx, Signature sig, const string& path, Position position, Backtrace* backtrace)
17
+
18
+ namespace Sass {
19
+ struct Context;
20
+ struct Backtrace;
21
+ class AST_Node;
22
+ class Expression;
23
+ class Definition;
24
+ typedef Environment<AST_Node*> Env;
25
+ typedef const char* Signature;
26
+ typedef Expression* (*Native_Function)(Env&, Env&, Context&, Signature, const string&, Position, Backtrace*);
27
+
28
+ Definition* make_native_function(Signature, Native_Function, Context&);
29
+ Definition* make_c_function(Signature sig, Sass_C_Function f, void* cookie, Context& ctx);
30
+
31
+ namespace Functions {
32
+
33
+ extern Signature rgb_sig;
34
+ extern Signature rgba_4_sig;
35
+ extern Signature rgba_2_sig;
36
+ extern Signature red_sig;
37
+ extern Signature green_sig;
38
+ extern Signature blue_sig;
39
+ extern Signature mix_sig;
40
+ extern Signature hsl_sig;
41
+ extern Signature hsla_sig;
42
+ extern Signature hue_sig;
43
+ extern Signature saturation_sig;
44
+ extern Signature lightness_sig;
45
+ extern Signature adjust_hue_sig;
46
+ extern Signature lighten_sig;
47
+ extern Signature darken_sig;
48
+ extern Signature saturate_sig;
49
+ extern Signature desaturate_sig;
50
+ extern Signature grayscale_sig;
51
+ extern Signature complement_sig;
52
+ extern Signature invert_sig;
53
+ extern Signature alpha_sig;
54
+ extern Signature opacity_sig;
55
+ extern Signature opacify_sig;
56
+ extern Signature fade_in_sig;
57
+ extern Signature transparentize_sig;
58
+ extern Signature fade_out_sig;
59
+ extern Signature adjust_color_sig;
60
+ extern Signature scale_color_sig;
61
+ extern Signature change_color_sig;
62
+ extern Signature ie_hex_str_sig;
63
+ extern Signature unquote_sig;
64
+ extern Signature quote_sig;
65
+ extern Signature str_length_sig;
66
+ extern Signature str_insert_sig;
67
+ extern Signature str_index_sig;
68
+ extern Signature str_slice_sig;
69
+ extern Signature to_upper_case_sig;
70
+ extern Signature to_lower_case_sig;
71
+ extern Signature percentage_sig;
72
+ extern Signature round_sig;
73
+ extern Signature ceil_sig;
74
+ extern Signature floor_sig;
75
+ extern Signature abs_sig;
76
+ extern Signature min_sig;
77
+ extern Signature max_sig;
78
+ extern Signature inspect_sig;
79
+ extern Signature random_sig;
80
+ extern Signature length_sig;
81
+ extern Signature nth_sig;
82
+ extern Signature index_sig;
83
+ extern Signature join_sig;
84
+ extern Signature append_sig;
85
+ extern Signature zip_sig;
86
+ extern Signature compact_sig;
87
+ extern Signature list_separator_sig;
88
+ extern Signature type_of_sig;
89
+ extern Signature unit_sig;
90
+ extern Signature unitless_sig;
91
+ extern Signature comparable_sig;
92
+ extern Signature variable_exists_sig;
93
+ extern Signature global_variable_exists_sig;
94
+ extern Signature function_exists_sig;
95
+ extern Signature mixin_exists_sig;
96
+ extern Signature feature_exists_sig;
97
+ extern Signature call_sig;
98
+ extern Signature not_sig;
99
+ extern Signature if_sig;
100
+ extern Signature image_url_sig;
101
+ extern Signature map_get_sig;
102
+ extern Signature map_merge_sig;
103
+ extern Signature map_remove_sig;
104
+ extern Signature map_keys_sig;
105
+ extern Signature map_values_sig;
106
+ extern Signature map_has_key_sig;
107
+ extern Signature keywords_sig;
108
+ extern Signature set_nth_sig;
109
+ extern Signature unique_id_sig;
110
+
111
+ BUILT_IN(rgb);
112
+ BUILT_IN(rgba_4);
113
+ BUILT_IN(rgba_2);
114
+ BUILT_IN(red);
115
+ BUILT_IN(green);
116
+ BUILT_IN(blue);
117
+ BUILT_IN(mix);
118
+ BUILT_IN(hsl);
119
+ BUILT_IN(hsla);
120
+ BUILT_IN(hue);
121
+ BUILT_IN(saturation);
122
+ BUILT_IN(lightness);
123
+ BUILT_IN(adjust_hue);
124
+ BUILT_IN(lighten);
125
+ BUILT_IN(darken);
126
+ BUILT_IN(saturate);
127
+ BUILT_IN(desaturate);
128
+ BUILT_IN(grayscale);
129
+ BUILT_IN(complement);
130
+ BUILT_IN(invert);
131
+ BUILT_IN(alpha);
132
+ BUILT_IN(opacify);
133
+ BUILT_IN(transparentize);
134
+ BUILT_IN(adjust_color);
135
+ BUILT_IN(scale_color);
136
+ BUILT_IN(change_color);
137
+ BUILT_IN(ie_hex_str);
138
+ BUILT_IN(sass_unquote);
139
+ BUILT_IN(sass_quote);
140
+ BUILT_IN(str_length);
141
+ BUILT_IN(str_insert);
142
+ BUILT_IN(str_index);
143
+ BUILT_IN(str_slice);
144
+ BUILT_IN(to_upper_case);
145
+ BUILT_IN(to_lower_case);
146
+ BUILT_IN(percentage);
147
+ BUILT_IN(round);
148
+ BUILT_IN(ceil);
149
+ BUILT_IN(floor);
150
+ BUILT_IN(abs);
151
+ BUILT_IN(min);
152
+ BUILT_IN(max);
153
+ BUILT_IN(inspect);
154
+ BUILT_IN(random);
155
+ BUILT_IN(length);
156
+ BUILT_IN(nth);
157
+ BUILT_IN(index);
158
+ BUILT_IN(join);
159
+ BUILT_IN(append);
160
+ BUILT_IN(zip);
161
+ BUILT_IN(compact);
162
+ BUILT_IN(list_separator);
163
+ BUILT_IN(type_of);
164
+ BUILT_IN(unit);
165
+ BUILT_IN(unitless);
166
+ BUILT_IN(comparable);
167
+ BUILT_IN(variable_exists);
168
+ BUILT_IN(global_variable_exists);
169
+ BUILT_IN(function_exists);
170
+ BUILT_IN(mixin_exists);
171
+ BUILT_IN(feature_exists);
172
+ BUILT_IN(call);
173
+ BUILT_IN(sass_not);
174
+ BUILT_IN(sass_if);
175
+ BUILT_IN(image_url);
176
+ BUILT_IN(map_get);
177
+ BUILT_IN(map_merge);
178
+ BUILT_IN(map_remove);
179
+ BUILT_IN(map_keys);
180
+ BUILT_IN(map_values);
181
+ BUILT_IN(map_has_key);
182
+ BUILT_IN(keywords);
183
+ BUILT_IN(set_nth);
184
+ BUILT_IN(unique_id);
185
+
186
+ }
187
+ }
@@ -0,0 +1,727 @@
1
+ #include "inspect.hpp"
2
+ #include "ast.hpp"
3
+ #include "context.hpp"
4
+ #include <cmath>
5
+ #include <iostream>
6
+ #include <iomanip>
7
+
8
+ namespace Sass {
9
+ using namespace std;
10
+
11
+ Inspect::Inspect(Context* ctx) : buffer(""), indentation(0), ctx(ctx) { }
12
+ Inspect::~Inspect() { }
13
+
14
+ // statements
15
+ void Inspect::operator()(Block* block)
16
+ {
17
+ if (!block->is_root()) {
18
+ append_to_buffer(" {\n");
19
+ ++indentation;
20
+ }
21
+ for (size_t i = 0, L = block->length(); i < L; ++i) {
22
+ indent();
23
+ (*block)[i]->perform(this);
24
+ // extra newline at the end of top-level statements
25
+ if (block->is_root()) append_to_buffer("\n");
26
+ append_to_buffer("\n");
27
+ }
28
+ if (!block->is_root()) {
29
+ --indentation;
30
+ indent();
31
+ append_to_buffer("}");
32
+ }
33
+ // remove extra newline that gets added after the last top-level block
34
+ if (block->is_root()) {
35
+ size_t l = buffer.length();
36
+ if (l > 2 && buffer[l-1] == '\n' && buffer[l-2] == '\n') {
37
+ buffer.erase(l-1);
38
+ if (ctx) ctx->source_map.remove_line();
39
+ }
40
+ }
41
+ }
42
+
43
+ void Inspect::operator()(Ruleset* ruleset)
44
+ {
45
+ ruleset->selector()->perform(this);
46
+ ruleset->block()->perform(this);
47
+ }
48
+
49
+ void Inspect::operator()(Propset* propset)
50
+ {
51
+ propset->property_fragment()->perform(this);
52
+ append_to_buffer(": ");
53
+ propset->block()->perform(this);
54
+ }
55
+
56
+ void Inspect::operator()(Media_Block* media_block)
57
+ {
58
+ if (ctx) ctx->source_map.add_mapping(media_block);
59
+ append_to_buffer("@media ");
60
+ media_block->media_queries()->perform(this);
61
+ media_block->block()->perform(this);
62
+ }
63
+
64
+ void Inspect::operator()(Feature_Block* feature_block)
65
+ {
66
+ if (ctx) ctx->source_map.add_mapping(feature_block);
67
+ append_to_buffer("@supports ");
68
+ feature_block->feature_queries()->perform(this);
69
+ feature_block->block()->perform(this);
70
+ }
71
+
72
+ void Inspect::operator()(At_Rule* at_rule)
73
+ {
74
+ append_to_buffer(at_rule->keyword());
75
+ if (at_rule->selector()) {
76
+ append_to_buffer(" ");
77
+ at_rule->selector()->perform(this);
78
+ }
79
+ if (at_rule->block()) {
80
+ at_rule->block()->perform(this);
81
+ }
82
+ else {
83
+ append_to_buffer(";");
84
+ }
85
+ }
86
+
87
+ void Inspect::operator()(Declaration* dec)
88
+ {
89
+ if (dec->value()->concrete_type() == Expression::NULL_VAL) return;
90
+ if (ctx) ctx->source_map.add_mapping(dec->property());
91
+ dec->property()->perform(this);
92
+ append_to_buffer(": ");
93
+ if (ctx) ctx->source_map.add_mapping(dec->value());
94
+ dec->value()->perform(this);
95
+ if (dec->is_important()) append_to_buffer(" !important");
96
+ append_to_buffer(";");
97
+ }
98
+
99
+ void Inspect::operator()(Assignment* assn)
100
+ {
101
+ append_to_buffer(assn->variable());
102
+ append_to_buffer(": ");
103
+ assn->value()->perform(this);
104
+ if (assn->is_guarded()) append_to_buffer(" !default");
105
+ append_to_buffer(";");
106
+ }
107
+
108
+ void Inspect::operator()(Import* import)
109
+ {
110
+ if (!import->urls().empty()) {
111
+ if (ctx) ctx->source_map.add_mapping(import);
112
+ append_to_buffer("@import ");
113
+ import->urls().front()->perform(this);
114
+ append_to_buffer(";");
115
+ for (size_t i = 1, S = import->urls().size(); i < S; ++i) {
116
+ append_to_buffer("\n");
117
+ if (ctx) ctx->source_map.add_mapping(import);
118
+ append_to_buffer("@import ");
119
+ import->urls()[i]->perform(this);
120
+ append_to_buffer(";");
121
+ }
122
+ }
123
+ }
124
+
125
+ void Inspect::operator()(Import_Stub* import)
126
+ {
127
+ if (ctx) ctx->source_map.add_mapping(import);
128
+ append_to_buffer("@import ");
129
+ append_to_buffer(import->file_name());
130
+ append_to_buffer(";");
131
+ }
132
+
133
+ void Inspect::operator()(Warning* warning)
134
+ {
135
+ if (ctx) ctx->source_map.add_mapping(warning);
136
+ append_to_buffer("@warn ");
137
+ warning->message()->perform(this);
138
+ append_to_buffer(";");
139
+ }
140
+
141
+ void Inspect::operator()(Error* error)
142
+ {
143
+ if (ctx) ctx->source_map.add_mapping(error);
144
+ append_to_buffer("@error ");
145
+ error->message()->perform(this);
146
+ append_to_buffer(";");
147
+ }
148
+
149
+ void Inspect::operator()(Debug* debug)
150
+ {
151
+ if (ctx) ctx->source_map.add_mapping(debug);
152
+ append_to_buffer("@debug ");
153
+ debug->value()->perform(this);
154
+ append_to_buffer(";");
155
+ }
156
+
157
+ void Inspect::operator()(Comment* comment)
158
+ {
159
+ comment->text()->perform(this);
160
+ }
161
+
162
+ void Inspect::operator()(If* cond)
163
+ {
164
+ append_to_buffer("@if ");
165
+ cond->predicate()->perform(this);
166
+ cond->consequent()->perform(this);
167
+ if (cond->alternative()) {
168
+ append_to_buffer("\n");
169
+ indent();
170
+ append_to_buffer("else");
171
+ cond->alternative()->perform(this);
172
+ }
173
+ }
174
+
175
+ void Inspect::operator()(For* loop)
176
+ {
177
+ append_to_buffer("@for ");
178
+ append_to_buffer(loop->variable());
179
+ append_to_buffer(" from ");
180
+ loop->lower_bound()->perform(this);
181
+ append_to_buffer((loop->is_inclusive() ? " through " : " to "));
182
+ loop->upper_bound()->perform(this);
183
+ loop->block()->perform(this);
184
+ }
185
+
186
+ void Inspect::operator()(Each* loop)
187
+ {
188
+ append_to_buffer("@each ");
189
+ append_to_buffer(loop->variables()[0]);
190
+ for (size_t i = 1, L = loop->variables().size(); i < L; ++i) {
191
+ append_to_buffer(", ");
192
+ append_to_buffer(loop->variables()[i]);
193
+ }
194
+ append_to_buffer(" in ");
195
+ loop->list()->perform(this);
196
+ loop->block()->perform(this);
197
+ }
198
+
199
+ void Inspect::operator()(While* loop)
200
+ {
201
+ append_to_buffer("@while ");
202
+ loop->predicate()->perform(this);
203
+ loop->block()->perform(this);
204
+ }
205
+
206
+ void Inspect::operator()(Return* ret)
207
+ {
208
+ append_to_buffer("@return ");
209
+ ret->value()->perform(this);
210
+ append_to_buffer(";");
211
+ }
212
+
213
+ void Inspect::operator()(Extension* extend)
214
+ {
215
+ append_to_buffer("@extend ");
216
+ extend->selector()->perform(this);
217
+ append_to_buffer(";");
218
+ }
219
+
220
+ void Inspect::operator()(Definition* def)
221
+ {
222
+ if (def->type() == Definition::MIXIN) {
223
+ append_to_buffer("@mixin ");
224
+ } else {
225
+ append_to_buffer("@function ");
226
+ }
227
+ append_to_buffer(def->name());
228
+ def->parameters()->perform(this);
229
+ def->block()->perform(this);
230
+ }
231
+
232
+ void Inspect::operator()(Mixin_Call* call)
233
+ {
234
+ append_to_buffer(string("@include ") += call->name());
235
+ if (call->arguments()) {
236
+ call->arguments()->perform(this);
237
+ }
238
+ if (call->block()) {
239
+ append_to_buffer(" ");
240
+ call->block()->perform(this);
241
+ }
242
+ if (!call->block()) append_to_buffer(";");
243
+ }
244
+
245
+ void Inspect::operator()(Content* content)
246
+ {
247
+ if (ctx) ctx->source_map.add_mapping(content);
248
+ append_to_buffer("@content;");
249
+ }
250
+
251
+ void Inspect::operator()(Map* map)
252
+ {
253
+ if (map->empty()) return;
254
+ if (map->is_invisible()) return;
255
+ bool items_output = false;
256
+ append_to_buffer("(");
257
+ for (auto key : map->keys()) {
258
+ if (key->is_invisible()) continue;
259
+ if (map->at(key)->is_invisible()) continue;
260
+ if (items_output) append_to_buffer(", ");
261
+ key->perform(this);
262
+ append_to_buffer(": ");
263
+ map->at(key)->perform(this);
264
+ items_output = true;
265
+ }
266
+ append_to_buffer(")");
267
+ }
268
+
269
+ void Inspect::operator()(List* list)
270
+ {
271
+ string sep(list->separator() == List::SPACE ? " " : ", ");
272
+ if (list->empty()) return;
273
+ bool items_output = false;
274
+ for (size_t i = 0, L = list->length(); i < L; ++i) {
275
+ Expression* list_item = (*list)[i];
276
+ if (list_item->is_invisible()) {
277
+ continue;
278
+ }
279
+ if (items_output) append_to_buffer(sep);
280
+ list_item->perform(this);
281
+ items_output = true;
282
+ }
283
+ }
284
+
285
+ void Inspect::operator()(Binary_Expression* expr)
286
+ {
287
+ expr->left()->perform(this);
288
+ switch (expr->type()) {
289
+ case Binary_Expression::AND: append_to_buffer(" and "); break;
290
+ case Binary_Expression::OR: append_to_buffer(" or "); break;
291
+ case Binary_Expression::EQ: append_to_buffer(" == "); break;
292
+ case Binary_Expression::NEQ: append_to_buffer(" != "); break;
293
+ case Binary_Expression::GT: append_to_buffer(" > "); break;
294
+ case Binary_Expression::GTE: append_to_buffer(" >= "); break;
295
+ case Binary_Expression::LT: append_to_buffer(" < "); break;
296
+ case Binary_Expression::LTE: append_to_buffer(" <= "); break;
297
+ case Binary_Expression::ADD: append_to_buffer(" + "); break;
298
+ case Binary_Expression::SUB: append_to_buffer(" - "); break;
299
+ case Binary_Expression::MUL: append_to_buffer(" * "); break;
300
+ case Binary_Expression::DIV: append_to_buffer("/"); break;
301
+ case Binary_Expression::MOD: append_to_buffer(" % "); break;
302
+ default: break; // shouldn't get here
303
+ }
304
+ expr->right()->perform(this);
305
+ }
306
+
307
+ void Inspect::operator()(Unary_Expression* expr)
308
+ {
309
+ if (expr->type() == Unary_Expression::PLUS) append_to_buffer("+");
310
+ else append_to_buffer("-");
311
+ expr->operand()->perform(this);
312
+ }
313
+
314
+ void Inspect::operator()(Function_Call* call)
315
+ {
316
+ append_to_buffer(call->name());
317
+ call->arguments()->perform(this);
318
+ }
319
+
320
+ void Inspect::operator()(Function_Call_Schema* call)
321
+ {
322
+ call->name()->perform(this);
323
+ call->arguments()->perform(this);
324
+ }
325
+
326
+ void Inspect::operator()(Variable* var)
327
+ {
328
+ append_to_buffer(var->name());
329
+ }
330
+
331
+ void Inspect::operator()(Textual* txt)
332
+ {
333
+ append_to_buffer(txt->value());
334
+ }
335
+
336
+ // helper functions for serializing numbers
337
+ // string frac_to_string(double f, size_t p) {
338
+ // stringstream ss;
339
+ // ss.setf(ios::fixed, ios::floatfield);
340
+ // ss.precision(p);
341
+ // ss << f;
342
+ // string result(ss.str().substr(f < 0 ? 2 : 1));
343
+ // size_t i = result.size() - 1;
344
+ // while (result[i] == '0') --i;
345
+ // result = result.substr(0, i+1);
346
+ // return result;
347
+ // }
348
+ // string double_to_string(double d, size_t p) {
349
+ // stringstream ss;
350
+ // double ipart;
351
+ // double fpart = std::modf(d, &ipart);
352
+ // ss << ipart;
353
+ // if (fpart != 0) ss << frac_to_string(fpart, 5);
354
+ // return ss.str();
355
+ // }
356
+
357
+ void Inspect::operator()(Number* n)
358
+ {
359
+ stringstream ss;
360
+ ss.precision(ctx ? ctx->precision : 5);
361
+ ss << fixed << n->value();
362
+ string d(ss.str());
363
+ // store if the value did not equal zero
364
+ // if after applying precsision, the value gets
365
+ // truncated to zero, sass emits 0.0 instead of 0
366
+ bool nonzero = n->value() != 0;
367
+ for (size_t i = d.length()-1; d[i] == '0'; --i) {
368
+ d.resize(d.length()-1);
369
+ }
370
+ if (d[d.length()-1] == '.') d.resize(d.length()-1);
371
+ if (n->numerator_units().size() > 1 || n->denominator_units().size() > 0) {
372
+ error(d + n->unit() + " is not a valid CSS value", n->path(), n->position());
373
+ }
374
+ if (!n->zero()) {
375
+ if (d.substr(0, 3) == "-0.") d.erase(1, 1);
376
+ if (d.substr(0, 2) == "0.") d.erase(0, 1);
377
+ }
378
+ // remove the leading minus
379
+ if (d == "-0") d.erase(0, 1);
380
+ // use fractional output if we had
381
+ // a value before it got truncated
382
+ if (d == "0" && nonzero) d = "0.0";
383
+ // append number and unit
384
+ append_to_buffer(d);
385
+ append_to_buffer(n->unit());
386
+ }
387
+
388
+ // helper function for serializing colors
389
+ template <size_t range>
390
+ static double cap_channel(double c) {
391
+ if (c > range) return range;
392
+ else if (c < 0) return 0;
393
+ else return c;
394
+ }
395
+
396
+ void Inspect::operator()(Color* c)
397
+ {
398
+ stringstream ss;
399
+ double r = round(cap_channel<0xff>(c->r()));
400
+ double g = round(cap_channel<0xff>(c->g()));
401
+ double b = round(cap_channel<0xff>(c->b()));
402
+ double a = cap_channel<1> (c->a());
403
+
404
+ // retain the originally specified color definition if unchanged
405
+ if (!c->disp().empty()) {
406
+ ss << c->disp();
407
+ }
408
+ else if (r == 0 && g == 0 && b == 0 && a == 0) {
409
+ ss << "transparent";
410
+ }
411
+ else if (a >= 1) {
412
+ // see if it's a named color
413
+ int numval = r * 0x10000;
414
+ numval += g * 0x100;
415
+ numval += b;
416
+ if (ctx && ctx->colors_to_names.count(numval)) {
417
+ ss << ctx->colors_to_names[numval];
418
+ }
419
+ else {
420
+ // otherwise output the hex triplet
421
+ ss << '#' << setw(2) << setfill('0');
422
+ ss << hex << setw(2) << static_cast<unsigned long>(r);
423
+ ss << hex << setw(2) << static_cast<unsigned long>(g);
424
+ ss << hex << setw(2) << static_cast<unsigned long>(b);
425
+ }
426
+ }
427
+ else {
428
+ ss << "rgba(";
429
+ ss << static_cast<unsigned long>(r) << ", ";
430
+ ss << static_cast<unsigned long>(g) << ", ";
431
+ ss << static_cast<unsigned long>(b) << ", ";
432
+ ss << a << ')';
433
+ }
434
+ append_to_buffer(ss.str());
435
+ }
436
+
437
+ void Inspect::operator()(Boolean* b)
438
+ {
439
+ append_to_buffer(b->value() ? "true" : "false");
440
+ }
441
+
442
+ void Inspect::operator()(String_Schema* ss)
443
+ {
444
+ // Evaluation should turn these into String_Constants, so this method is
445
+ // only for inspection purposes.
446
+ for (size_t i = 0, L = ss->length(); i < L; ++i) {
447
+ if ((*ss)[i]->is_interpolant()) append_to_buffer("#{");
448
+ (*ss)[i]->perform(this);
449
+ if ((*ss)[i]->is_interpolant()) append_to_buffer("}");
450
+ }
451
+ }
452
+
453
+ void Inspect::operator()(String_Constant* s)
454
+ {
455
+ append_to_buffer(s->needs_unquoting() ? unquote(s->value()) : s->value());
456
+ }
457
+
458
+ void Inspect::operator()(Feature_Query* fq)
459
+ {
460
+ size_t i = 0;
461
+ (*fq)[i++]->perform(this);
462
+ for (size_t L = fq->length(); i < L; ++i) {
463
+ (*fq)[i]->perform(this);
464
+ }
465
+ }
466
+
467
+ void Inspect::operator()(Feature_Query_Condition* fqc)
468
+ {
469
+ if (fqc->operand() == Feature_Query_Condition::AND)
470
+ append_to_buffer(" and ");
471
+ else if (fqc->operand() == Feature_Query_Condition::OR)
472
+ append_to_buffer(" or ");
473
+ else if (fqc->operand() == Feature_Query_Condition::NOT)
474
+ append_to_buffer(" not ");
475
+
476
+ if (!fqc->is_root()) append_to_buffer("(");
477
+
478
+ if (!fqc->length()) {
479
+ fqc->feature()->perform(this);
480
+ append_to_buffer(": ");
481
+ fqc->value()->perform(this);
482
+ }
483
+ // else
484
+ for (size_t i = 0, L = fqc->length(); i < L; ++i)
485
+ (*fqc)[i]->perform(this);
486
+
487
+ if (!fqc->is_root()) append_to_buffer(")");
488
+ }
489
+
490
+ void Inspect::operator()(Media_Query* mq)
491
+ {
492
+ size_t i = 0;
493
+ if (mq->media_type()) {
494
+ if (mq->is_negated()) append_to_buffer("not ");
495
+ else if (mq->is_restricted()) append_to_buffer("only ");
496
+ mq->media_type()->perform(this);
497
+ }
498
+ else {
499
+ (*mq)[i++]->perform(this);
500
+ }
501
+ for (size_t L = mq->length(); i < L; ++i) {
502
+ append_to_buffer(" and ");
503
+ (*mq)[i]->perform(this);
504
+ }
505
+ }
506
+
507
+ void Inspect::operator()(Media_Query_Expression* mqe)
508
+ {
509
+ if (mqe->is_interpolated()) {
510
+ mqe->feature()->perform(this);
511
+ }
512
+ else {
513
+ append_to_buffer("(");
514
+ mqe->feature()->perform(this);
515
+ if (mqe->value()) {
516
+ append_to_buffer(": ");
517
+ mqe->value()->perform(this);
518
+ }
519
+ append_to_buffer(")");
520
+ }
521
+ }
522
+
523
+ void Inspect::operator()(Null* n)
524
+ {
525
+ append_to_buffer("null");
526
+ }
527
+
528
+ // parameters and arguments
529
+ void Inspect::operator()(Parameter* p)
530
+ {
531
+ append_to_buffer(p->name());
532
+ if (p->default_value()) {
533
+ append_to_buffer(": ");
534
+ p->default_value()->perform(this);
535
+ }
536
+ else if (p->is_rest_parameter()) {
537
+ append_to_buffer("...");
538
+ }
539
+ }
540
+
541
+ void Inspect::operator()(Parameters* p)
542
+ {
543
+ append_to_buffer("(");
544
+ if (!p->empty()) {
545
+ (*p)[0]->perform(this);
546
+ for (size_t i = 1, L = p->length(); i < L; ++i) {
547
+ append_to_buffer(", ");
548
+ (*p)[i]->perform(this);
549
+ }
550
+ }
551
+ append_to_buffer(")");
552
+ }
553
+
554
+ void Inspect::operator()(Argument* a)
555
+ {
556
+ if (!a->name().empty()) {
557
+ append_to_buffer(a->name());
558
+ append_to_buffer(": ");
559
+ }
560
+ // Special case: argument nulls can be ignored
561
+ if (a->value()->concrete_type() == Expression::NULL_VAL) {
562
+ return;
563
+ }
564
+ a->value()->perform(this);
565
+ if (a->is_rest_argument()) {
566
+ append_to_buffer("...");
567
+ }
568
+ }
569
+
570
+ void Inspect::operator()(Arguments* a)
571
+ {
572
+ append_to_buffer("(");
573
+ if (!a->empty()) {
574
+ (*a)[0]->perform(this);
575
+ for (size_t i = 1, L = a->length(); i < L; ++i) {
576
+ append_to_buffer(", ");
577
+ (*a)[i]->perform(this);
578
+ }
579
+ }
580
+ append_to_buffer(")");
581
+ }
582
+
583
+ // selectors
584
+ void Inspect::operator()(Selector_Schema* s)
585
+ {
586
+ s->contents()->perform(this);
587
+ }
588
+
589
+ void Inspect::operator()(Selector_Reference* ref)
590
+ {
591
+ if (ref->selector()) ref->selector()->perform(this);
592
+ else append_to_buffer("&");
593
+ }
594
+
595
+ void Inspect::operator()(Selector_Placeholder* s)
596
+ {
597
+ append_to_buffer(s->name());
598
+ }
599
+
600
+ void Inspect::operator()(Type_Selector* s)
601
+ {
602
+ if (ctx) ctx->source_map.add_mapping(s);
603
+ append_to_buffer(s->name());
604
+ }
605
+
606
+ void Inspect::operator()(Selector_Qualifier* s)
607
+ {
608
+ if (ctx) ctx->source_map.add_mapping(s);
609
+ append_to_buffer(s->name());
610
+ }
611
+
612
+ void Inspect::operator()(Attribute_Selector* s)
613
+ {
614
+ if (ctx) ctx->source_map.add_mapping(s);
615
+ append_to_buffer("[");
616
+ append_to_buffer(s->name());
617
+ if (!s->matcher().empty()) {
618
+ append_to_buffer(s->matcher());
619
+ if (s->value()) {
620
+ s->value()->perform(this);
621
+ }
622
+ // append_to_buffer(s->value());
623
+ }
624
+ append_to_buffer("]");
625
+ }
626
+
627
+ void Inspect::operator()(Pseudo_Selector* s)
628
+ {
629
+ if (ctx) ctx->source_map.add_mapping(s);
630
+ append_to_buffer(s->name());
631
+ if (s->expression()) {
632
+ s->expression()->perform(this);
633
+ append_to_buffer(")");
634
+ }
635
+ }
636
+
637
+ void Inspect::operator()(Wrapped_Selector* s)
638
+ {
639
+ if (ctx) ctx->source_map.add_mapping(s);
640
+ append_to_buffer(s->name());
641
+ s->selector()->perform(this);
642
+ append_to_buffer(")");
643
+ }
644
+
645
+ void Inspect::operator()(Compound_Selector* s)
646
+ {
647
+ for (size_t i = 0, L = s->length(); i < L; ++i) {
648
+ (*s)[i]->perform(this);
649
+ }
650
+ }
651
+
652
+ void Inspect::operator()(Complex_Selector* c)
653
+ {
654
+ Compound_Selector* head = c->head();
655
+ Complex_Selector* tail = c->tail();
656
+ Complex_Selector::Combinator comb = c->combinator();
657
+ if (head && !head->is_empty_reference()) head->perform(this);
658
+ if (head && !head->is_empty_reference() && tail) append_to_buffer(" ");
659
+ switch (comb) {
660
+ case Complex_Selector::ANCESTOR_OF: break;
661
+ case Complex_Selector::PARENT_OF: append_to_buffer(">"); break;
662
+ case Complex_Selector::PRECEDES: append_to_buffer("~"); break;
663
+ case Complex_Selector::ADJACENT_TO: append_to_buffer("+"); break;
664
+ }
665
+ if (tail && comb != Complex_Selector::ANCESTOR_OF) {
666
+ append_to_buffer(" ");
667
+ }
668
+ if (tail) tail->perform(this);
669
+ }
670
+
671
+ void Inspect::operator()(Selector_List* g)
672
+ {
673
+ if (g->empty()) return;
674
+ (*g)[0]->perform(this);
675
+ for (size_t i = 1, L = g->length(); i < L; ++i) {
676
+ append_to_buffer(", ");
677
+ (*g)[i]->perform(this);
678
+ }
679
+ }
680
+
681
+ inline void Inspect::fallback_impl(AST_Node* n)
682
+ { }
683
+
684
+ void Inspect::indent()
685
+ { append_to_buffer(string(2*indentation, ' ')); }
686
+
687
+ string unquote(const string& s)
688
+ {
689
+ if (s.empty()) return "";
690
+ if (s.length() == 1) {
691
+ if (s[0] == '"' || s[0] == '\'') return "";
692
+ }
693
+ char q;
694
+ if (*s.begin() == '"' && *s.rbegin() == '"') q = '"';
695
+ else if (*s.begin() == '\'' && *s.rbegin() == '\'') q = '\'';
696
+ else return s;
697
+ string t;
698
+ t.reserve(s.length()-2);
699
+ for (size_t i = 1, L = s.length()-1; i < L; ++i) {
700
+ // if we see a quote, we need to remove the preceding backslash from t
701
+ if (s[i-1] == '\\' && s[i] == q) t.erase(t.length()-1);
702
+ t.push_back(s[i]);
703
+ }
704
+ return t;
705
+ }
706
+
707
+ string quote(const string& s, char q)
708
+ {
709
+ if (s.empty()) return string(2, q);
710
+ if (!q || s[0] == '"' || s[0] == '\'') return s;
711
+ string t;
712
+ t.reserve(s.length()+2);
713
+ t.push_back(q);
714
+ for (size_t i = 0, L = s.length(); i < L; ++i) {
715
+ if (s[i] == q) t.push_back('\\');
716
+ t.push_back(s[i]);
717
+ }
718
+ t.push_back(q);
719
+ return t;
720
+ }
721
+
722
+ void Inspect::append_to_buffer(const string& text)
723
+ {
724
+ buffer += text;
725
+ }
726
+
727
+ }