sassc 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.gitmodules +3 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +24 -0
- data/Rakefile +21 -0
- data/ext/libsass/.editorconfig +15 -0
- data/ext/libsass/.gitattributes +2 -0
- data/ext/libsass/.gitignore +61 -0
- data/ext/libsass/.travis.yml +38 -0
- data/ext/libsass/COPYING +25 -0
- data/ext/libsass/INSTALL +1 -0
- data/ext/libsass/LICENSE +25 -0
- data/ext/libsass/Makefile +223 -0
- data/ext/libsass/Makefile.am +145 -0
- data/ext/libsass/Readme.md +93 -0
- data/ext/libsass/appveyor.yml +76 -0
- data/ext/libsass/ast.cpp +581 -0
- data/ext/libsass/ast.hpp +1949 -0
- data/ext/libsass/ast_def_macros.hpp +16 -0
- data/ext/libsass/ast_factory.hpp +87 -0
- data/ext/libsass/ast_fwd_decl.hpp +72 -0
- data/ext/libsass/b64/cencode.h +32 -0
- data/ext/libsass/b64/encode.h +77 -0
- data/ext/libsass/backtrace.hpp +81 -0
- data/ext/libsass/base64vlq.cpp +43 -0
- data/ext/libsass/base64vlq.hpp +28 -0
- data/ext/libsass/bind.cpp +187 -0
- data/ext/libsass/bind.hpp +18 -0
- data/ext/libsass/cencode.c +102 -0
- data/ext/libsass/color_names.hpp +324 -0
- data/ext/libsass/configure.ac +130 -0
- data/ext/libsass/constants.cpp +144 -0
- data/ext/libsass/constants.hpp +145 -0
- data/ext/libsass/context.cpp +507 -0
- data/ext/libsass/context.hpp +150 -0
- data/ext/libsass/contextualize.cpp +157 -0
- data/ext/libsass/contextualize.hpp +65 -0
- data/ext/libsass/copy_c_str.cpp +13 -0
- data/ext/libsass/copy_c_str.hpp +5 -0
- data/ext/libsass/debug.hpp +39 -0
- data/ext/libsass/environment.hpp +75 -0
- data/ext/libsass/error_handling.cpp +28 -0
- data/ext/libsass/error_handling.hpp +28 -0
- data/ext/libsass/eval.cpp +1149 -0
- data/ext/libsass/eval.hpp +80 -0
- data/ext/libsass/expand.cpp +430 -0
- data/ext/libsass/expand.hpp +77 -0
- data/ext/libsass/extconf.rb +6 -0
- data/ext/libsass/extend.cpp +1962 -0
- data/ext/libsass/extend.hpp +50 -0
- data/ext/libsass/file.cpp +291 -0
- data/ext/libsass/file.hpp +18 -0
- data/ext/libsass/functions.cpp +1565 -0
- data/ext/libsass/functions.hpp +187 -0
- data/ext/libsass/inspect.cpp +727 -0
- data/ext/libsass/inspect.hpp +108 -0
- data/ext/libsass/json.cpp +1411 -0
- data/ext/libsass/json.hpp +117 -0
- data/ext/libsass/kwd_arg_macros.hpp +23 -0
- data/ext/libsass/m4/.gitkeep +0 -0
- data/ext/libsass/mapping.hpp +17 -0
- data/ext/libsass/memory_manager.hpp +54 -0
- data/ext/libsass/node.cpp +251 -0
- data/ext/libsass/node.hpp +122 -0
- data/ext/libsass/operation.hpp +153 -0
- data/ext/libsass/output_compressed.cpp +401 -0
- data/ext/libsass/output_compressed.hpp +95 -0
- data/ext/libsass/output_nested.cpp +364 -0
- data/ext/libsass/output_nested.hpp +108 -0
- data/ext/libsass/parser.cpp +2016 -0
- data/ext/libsass/parser.hpp +264 -0
- data/ext/libsass/paths.hpp +69 -0
- data/ext/libsass/position.hpp +22 -0
- data/ext/libsass/posix/getopt.c +562 -0
- data/ext/libsass/posix/getopt.h +95 -0
- data/ext/libsass/prelexer.cpp +688 -0
- data/ext/libsass/prelexer.hpp +513 -0
- data/ext/libsass/remove_placeholders.cpp +59 -0
- data/ext/libsass/remove_placeholders.hpp +43 -0
- data/ext/libsass/res/resource.rc +35 -0
- data/ext/libsass/sass.cpp +33 -0
- data/ext/libsass/sass.h +60 -0
- data/ext/libsass/sass2scss.cpp +834 -0
- data/ext/libsass/sass2scss.h +110 -0
- data/ext/libsass/sass_context.cpp +709 -0
- data/ext/libsass/sass_context.h +120 -0
- data/ext/libsass/sass_functions.cpp +137 -0
- data/ext/libsass/sass_functions.h +90 -0
- data/ext/libsass/sass_interface.cpp +277 -0
- data/ext/libsass/sass_interface.h +97 -0
- data/ext/libsass/sass_util.cpp +136 -0
- data/ext/libsass/sass_util.hpp +259 -0
- data/ext/libsass/sass_values.cpp +337 -0
- data/ext/libsass/sass_values.h +124 -0
- data/ext/libsass/script/bootstrap +10 -0
- data/ext/libsass/script/branding +10 -0
- data/ext/libsass/script/ci-build-libsass +72 -0
- data/ext/libsass/script/ci-install-compiler +4 -0
- data/ext/libsass/script/ci-install-deps +19 -0
- data/ext/libsass/script/ci-report-coverage +25 -0
- data/ext/libsass/script/coveralls-debug +32 -0
- data/ext/libsass/script/spec +5 -0
- data/ext/libsass/script/tap-driver +652 -0
- data/ext/libsass/script/tap-runner +1 -0
- data/ext/libsass/source_map.cpp +133 -0
- data/ext/libsass/source_map.hpp +46 -0
- data/ext/libsass/subset_map.hpp +145 -0
- data/ext/libsass/support/libsass.pc.in +11 -0
- data/ext/libsass/test-driver +127 -0
- data/ext/libsass/test/test_node.cpp +98 -0
- data/ext/libsass/test/test_paths.cpp +29 -0
- data/ext/libsass/test/test_selector_difference.cpp +28 -0
- data/ext/libsass/test/test_specificity.cpp +28 -0
- data/ext/libsass/test/test_subset_map.cpp +472 -0
- data/ext/libsass/test/test_superselector.cpp +71 -0
- data/ext/libsass/test/test_unification.cpp +33 -0
- data/ext/libsass/to_c.cpp +61 -0
- data/ext/libsass/to_c.hpp +44 -0
- data/ext/libsass/to_string.cpp +29 -0
- data/ext/libsass/to_string.hpp +32 -0
- data/ext/libsass/token.hpp +32 -0
- data/ext/libsass/units.cpp +54 -0
- data/ext/libsass/units.hpp +10 -0
- data/ext/libsass/utf8.h +34 -0
- data/ext/libsass/utf8/checked.h +327 -0
- data/ext/libsass/utf8/core.h +329 -0
- data/ext/libsass/utf8/unchecked.h +228 -0
- data/ext/libsass/utf8_string.cpp +102 -0
- data/ext/libsass/utf8_string.hpp +36 -0
- data/ext/libsass/util.cpp +189 -0
- data/ext/libsass/util.hpp +26 -0
- data/ext/libsass/win/libsass.filters +291 -0
- data/ext/libsass/win/libsass.sln +28 -0
- data/ext/libsass/win/libsass.vcxproj +255 -0
- data/lib/sassc.rb +6 -0
- data/lib/sassc/engine.rb +13 -0
- data/lib/sassc/native.rb +44 -0
- data/lib/sassc/native/native_context_api.rb +140 -0
- data/lib/sassc/native/native_functions_api.rb +41 -0
- data/lib/sassc/native/sass_input_style.rb +11 -0
- data/lib/sassc/native/sass_output_style.rb +10 -0
- data/lib/sassc/native/sass_value.rb +95 -0
- data/lib/sassc/native/string_list.rb +8 -0
- data/lib/sassc/version.rb +3 -0
- data/sassc.gemspec +43 -0
- data/test/smoke_test.rb +171 -0
- data/test/test_helper.rb +4 -0
- 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
|
+
}
|