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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.gitmodules +3 -0
- data/.travis.yml +16 -0
- data/CHANGELOG.md +97 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +80 -0
- data/Rakefile +51 -0
- data/ext/depend +4 -0
- data/ext/extconf.rb +92 -0
- data/ext/libsass/VERSION +1 -0
- data/ext/libsass/contrib/plugin.cpp +60 -0
- data/ext/libsass/include/sass/base.h +97 -0
- data/ext/libsass/include/sass/context.h +174 -0
- data/ext/libsass/include/sass/functions.h +139 -0
- data/ext/libsass/include/sass/values.h +145 -0
- data/ext/libsass/include/sass/version.h +12 -0
- data/ext/libsass/include/sass.h +15 -0
- data/ext/libsass/include/sass2scss.h +120 -0
- data/ext/libsass/src/MurmurHash2.hpp +91 -0
- data/ext/libsass/src/ast.cpp +953 -0
- data/ext/libsass/src/ast.hpp +1064 -0
- data/ext/libsass/src/ast2c.cpp +80 -0
- data/ext/libsass/src/ast2c.hpp +39 -0
- data/ext/libsass/src/ast_def_macros.hpp +140 -0
- data/ext/libsass/src/ast_fwd_decl.cpp +31 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +274 -0
- data/ext/libsass/src/ast_helpers.hpp +316 -0
- data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
- data/ext/libsass/src/ast_sel_super.cpp +539 -0
- data/ext/libsass/src/ast_sel_unify.cpp +275 -0
- data/ext/libsass/src/ast_sel_weave.cpp +616 -0
- data/ext/libsass/src/ast_selectors.cpp +1070 -0
- data/ext/libsass/src/ast_selectors.hpp +523 -0
- data/ext/libsass/src/ast_supports.cpp +114 -0
- data/ext/libsass/src/ast_supports.hpp +121 -0
- data/ext/libsass/src/ast_values.cpp +1154 -0
- data/ext/libsass/src/ast_values.hpp +498 -0
- data/ext/libsass/src/b64/cencode.h +32 -0
- data/ext/libsass/src/b64/encode.h +79 -0
- data/ext/libsass/src/backtrace.cpp +50 -0
- data/ext/libsass/src/backtrace.hpp +29 -0
- data/ext/libsass/src/base64vlq.cpp +47 -0
- data/ext/libsass/src/base64vlq.hpp +30 -0
- data/ext/libsass/src/bind.cpp +312 -0
- data/ext/libsass/src/bind.hpp +15 -0
- data/ext/libsass/src/c2ast.cpp +64 -0
- data/ext/libsass/src/c2ast.hpp +14 -0
- data/ext/libsass/src/c99func.c +54 -0
- data/ext/libsass/src/cencode.c +106 -0
- data/ext/libsass/src/check_nesting.cpp +393 -0
- data/ext/libsass/src/check_nesting.hpp +70 -0
- data/ext/libsass/src/color_maps.cpp +652 -0
- data/ext/libsass/src/color_maps.hpp +323 -0
- data/ext/libsass/src/color_spaces.cpp +241 -0
- data/ext/libsass/src/color_spaces.hpp +227 -0
- data/ext/libsass/src/constants.cpp +199 -0
- data/ext/libsass/src/constants.hpp +200 -0
- data/ext/libsass/src/context.cpp +870 -0
- data/ext/libsass/src/context.hpp +140 -0
- data/ext/libsass/src/cssize.cpp +521 -0
- data/ext/libsass/src/cssize.hpp +71 -0
- data/ext/libsass/src/dart_helpers.hpp +199 -0
- data/ext/libsass/src/debug.hpp +43 -0
- data/ext/libsass/src/debugger.hpp +964 -0
- data/ext/libsass/src/emitter.cpp +297 -0
- data/ext/libsass/src/emitter.hpp +101 -0
- data/ext/libsass/src/environment.cpp +260 -0
- data/ext/libsass/src/environment.hpp +124 -0
- data/ext/libsass/src/error_handling.cpp +239 -0
- data/ext/libsass/src/error_handling.hpp +248 -0
- data/ext/libsass/src/eval.cpp +1543 -0
- data/ext/libsass/src/eval.hpp +110 -0
- data/ext/libsass/src/eval_selectors.cpp +75 -0
- data/ext/libsass/src/expand.cpp +875 -0
- data/ext/libsass/src/expand.hpp +98 -0
- data/ext/libsass/src/extender.cpp +1226 -0
- data/ext/libsass/src/extender.hpp +399 -0
- data/ext/libsass/src/extension.cpp +43 -0
- data/ext/libsass/src/extension.hpp +89 -0
- data/ext/libsass/src/file.cpp +531 -0
- data/ext/libsass/src/file.hpp +124 -0
- data/ext/libsass/src/fn_colors.cpp +836 -0
- data/ext/libsass/src/fn_colors.hpp +99 -0
- data/ext/libsass/src/fn_lists.cpp +285 -0
- data/ext/libsass/src/fn_lists.hpp +34 -0
- data/ext/libsass/src/fn_maps.cpp +94 -0
- data/ext/libsass/src/fn_maps.hpp +30 -0
- data/ext/libsass/src/fn_miscs.cpp +248 -0
- data/ext/libsass/src/fn_miscs.hpp +40 -0
- data/ext/libsass/src/fn_numbers.cpp +246 -0
- data/ext/libsass/src/fn_numbers.hpp +45 -0
- data/ext/libsass/src/fn_selectors.cpp +205 -0
- data/ext/libsass/src/fn_selectors.hpp +35 -0
- data/ext/libsass/src/fn_strings.cpp +268 -0
- data/ext/libsass/src/fn_strings.hpp +34 -0
- data/ext/libsass/src/fn_utils.cpp +159 -0
- data/ext/libsass/src/fn_utils.hpp +62 -0
- data/ext/libsass/src/inspect.cpp +1126 -0
- data/ext/libsass/src/inspect.hpp +101 -0
- data/ext/libsass/src/json.cpp +1436 -0
- data/ext/libsass/src/json.hpp +117 -0
- data/ext/libsass/src/kwd_arg_macros.hpp +28 -0
- data/ext/libsass/src/lexer.cpp +122 -0
- data/ext/libsass/src/lexer.hpp +304 -0
- data/ext/libsass/src/listize.cpp +70 -0
- data/ext/libsass/src/listize.hpp +37 -0
- data/ext/libsass/src/mapping.hpp +19 -0
- data/ext/libsass/src/memory/allocator.cpp +48 -0
- data/ext/libsass/src/memory/allocator.hpp +138 -0
- data/ext/libsass/src/memory/config.hpp +20 -0
- data/ext/libsass/src/memory/memory_pool.hpp +186 -0
- data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
- data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
- data/ext/libsass/src/memory.hpp +12 -0
- data/ext/libsass/src/operation.hpp +223 -0
- data/ext/libsass/src/operators.cpp +267 -0
- data/ext/libsass/src/operators.hpp +30 -0
- data/ext/libsass/src/ordered_map.hpp +112 -0
- data/ext/libsass/src/output.cpp +320 -0
- data/ext/libsass/src/output.hpp +47 -0
- data/ext/libsass/src/parser.cpp +3059 -0
- data/ext/libsass/src/parser.hpp +395 -0
- data/ext/libsass/src/parser_selectors.cpp +189 -0
- data/ext/libsass/src/permutate.hpp +164 -0
- data/ext/libsass/src/plugins.cpp +188 -0
- data/ext/libsass/src/plugins.hpp +57 -0
- data/ext/libsass/src/position.cpp +163 -0
- data/ext/libsass/src/position.hpp +147 -0
- data/ext/libsass/src/prelexer.cpp +1780 -0
- data/ext/libsass/src/prelexer.hpp +484 -0
- data/ext/libsass/src/remove_placeholders.cpp +86 -0
- data/ext/libsass/src/remove_placeholders.hpp +37 -0
- data/ext/libsass/src/sass.cpp +156 -0
- data/ext/libsass/src/sass.hpp +147 -0
- data/ext/libsass/src/sass2scss.cpp +895 -0
- data/ext/libsass/src/sass_context.cpp +742 -0
- data/ext/libsass/src/sass_context.hpp +129 -0
- data/ext/libsass/src/sass_functions.cpp +210 -0
- data/ext/libsass/src/sass_functions.hpp +50 -0
- data/ext/libsass/src/sass_values.cpp +362 -0
- data/ext/libsass/src/sass_values.hpp +82 -0
- data/ext/libsass/src/settings.hpp +19 -0
- data/ext/libsass/src/source.cpp +69 -0
- data/ext/libsass/src/source.hpp +95 -0
- data/ext/libsass/src/source_data.hpp +32 -0
- data/ext/libsass/src/source_map.cpp +202 -0
- data/ext/libsass/src/source_map.hpp +65 -0
- data/ext/libsass/src/stylesheet.cpp +22 -0
- data/ext/libsass/src/stylesheet.hpp +57 -0
- data/ext/libsass/src/to_value.cpp +114 -0
- data/ext/libsass/src/to_value.hpp +46 -0
- data/ext/libsass/src/units.cpp +507 -0
- data/ext/libsass/src/units.hpp +110 -0
- data/ext/libsass/src/utf8/checked.h +336 -0
- data/ext/libsass/src/utf8/core.h +332 -0
- data/ext/libsass/src/utf8/unchecked.h +235 -0
- data/ext/libsass/src/utf8.h +34 -0
- data/ext/libsass/src/utf8_string.cpp +104 -0
- data/ext/libsass/src/utf8_string.hpp +38 -0
- data/ext/libsass/src/util.cpp +723 -0
- data/ext/libsass/src/util.hpp +105 -0
- data/ext/libsass/src/util_string.cpp +125 -0
- data/ext/libsass/src/util_string.hpp +73 -0
- data/ext/libsass/src/values.cpp +140 -0
- data/ext/libsass/src/values.hpp +12 -0
- data/lib/sassc/dependency.rb +17 -0
- data/lib/sassc/engine.rb +141 -0
- data/lib/sassc/error.rb +37 -0
- data/lib/sassc/functions_handler.rb +73 -0
- data/lib/sassc/import_handler.rb +50 -0
- data/lib/sassc/importer.rb +31 -0
- data/lib/sassc/native/native_context_api.rb +147 -0
- data/lib/sassc/native/native_functions_api.rb +159 -0
- data/lib/sassc/native/sass2scss_api.rb +10 -0
- data/lib/sassc/native/sass_input_style.rb +13 -0
- data/lib/sassc/native/sass_output_style.rb +12 -0
- data/lib/sassc/native/sass_value.rb +97 -0
- data/lib/sassc/native/string_list.rb +10 -0
- data/lib/sassc/native.rb +64 -0
- data/lib/sassc/sass_2_scss.rb +9 -0
- data/lib/sassc/script/functions.rb +8 -0
- data/lib/sassc/script/value/bool.rb +32 -0
- data/lib/sassc/script/value/color.rb +95 -0
- data/lib/sassc/script/value/list.rb +136 -0
- data/lib/sassc/script/value/map.rb +69 -0
- data/lib/sassc/script/value/number.rb +389 -0
- data/lib/sassc/script/value/string.rb +96 -0
- data/lib/sassc/script/value.rb +137 -0
- data/lib/sassc/script/value_conversion/base.rb +13 -0
- data/lib/sassc/script/value_conversion/bool.rb +13 -0
- data/lib/sassc/script/value_conversion/color.rb +18 -0
- data/lib/sassc/script/value_conversion/list.rb +25 -0
- data/lib/sassc/script/value_conversion/map.rb +21 -0
- data/lib/sassc/script/value_conversion/number.rb +13 -0
- data/lib/sassc/script/value_conversion/string.rb +17 -0
- data/lib/sassc/script/value_conversion.rb +69 -0
- data/lib/sassc/script.rb +17 -0
- data/lib/sassc/util/normalized_map.rb +117 -0
- data/lib/sassc/util.rb +231 -0
- data/lib/sassc/version.rb +5 -0
- data/lib/sassc.rb +57 -0
- data/sassc.gemspec +69 -0
- data/test/css_color_level4_test.rb +168 -0
- data/test/custom_importer_test.rb +127 -0
- data/test/engine_test.rb +314 -0
- data/test/error_test.rb +29 -0
- data/test/fixtures/paths.scss +10 -0
- data/test/functions_test.rb +340 -0
- data/test/native_test.rb +213 -0
- data/test/output_style_test.rb +107 -0
- data/test/sass_2_scss_test.rb +14 -0
- data/test/test_helper.rb +45 -0
- metadata +396 -0
|
@@ -0,0 +1,870 @@
|
|
|
1
|
+
// sass.hpp must go before all system headers to get the
|
|
2
|
+
// __EXTENSIONS__ fix on Solaris.
|
|
3
|
+
#include "sass.hpp"
|
|
4
|
+
#include "ast.hpp"
|
|
5
|
+
|
|
6
|
+
#include "remove_placeholders.hpp"
|
|
7
|
+
#include "sass_functions.hpp"
|
|
8
|
+
#include "check_nesting.hpp"
|
|
9
|
+
#include "fn_selectors.hpp"
|
|
10
|
+
#include "fn_strings.hpp"
|
|
11
|
+
#include "fn_numbers.hpp"
|
|
12
|
+
#include "fn_colors.hpp"
|
|
13
|
+
#include "fn_miscs.hpp"
|
|
14
|
+
#include "fn_lists.hpp"
|
|
15
|
+
#include "fn_maps.hpp"
|
|
16
|
+
#include "context.hpp"
|
|
17
|
+
#include "expand.hpp"
|
|
18
|
+
#include "parser.hpp"
|
|
19
|
+
#include "cssize.hpp"
|
|
20
|
+
#include "source.hpp"
|
|
21
|
+
|
|
22
|
+
namespace Sass {
|
|
23
|
+
using namespace Constants;
|
|
24
|
+
using namespace File;
|
|
25
|
+
using namespace Sass;
|
|
26
|
+
|
|
27
|
+
inline bool sort_importers (const Sass_Importer_Entry& i, const Sass_Importer_Entry& j)
|
|
28
|
+
{ return sass_importer_get_priority(i) > sass_importer_get_priority(j); }
|
|
29
|
+
|
|
30
|
+
static sass::string safe_input(const char* in_path)
|
|
31
|
+
{
|
|
32
|
+
if (in_path == nullptr || in_path[0] == '\0') return "stdin";
|
|
33
|
+
return in_path;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static sass::string safe_output(const char* out_path, sass::string input_path)
|
|
37
|
+
{
|
|
38
|
+
if (out_path == nullptr || out_path[0] == '\0') {
|
|
39
|
+
if (input_path.empty()) return "stdout";
|
|
40
|
+
return input_path.substr(0, input_path.find_last_of(".")) + ".css";
|
|
41
|
+
}
|
|
42
|
+
return out_path;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
Context::Context(struct Sass_Context& c_ctx)
|
|
46
|
+
: CWD(File::get_cwd()),
|
|
47
|
+
c_options(c_ctx),
|
|
48
|
+
entry_path(""),
|
|
49
|
+
head_imports(0),
|
|
50
|
+
plugins(),
|
|
51
|
+
emitter(c_options),
|
|
52
|
+
|
|
53
|
+
ast_gc(),
|
|
54
|
+
strings(),
|
|
55
|
+
resources(),
|
|
56
|
+
sheets(),
|
|
57
|
+
import_stack(),
|
|
58
|
+
callee_stack(),
|
|
59
|
+
traces(),
|
|
60
|
+
extender(Extender::NORMAL, traces),
|
|
61
|
+
c_compiler(NULL),
|
|
62
|
+
|
|
63
|
+
c_headers (sass::vector<Sass_Importer_Entry>()),
|
|
64
|
+
c_importers (sass::vector<Sass_Importer_Entry>()),
|
|
65
|
+
c_functions (sass::vector<Sass_Function_Entry>()),
|
|
66
|
+
|
|
67
|
+
indent (safe_str(c_options.indent, " ")),
|
|
68
|
+
linefeed (safe_str(c_options.linefeed, "\n")),
|
|
69
|
+
|
|
70
|
+
input_path (make_canonical_path(safe_input(c_options.input_path))),
|
|
71
|
+
output_path (make_canonical_path(safe_output(c_options.output_path, input_path))),
|
|
72
|
+
source_map_file (make_canonical_path(safe_str(c_options.source_map_file, ""))),
|
|
73
|
+
source_map_root (make_canonical_path(safe_str(c_options.source_map_root, "")))
|
|
74
|
+
|
|
75
|
+
{
|
|
76
|
+
|
|
77
|
+
// Sass 3.4: The current working directory will no longer be placed onto the Sass load path by default.
|
|
78
|
+
// If you need the current working directory to be available, set SASS_PATH=. in your shell's environment.
|
|
79
|
+
// include_paths.push_back(CWD);
|
|
80
|
+
|
|
81
|
+
// collect more paths from different options
|
|
82
|
+
collect_include_paths(c_options.include_path);
|
|
83
|
+
collect_include_paths(c_options.include_paths);
|
|
84
|
+
collect_plugin_paths(c_options.plugin_path);
|
|
85
|
+
collect_plugin_paths(c_options.plugin_paths);
|
|
86
|
+
|
|
87
|
+
// load plugins and register custom behaviors
|
|
88
|
+
for(auto plug : plugin_paths) plugins.load_plugins(plug);
|
|
89
|
+
for(auto fn : plugins.get_headers()) c_headers.push_back(fn);
|
|
90
|
+
for(auto fn : plugins.get_importers()) c_importers.push_back(fn);
|
|
91
|
+
for(auto fn : plugins.get_functions()) c_functions.push_back(fn);
|
|
92
|
+
|
|
93
|
+
// sort the items by priority (lowest first)
|
|
94
|
+
sort (c_headers.begin(), c_headers.end(), sort_importers);
|
|
95
|
+
sort (c_importers.begin(), c_importers.end(), sort_importers);
|
|
96
|
+
|
|
97
|
+
emitter.set_filename(abs2rel(output_path, source_map_file, CWD));
|
|
98
|
+
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
void Context::add_c_function(Sass_Function_Entry function)
|
|
102
|
+
{
|
|
103
|
+
c_functions.push_back(function);
|
|
104
|
+
}
|
|
105
|
+
void Context::add_c_header(Sass_Importer_Entry header)
|
|
106
|
+
{
|
|
107
|
+
c_headers.push_back(header);
|
|
108
|
+
// need to sort the array afterwards (no big deal)
|
|
109
|
+
sort (c_headers.begin(), c_headers.end(), sort_importers);
|
|
110
|
+
}
|
|
111
|
+
void Context::add_c_importer(Sass_Importer_Entry importer)
|
|
112
|
+
{
|
|
113
|
+
c_importers.push_back(importer);
|
|
114
|
+
// need to sort the array afterwards (no big deal)
|
|
115
|
+
sort (c_importers.begin(), c_importers.end(), sort_importers);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
Context::~Context()
|
|
119
|
+
{
|
|
120
|
+
// resources were allocated by malloc
|
|
121
|
+
for (size_t i = 0; i < resources.size(); ++i) {
|
|
122
|
+
free(resources[i].contents);
|
|
123
|
+
free(resources[i].srcmap);
|
|
124
|
+
}
|
|
125
|
+
// free all strings we kept alive during compiler execution
|
|
126
|
+
for (size_t n = 0; n < strings.size(); ++n) free(strings[n]);
|
|
127
|
+
// everything that gets put into sources will be freed by us
|
|
128
|
+
// this shouldn't have anything in it anyway!?
|
|
129
|
+
for (size_t m = 0; m < import_stack.size(); ++m) {
|
|
130
|
+
sass_import_take_source(import_stack[m]);
|
|
131
|
+
sass_import_take_srcmap(import_stack[m]);
|
|
132
|
+
sass_delete_import(import_stack[m]);
|
|
133
|
+
}
|
|
134
|
+
// clear inner structures (vectors) and input source
|
|
135
|
+
resources.clear(); import_stack.clear();
|
|
136
|
+
sheets.clear();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
Data_Context::~Data_Context()
|
|
140
|
+
{
|
|
141
|
+
// --> this will be freed by resources
|
|
142
|
+
// make sure we free the source even if not processed!
|
|
143
|
+
// if (resources.size() == 0 && source_c_str) free(source_c_str);
|
|
144
|
+
// if (resources.size() == 0 && srcmap_c_str) free(srcmap_c_str);
|
|
145
|
+
// source_c_str = 0; srcmap_c_str = 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
File_Context::~File_Context()
|
|
149
|
+
{
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
void Context::collect_include_paths(const char* paths_str)
|
|
153
|
+
{
|
|
154
|
+
if (paths_str) {
|
|
155
|
+
const char* beg = paths_str;
|
|
156
|
+
const char* end = Prelexer::find_first<PATH_SEP>(beg);
|
|
157
|
+
|
|
158
|
+
while (end) {
|
|
159
|
+
sass::string path(beg, end - beg);
|
|
160
|
+
if (!path.empty()) {
|
|
161
|
+
if (*path.rbegin() != '/') path += '/';
|
|
162
|
+
include_paths.push_back(path);
|
|
163
|
+
}
|
|
164
|
+
beg = end + 1;
|
|
165
|
+
end = Prelexer::find_first<PATH_SEP>(beg);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
sass::string path(beg);
|
|
169
|
+
if (!path.empty()) {
|
|
170
|
+
if (*path.rbegin() != '/') path += '/';
|
|
171
|
+
include_paths.push_back(path);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
void Context::collect_include_paths(string_list* paths_array)
|
|
177
|
+
{
|
|
178
|
+
while (paths_array)
|
|
179
|
+
{
|
|
180
|
+
collect_include_paths(paths_array->string);
|
|
181
|
+
paths_array = paths_array->next;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
void Context::collect_plugin_paths(const char* paths_str)
|
|
186
|
+
{
|
|
187
|
+
if (paths_str) {
|
|
188
|
+
const char* beg = paths_str;
|
|
189
|
+
const char* end = Prelexer::find_first<PATH_SEP>(beg);
|
|
190
|
+
|
|
191
|
+
while (end) {
|
|
192
|
+
sass::string path(beg, end - beg);
|
|
193
|
+
if (!path.empty()) {
|
|
194
|
+
if (*path.rbegin() != '/') path += '/';
|
|
195
|
+
plugin_paths.push_back(path);
|
|
196
|
+
}
|
|
197
|
+
beg = end + 1;
|
|
198
|
+
end = Prelexer::find_first<PATH_SEP>(beg);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
sass::string path(beg);
|
|
202
|
+
if (!path.empty()) {
|
|
203
|
+
if (*path.rbegin() != '/') path += '/';
|
|
204
|
+
plugin_paths.push_back(path);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
void Context::collect_plugin_paths(string_list* paths_array)
|
|
210
|
+
{
|
|
211
|
+
while (paths_array)
|
|
212
|
+
{
|
|
213
|
+
collect_plugin_paths(paths_array->string);
|
|
214
|
+
paths_array = paths_array->next;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// resolve the imp_path in base_path or include_paths
|
|
219
|
+
// looks for alternatives and returns a list from one directory
|
|
220
|
+
sass::vector<Include> Context::find_includes(const Importer& import)
|
|
221
|
+
{
|
|
222
|
+
// make sure we resolve against an absolute path
|
|
223
|
+
sass::string base_path(rel2abs(import.base_path));
|
|
224
|
+
// first try to resolve the load path relative to the base path
|
|
225
|
+
sass::vector<Include> vec(resolve_includes(base_path, import.imp_path));
|
|
226
|
+
// then search in every include path (but only if nothing found yet)
|
|
227
|
+
for (size_t i = 0, S = include_paths.size(); vec.size() == 0 && i < S; ++i)
|
|
228
|
+
{
|
|
229
|
+
// call resolve_includes and individual base path and append all results
|
|
230
|
+
sass::vector<Include> resolved(resolve_includes(include_paths[i], import.imp_path));
|
|
231
|
+
if (resolved.size()) vec.insert(vec.end(), resolved.begin(), resolved.end());
|
|
232
|
+
}
|
|
233
|
+
// return vector
|
|
234
|
+
return vec;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// register include with resolved path and its content
|
|
238
|
+
// memory of the resources will be freed by us on exit
|
|
239
|
+
void Context::register_resource(const Include& inc, const Resource& res)
|
|
240
|
+
{
|
|
241
|
+
|
|
242
|
+
// do not parse same resource twice
|
|
243
|
+
// maybe raise an error in this case
|
|
244
|
+
// if (sheets.count(inc.abs_path)) {
|
|
245
|
+
// free(res.contents); free(res.srcmap);
|
|
246
|
+
// throw std::runtime_error("duplicate resource registered");
|
|
247
|
+
// return;
|
|
248
|
+
// }
|
|
249
|
+
|
|
250
|
+
// get index for this resource
|
|
251
|
+
size_t idx = resources.size();
|
|
252
|
+
|
|
253
|
+
// tell emitter about new resource
|
|
254
|
+
emitter.add_source_index(idx);
|
|
255
|
+
|
|
256
|
+
// put resources under our control
|
|
257
|
+
// the memory will be freed later
|
|
258
|
+
resources.push_back(res);
|
|
259
|
+
|
|
260
|
+
// add a relative link to the working directory
|
|
261
|
+
included_files.push_back(inc.abs_path);
|
|
262
|
+
// add a relative link to the source map output file
|
|
263
|
+
srcmap_links.push_back(abs2rel(inc.abs_path, source_map_file, CWD));
|
|
264
|
+
|
|
265
|
+
// get pointer to the loaded content
|
|
266
|
+
Sass_Import_Entry import = sass_make_import(
|
|
267
|
+
inc.imp_path.c_str(),
|
|
268
|
+
inc.abs_path.c_str(),
|
|
269
|
+
res.contents,
|
|
270
|
+
res.srcmap
|
|
271
|
+
);
|
|
272
|
+
// add the entry to the stack
|
|
273
|
+
import_stack.push_back(import);
|
|
274
|
+
|
|
275
|
+
// get pointer to the loaded content
|
|
276
|
+
const char* contents = resources[idx].contents;
|
|
277
|
+
SourceFileObj source = SASS_MEMORY_NEW(SourceFile,
|
|
278
|
+
inc.abs_path.c_str(), contents, idx);
|
|
279
|
+
|
|
280
|
+
// create the initial parser state from resource
|
|
281
|
+
SourceSpan pstate(source);
|
|
282
|
+
|
|
283
|
+
// check existing import stack for possible recursion
|
|
284
|
+
for (size_t i = 0; i < import_stack.size() - 2; ++i) {
|
|
285
|
+
auto parent = import_stack[i];
|
|
286
|
+
if (std::strcmp(parent->abs_path, import->abs_path) == 0) {
|
|
287
|
+
sass::string cwd(File::get_cwd());
|
|
288
|
+
// make path relative to the current directory
|
|
289
|
+
sass::string stack("An @import loop has been found:");
|
|
290
|
+
for (size_t n = 1; n < i + 2; ++n) {
|
|
291
|
+
stack += "\n " + sass::string(File::abs2rel(import_stack[n]->abs_path, cwd, cwd)) +
|
|
292
|
+
" imports " + sass::string(File::abs2rel(import_stack[n+1]->abs_path, cwd, cwd));
|
|
293
|
+
}
|
|
294
|
+
// implement error throw directly until we
|
|
295
|
+
// decided how to handle full stack traces
|
|
296
|
+
throw Exception::InvalidSyntax(pstate, traces, stack);
|
|
297
|
+
// error(stack, prstate ? *prstate : pstate, import_stack);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// create a parser instance from the given c_str buffer
|
|
302
|
+
Parser p(source, *this, traces);
|
|
303
|
+
// do not yet dispose these buffers
|
|
304
|
+
sass_import_take_source(import);
|
|
305
|
+
sass_import_take_srcmap(import);
|
|
306
|
+
// then parse the root block
|
|
307
|
+
Block_Obj root = p.parse();
|
|
308
|
+
// delete memory of current stack frame
|
|
309
|
+
sass_delete_import(import_stack.back());
|
|
310
|
+
// remove current stack frame
|
|
311
|
+
import_stack.pop_back();
|
|
312
|
+
// create key/value pair for ast node
|
|
313
|
+
std::pair<const sass::string, StyleSheet>
|
|
314
|
+
ast_pair(inc.abs_path, { res, root });
|
|
315
|
+
// register resulting resource
|
|
316
|
+
sheets.insert(ast_pair);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// register include with resolved path and its content
|
|
320
|
+
// memory of the resources will be freed by us on exit
|
|
321
|
+
void Context::register_resource(const Include& inc, const Resource& res, SourceSpan& prstate)
|
|
322
|
+
{
|
|
323
|
+
traces.push_back(Backtrace(prstate));
|
|
324
|
+
register_resource(inc, res);
|
|
325
|
+
traces.pop_back();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Add a new import to the context (called from `import_url`)
|
|
329
|
+
Include Context::load_import(const Importer& imp, SourceSpan pstate)
|
|
330
|
+
{
|
|
331
|
+
|
|
332
|
+
// search for valid imports (ie. partials) on the filesystem
|
|
333
|
+
// this may return more than one valid result (ambiguous imp_path)
|
|
334
|
+
const sass::vector<Include> resolved(find_includes(imp));
|
|
335
|
+
|
|
336
|
+
// error nicely on ambiguous imp_path
|
|
337
|
+
if (resolved.size() > 1) {
|
|
338
|
+
sass::ostream msg_stream;
|
|
339
|
+
msg_stream << "It's not clear which file to import for ";
|
|
340
|
+
msg_stream << "'@import \"" << imp.imp_path << "\"'." << "\n";
|
|
341
|
+
msg_stream << "Candidates:" << "\n";
|
|
342
|
+
for (size_t i = 0, L = resolved.size(); i < L; ++i)
|
|
343
|
+
{ msg_stream << " " << resolved[i].imp_path << "\n"; }
|
|
344
|
+
msg_stream << "Please delete or rename all but one of these files." << "\n";
|
|
345
|
+
error(msg_stream.str(), pstate, traces);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// process the resolved entry
|
|
349
|
+
else if (resolved.size() == 1) {
|
|
350
|
+
bool use_cache = c_importers.size() == 0;
|
|
351
|
+
// use cache for the resource loading
|
|
352
|
+
if (use_cache && sheets.count(resolved[0].abs_path)) return resolved[0];
|
|
353
|
+
// try to read the content of the resolved file entry
|
|
354
|
+
// the memory buffer returned must be freed by us!
|
|
355
|
+
if (char* contents = read_file(resolved[0].abs_path)) {
|
|
356
|
+
// register the newly resolved file resource
|
|
357
|
+
register_resource(resolved[0], { contents, 0 }, pstate);
|
|
358
|
+
// return resolved entry
|
|
359
|
+
return resolved[0];
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// nothing found
|
|
364
|
+
return { imp, "" };
|
|
365
|
+
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
void Context::import_url (Import* imp, sass::string load_path, const sass::string& ctx_path) {
|
|
369
|
+
|
|
370
|
+
SourceSpan pstate(imp->pstate());
|
|
371
|
+
sass::string imp_path(unquote(load_path));
|
|
372
|
+
sass::string protocol("file");
|
|
373
|
+
|
|
374
|
+
using namespace Prelexer;
|
|
375
|
+
if (const char* proto = sequence< identifier, exactly<':'>, exactly<'/'>, exactly<'/'> >(imp_path.c_str())) {
|
|
376
|
+
|
|
377
|
+
protocol = sass::string(imp_path.c_str(), proto - 3);
|
|
378
|
+
// if (protocol.compare("file") && true) { }
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// add urls (protocol other than file) and urls without protocol to `urls` member
|
|
382
|
+
// ToDo: if ctx_path is already a file resource, we should not add it here?
|
|
383
|
+
if (imp->import_queries() || protocol != "file" || imp_path.substr(0, 2) == "//") {
|
|
384
|
+
imp->urls().push_back(SASS_MEMORY_NEW(String_Quoted, imp->pstate(), load_path));
|
|
385
|
+
}
|
|
386
|
+
else if (imp_path.length() > 4 && imp_path.substr(imp_path.length() - 4, 4) == ".css") {
|
|
387
|
+
String_Constant* loc = SASS_MEMORY_NEW(String_Constant, pstate, unquote(load_path));
|
|
388
|
+
Argument_Obj loc_arg = SASS_MEMORY_NEW(Argument, pstate, loc);
|
|
389
|
+
Arguments_Obj loc_args = SASS_MEMORY_NEW(Arguments, pstate);
|
|
390
|
+
loc_args->append(loc_arg);
|
|
391
|
+
Function_Call* new_url = SASS_MEMORY_NEW(Function_Call, pstate, sass::string("url"), loc_args);
|
|
392
|
+
imp->urls().push_back(new_url);
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
const Importer importer(imp_path, ctx_path);
|
|
396
|
+
Include include(load_import(importer, pstate));
|
|
397
|
+
if (include.abs_path.empty()) {
|
|
398
|
+
error("File to import not found or unreadable: " + imp_path + ".", pstate, traces);
|
|
399
|
+
}
|
|
400
|
+
imp->incs().push_back(include);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
// call custom importers on the given (unquoted) load_path and eventually parse the resulting style_sheet
|
|
407
|
+
bool Context::call_loader(const sass::string& load_path, const char* ctx_path, SourceSpan& pstate, Import* imp, sass::vector<Sass_Importer_Entry> importers, bool only_one)
|
|
408
|
+
{
|
|
409
|
+
// unique counter
|
|
410
|
+
size_t count = 0;
|
|
411
|
+
// need one correct import
|
|
412
|
+
bool has_import = false;
|
|
413
|
+
// process all custom importers (or custom headers)
|
|
414
|
+
for (Sass_Importer_Entry& importer_ent : importers) {
|
|
415
|
+
// int priority = sass_importer_get_priority(importer);
|
|
416
|
+
Sass_Importer_Fn fn = sass_importer_get_function(importer_ent);
|
|
417
|
+
// skip importer if it returns NULL
|
|
418
|
+
if (Sass_Import_List includes =
|
|
419
|
+
fn(load_path.c_str(), importer_ent, c_compiler)
|
|
420
|
+
) {
|
|
421
|
+
// get c pointer copy to iterate over
|
|
422
|
+
Sass_Import_List it_includes = includes;
|
|
423
|
+
while (*it_includes) { ++count;
|
|
424
|
+
// create unique path to use as key
|
|
425
|
+
sass::string uniq_path = load_path;
|
|
426
|
+
if (!only_one && count) {
|
|
427
|
+
sass::ostream path_strm;
|
|
428
|
+
path_strm << uniq_path << ":" << count;
|
|
429
|
+
uniq_path = path_strm.str();
|
|
430
|
+
}
|
|
431
|
+
// create the importer struct
|
|
432
|
+
Importer importer(uniq_path, ctx_path);
|
|
433
|
+
// query data from the current include
|
|
434
|
+
Sass_Import_Entry include_ent = *it_includes;
|
|
435
|
+
char* source = sass_import_take_source(include_ent);
|
|
436
|
+
char* srcmap = sass_import_take_srcmap(include_ent);
|
|
437
|
+
size_t line = sass_import_get_error_line(include_ent);
|
|
438
|
+
size_t column = sass_import_get_error_column(include_ent);
|
|
439
|
+
const char *abs_path = sass_import_get_abs_path(include_ent);
|
|
440
|
+
// handle error message passed back from custom importer
|
|
441
|
+
// it may (or may not) override the line and column info
|
|
442
|
+
if (const char* err_message = sass_import_get_error_message(include_ent)) {
|
|
443
|
+
if (source || srcmap) register_resource({ importer, uniq_path }, { source, srcmap }, pstate);
|
|
444
|
+
if (line == sass::string::npos && column == sass::string::npos) error(err_message, pstate, traces);
|
|
445
|
+
else { error(err_message, { pstate.source, { line, column } }, traces); }
|
|
446
|
+
}
|
|
447
|
+
// content for import was set
|
|
448
|
+
else if (source) {
|
|
449
|
+
// resolved abs_path should be set by custom importer
|
|
450
|
+
// use the created uniq_path as fallback (maybe enforce)
|
|
451
|
+
sass::string path_key(abs_path ? abs_path : uniq_path);
|
|
452
|
+
// create the importer struct
|
|
453
|
+
Include include(importer, path_key);
|
|
454
|
+
// attach information to AST node
|
|
455
|
+
imp->incs().push_back(include);
|
|
456
|
+
// register the resource buffers
|
|
457
|
+
register_resource(include, { source, srcmap }, pstate);
|
|
458
|
+
}
|
|
459
|
+
// only a path was retuned
|
|
460
|
+
// try to load it like normal
|
|
461
|
+
else if(abs_path) {
|
|
462
|
+
// checks some urls to preserve
|
|
463
|
+
// `http://`, `https://` and `//`
|
|
464
|
+
// or dispatchs to `import_file`
|
|
465
|
+
// which will check for a `.css` extension
|
|
466
|
+
// or resolves the file on the filesystem
|
|
467
|
+
// added and resolved via `add_file`
|
|
468
|
+
// finally stores everything on `imp`
|
|
469
|
+
import_url(imp, abs_path, ctx_path);
|
|
470
|
+
}
|
|
471
|
+
// move to next
|
|
472
|
+
++it_includes;
|
|
473
|
+
}
|
|
474
|
+
// deallocate the returned memory
|
|
475
|
+
sass_delete_import_list(includes);
|
|
476
|
+
// set success flag
|
|
477
|
+
has_import = true;
|
|
478
|
+
// break out of loop
|
|
479
|
+
if (only_one) break;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
// return result
|
|
483
|
+
return has_import;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
void register_function(Context&, Signature sig, Native_Function f, Env* env);
|
|
487
|
+
void register_function(Context&, Signature sig, Native_Function f, size_t arity, Env* env);
|
|
488
|
+
void register_overload_stub(Context&, sass::string name, Env* env);
|
|
489
|
+
void register_built_in_functions(Context&, Env* env);
|
|
490
|
+
void register_c_functions(Context&, Env* env, Sass_Function_List);
|
|
491
|
+
void register_c_function(Context&, Env* env, Sass_Function_Entry);
|
|
492
|
+
|
|
493
|
+
char* Context::render(Block_Obj root)
|
|
494
|
+
{
|
|
495
|
+
// check for valid block
|
|
496
|
+
if (!root) return 0;
|
|
497
|
+
// start the render process
|
|
498
|
+
root->perform(&emitter);
|
|
499
|
+
// finish emitter stream
|
|
500
|
+
emitter.finalize();
|
|
501
|
+
// get the resulting buffer from stream
|
|
502
|
+
OutputBuffer emitted = emitter.get_buffer();
|
|
503
|
+
// should we append a source map url?
|
|
504
|
+
if (!c_options.omit_source_map_url) {
|
|
505
|
+
// generate an embedded source map
|
|
506
|
+
if (c_options.source_map_embed) {
|
|
507
|
+
emitted.buffer += linefeed;
|
|
508
|
+
emitted.buffer += format_embedded_source_map();
|
|
509
|
+
}
|
|
510
|
+
// or just link the generated one
|
|
511
|
+
else if (source_map_file != "") {
|
|
512
|
+
emitted.buffer += linefeed;
|
|
513
|
+
emitted.buffer += format_source_mapping_url(source_map_file);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
// create a copy of the resulting buffer string
|
|
517
|
+
// this must be freed or taken over by implementor
|
|
518
|
+
return sass_copy_c_string(emitted.buffer.c_str());
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
void Context::apply_custom_headers(Block_Obj root, const char* ctx_path, SourceSpan pstate)
|
|
522
|
+
{
|
|
523
|
+
// create a custom import to resolve headers
|
|
524
|
+
Import_Obj imp = SASS_MEMORY_NEW(Import, pstate);
|
|
525
|
+
// dispatch headers which will add custom functions
|
|
526
|
+
// custom headers are added to the import instance
|
|
527
|
+
call_headers(entry_path, ctx_path, pstate, imp);
|
|
528
|
+
// increase head count to skip later
|
|
529
|
+
head_imports += resources.size() - 1;
|
|
530
|
+
// add the statement if we have urls
|
|
531
|
+
if (!imp->urls().empty()) root->append(imp);
|
|
532
|
+
// process all other resources (add Import_Stub nodes)
|
|
533
|
+
for (size_t i = 0, S = imp->incs().size(); i < S; ++i) {
|
|
534
|
+
root->append(SASS_MEMORY_NEW(Import_Stub, pstate, imp->incs()[i]));
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
Block_Obj File_Context::parse()
|
|
539
|
+
{
|
|
540
|
+
|
|
541
|
+
// check if entry file is given
|
|
542
|
+
if (input_path.empty()) return {};
|
|
543
|
+
|
|
544
|
+
// create absolute path from input filename
|
|
545
|
+
// ToDo: this should be resolved via custom importers
|
|
546
|
+
sass::string abs_path(rel2abs(input_path, CWD));
|
|
547
|
+
|
|
548
|
+
// try to load the entry file
|
|
549
|
+
char* contents = read_file(abs_path);
|
|
550
|
+
|
|
551
|
+
// alternatively also look inside each include path folder
|
|
552
|
+
// I think this differs from ruby sass (IMO too late to remove)
|
|
553
|
+
for (size_t i = 0, S = include_paths.size(); contents == 0 && i < S; ++i) {
|
|
554
|
+
// build absolute path for this include path entry
|
|
555
|
+
abs_path = rel2abs(input_path, include_paths[i]);
|
|
556
|
+
// try to load the resulting path
|
|
557
|
+
contents = read_file(abs_path);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// abort early if no content could be loaded (various reasons)
|
|
561
|
+
if (!contents) throw std::runtime_error(
|
|
562
|
+
"File to read not found or unreadable: "
|
|
563
|
+
+ std::string(input_path.c_str()));
|
|
564
|
+
|
|
565
|
+
// store entry path
|
|
566
|
+
entry_path = abs_path;
|
|
567
|
+
|
|
568
|
+
// create entry only for import stack
|
|
569
|
+
Sass_Import_Entry import = sass_make_import(
|
|
570
|
+
input_path.c_str(),
|
|
571
|
+
entry_path.c_str(),
|
|
572
|
+
contents,
|
|
573
|
+
0
|
|
574
|
+
);
|
|
575
|
+
// add the entry to the stack
|
|
576
|
+
import_stack.push_back(import);
|
|
577
|
+
|
|
578
|
+
// create the source entry for file entry
|
|
579
|
+
register_resource({{ input_path, "." }, abs_path }, { contents, 0 });
|
|
580
|
+
|
|
581
|
+
// create root ast tree node
|
|
582
|
+
return compile();
|
|
583
|
+
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
Block_Obj Data_Context::parse()
|
|
587
|
+
{
|
|
588
|
+
|
|
589
|
+
// check if source string is given
|
|
590
|
+
if (!source_c_str) return {};
|
|
591
|
+
|
|
592
|
+
// convert indented sass syntax
|
|
593
|
+
if(c_options.is_indented_syntax_src) {
|
|
594
|
+
// call sass2scss to convert the string
|
|
595
|
+
char * converted = sass2scss(source_c_str,
|
|
596
|
+
// preserve the structure as much as possible
|
|
597
|
+
SASS2SCSS_PRETTIFY_1 | SASS2SCSS_KEEP_COMMENT);
|
|
598
|
+
// replace old source_c_str with converted
|
|
599
|
+
free(source_c_str); source_c_str = converted;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// remember entry path (defaults to stdin for string)
|
|
603
|
+
entry_path = input_path.empty() ? "stdin" : input_path;
|
|
604
|
+
|
|
605
|
+
// ToDo: this may be resolved via custom importers
|
|
606
|
+
sass::string abs_path(rel2abs(entry_path));
|
|
607
|
+
char* abs_path_c_str = sass_copy_c_string(abs_path.c_str());
|
|
608
|
+
strings.push_back(abs_path_c_str);
|
|
609
|
+
|
|
610
|
+
// create entry only for the import stack
|
|
611
|
+
Sass_Import_Entry import = sass_make_import(
|
|
612
|
+
entry_path.c_str(),
|
|
613
|
+
abs_path_c_str,
|
|
614
|
+
source_c_str,
|
|
615
|
+
srcmap_c_str
|
|
616
|
+
);
|
|
617
|
+
// add the entry to the stack
|
|
618
|
+
import_stack.push_back(import);
|
|
619
|
+
|
|
620
|
+
// register a synthetic resource (path does not really exist, skip in includes)
|
|
621
|
+
register_resource({{ input_path, "." }, input_path }, { source_c_str, srcmap_c_str });
|
|
622
|
+
|
|
623
|
+
// create root ast tree node
|
|
624
|
+
return compile();
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// parse root block from includes
|
|
628
|
+
Block_Obj Context::compile()
|
|
629
|
+
{
|
|
630
|
+
// abort if there is no data
|
|
631
|
+
if (resources.size() == 0) return {};
|
|
632
|
+
// get root block from the first style sheet
|
|
633
|
+
Block_Obj root = sheets.at(entry_path).root;
|
|
634
|
+
// abort on invalid root
|
|
635
|
+
if (root.isNull()) return {};
|
|
636
|
+
Env global; // create root environment
|
|
637
|
+
// register built-in functions on env
|
|
638
|
+
register_built_in_functions(*this, &global);
|
|
639
|
+
// register custom functions (defined via C-API)
|
|
640
|
+
for (size_t i = 0, S = c_functions.size(); i < S; ++i)
|
|
641
|
+
{ register_c_function(*this, &global, c_functions[i]); }
|
|
642
|
+
// create initial backtrace entry
|
|
643
|
+
// create crtp visitor objects
|
|
644
|
+
Expand expand(*this, &global);
|
|
645
|
+
Cssize cssize(*this);
|
|
646
|
+
CheckNesting check_nesting;
|
|
647
|
+
// check nesting in all files
|
|
648
|
+
for (auto sheet : sheets) {
|
|
649
|
+
auto styles = sheet.second;
|
|
650
|
+
check_nesting(styles.root);
|
|
651
|
+
}
|
|
652
|
+
// expand and eval the tree
|
|
653
|
+
root = expand(root);
|
|
654
|
+
|
|
655
|
+
Extension unsatisfied;
|
|
656
|
+
// check that all extends were used
|
|
657
|
+
if (extender.checkForUnsatisfiedExtends(unsatisfied)) {
|
|
658
|
+
throw Exception::UnsatisfiedExtend(traces, unsatisfied);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// check nesting
|
|
662
|
+
check_nesting(root);
|
|
663
|
+
// merge and bubble certain rules
|
|
664
|
+
root = cssize(root);
|
|
665
|
+
|
|
666
|
+
// clean up by removing empty placeholders
|
|
667
|
+
// ToDo: maybe we can do this somewhere else?
|
|
668
|
+
Remove_Placeholders remove_placeholders;
|
|
669
|
+
root->perform(&remove_placeholders);
|
|
670
|
+
|
|
671
|
+
// return processed tree
|
|
672
|
+
return root;
|
|
673
|
+
}
|
|
674
|
+
// EO compile
|
|
675
|
+
|
|
676
|
+
sass::string Context::format_embedded_source_map()
|
|
677
|
+
{
|
|
678
|
+
sass::string map = emitter.render_srcmap(*this);
|
|
679
|
+
sass::istream is( map.c_str() );
|
|
680
|
+
sass::ostream buffer;
|
|
681
|
+
base64::encoder E;
|
|
682
|
+
E.encode(is, buffer);
|
|
683
|
+
sass::string url = "data:application/json;base64," + buffer.str();
|
|
684
|
+
url.erase(url.size() - 1);
|
|
685
|
+
return "/*# sourceMappingURL=" + url + " */";
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
sass::string Context::format_source_mapping_url(const sass::string& file)
|
|
689
|
+
{
|
|
690
|
+
sass::string url = abs2rel(file, output_path, CWD);
|
|
691
|
+
return "/*# sourceMappingURL=" + url + " */";
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
char* Context::render_srcmap()
|
|
695
|
+
{
|
|
696
|
+
if (source_map_file == "") return 0;
|
|
697
|
+
sass::string map = emitter.render_srcmap(*this);
|
|
698
|
+
return sass_copy_c_string(map.c_str());
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
// for data context we want to start after "stdin"
|
|
703
|
+
// we probably always want to skip the header includes?
|
|
704
|
+
sass::vector<sass::string> Context::get_included_files(bool skip, size_t headers)
|
|
705
|
+
{
|
|
706
|
+
// create a copy of the vector for manipulations
|
|
707
|
+
sass::vector<sass::string> includes = included_files;
|
|
708
|
+
if (includes.size() == 0) return includes;
|
|
709
|
+
if (skip) { includes.erase( includes.begin(), includes.begin() + 1 + headers); }
|
|
710
|
+
else { includes.erase( includes.begin() + 1, includes.begin() + 1 + headers); }
|
|
711
|
+
includes.erase( std::unique( includes.begin(), includes.end() ), includes.end() );
|
|
712
|
+
std::sort( includes.begin() + (skip ? 0 : 1), includes.end() );
|
|
713
|
+
return includes;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
void register_function(Context& ctx, Signature sig, Native_Function f, Env* env)
|
|
717
|
+
{
|
|
718
|
+
Definition* def = make_native_function(sig, f, ctx);
|
|
719
|
+
def->environment(env);
|
|
720
|
+
(*env)[def->name() + "[f]"] = def;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
void register_function(Context& ctx, Signature sig, Native_Function f, size_t arity, Env* env)
|
|
724
|
+
{
|
|
725
|
+
Definition* def = make_native_function(sig, f, ctx);
|
|
726
|
+
sass::ostream ss;
|
|
727
|
+
ss << def->name() << "[f]" << arity;
|
|
728
|
+
def->environment(env);
|
|
729
|
+
(*env)[ss.str()] = def;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
void register_overload_stub(Context& ctx, sass::string name, Env* env)
|
|
733
|
+
{
|
|
734
|
+
Definition* stub = SASS_MEMORY_NEW(Definition,
|
|
735
|
+
SourceSpan{ "[built-in function]" },
|
|
736
|
+
nullptr,
|
|
737
|
+
name,
|
|
738
|
+
Parameters_Obj{},
|
|
739
|
+
nullptr,
|
|
740
|
+
true);
|
|
741
|
+
(*env)[name + "[f]"] = stub;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
void register_built_in_functions(Context& ctx, Env* env)
|
|
746
|
+
{
|
|
747
|
+
using namespace Functions;
|
|
748
|
+
// RGB Functions (CSS Colors Level 4: rgb() now supports optional alpha)
|
|
749
|
+
register_function(ctx, rgb_sig, rgb, env);
|
|
750
|
+
register_overload_stub(ctx, "rgba", env);
|
|
751
|
+
register_function(ctx, rgba_4_sig, rgba_4, 4, env);
|
|
752
|
+
register_function(ctx, rgba_2_sig, rgba_2, 2, env);
|
|
753
|
+
register_function(ctx, red_sig, red, env);
|
|
754
|
+
register_function(ctx, green_sig, green, env);
|
|
755
|
+
register_function(ctx, blue_sig, blue, env);
|
|
756
|
+
register_function(ctx, mix_sig, mix, env);
|
|
757
|
+
// HSL Functions (CSS Colors Level 4: hsl() now supports optional alpha)
|
|
758
|
+
register_function(ctx, hsl_sig, hsl, env);
|
|
759
|
+
register_function(ctx, hsla_sig, hsla, env);
|
|
760
|
+
register_function(ctx, hue_sig, hue, env);
|
|
761
|
+
register_function(ctx, saturation_sig, saturation, env);
|
|
762
|
+
register_function(ctx, lightness_sig, lightness, env);
|
|
763
|
+
register_function(ctx, adjust_hue_sig, adjust_hue, env);
|
|
764
|
+
register_function(ctx, lighten_sig, lighten, env);
|
|
765
|
+
register_function(ctx, darken_sig, darken, env);
|
|
766
|
+
register_function(ctx, saturate_sig, saturate, env);
|
|
767
|
+
register_function(ctx, desaturate_sig, desaturate, env);
|
|
768
|
+
register_function(ctx, grayscale_sig, grayscale, env);
|
|
769
|
+
register_function(ctx, complement_sig, complement, env);
|
|
770
|
+
register_function(ctx, invert_sig, invert, env);
|
|
771
|
+
// Opacity Functions
|
|
772
|
+
register_function(ctx, alpha_sig, alpha, env);
|
|
773
|
+
register_function(ctx, opacity_sig, alpha, env);
|
|
774
|
+
register_function(ctx, opacify_sig, opacify, env);
|
|
775
|
+
register_function(ctx, fade_in_sig, opacify, env);
|
|
776
|
+
register_function(ctx, transparentize_sig, transparentize, env);
|
|
777
|
+
register_function(ctx, fade_out_sig, transparentize, env);
|
|
778
|
+
// Other Color Functions
|
|
779
|
+
register_function(ctx, adjust_color_sig, adjust_color, env);
|
|
780
|
+
register_function(ctx, scale_color_sig, scale_color, env);
|
|
781
|
+
register_function(ctx, change_color_sig, change_color, env);
|
|
782
|
+
register_function(ctx, ie_hex_str_sig, ie_hex_str, env);
|
|
783
|
+
// CSS Colors Level 4 Functions
|
|
784
|
+
register_function(ctx, hwb_sig, hwb, env);
|
|
785
|
+
register_function(ctx, lab_sig, lab, env);
|
|
786
|
+
register_function(ctx, lch_sig, lch, env);
|
|
787
|
+
register_function(ctx, oklab_sig, oklab, env);
|
|
788
|
+
register_function(ctx, oklch_sig, oklch, env);
|
|
789
|
+
register_function(ctx, color_sig, color, env);
|
|
790
|
+
// String Functions
|
|
791
|
+
register_function(ctx, unquote_sig, sass_unquote, env);
|
|
792
|
+
register_function(ctx, quote_sig, sass_quote, env);
|
|
793
|
+
register_function(ctx, str_length_sig, str_length, env);
|
|
794
|
+
register_function(ctx, str_insert_sig, str_insert, env);
|
|
795
|
+
register_function(ctx, str_index_sig, str_index, env);
|
|
796
|
+
register_function(ctx, str_slice_sig, str_slice, env);
|
|
797
|
+
register_function(ctx, to_upper_case_sig, to_upper_case, env);
|
|
798
|
+
register_function(ctx, to_lower_case_sig, to_lower_case, env);
|
|
799
|
+
// Number Functions
|
|
800
|
+
register_function(ctx, percentage_sig, percentage, env);
|
|
801
|
+
register_function(ctx, round_sig, round, env);
|
|
802
|
+
register_function(ctx, ceil_sig, ceil, env);
|
|
803
|
+
register_function(ctx, floor_sig, floor, env);
|
|
804
|
+
register_function(ctx, abs_sig, abs, env);
|
|
805
|
+
register_function(ctx, min_sig, min, env);
|
|
806
|
+
register_function(ctx, max_sig, max, env);
|
|
807
|
+
register_function(ctx, random_sig, random, env);
|
|
808
|
+
// List Functions
|
|
809
|
+
register_function(ctx, length_sig, length, env);
|
|
810
|
+
register_function(ctx, nth_sig, nth, env);
|
|
811
|
+
register_function(ctx, set_nth_sig, set_nth, env);
|
|
812
|
+
register_function(ctx, index_sig, index, env);
|
|
813
|
+
register_function(ctx, join_sig, join, env);
|
|
814
|
+
register_function(ctx, append_sig, append, env);
|
|
815
|
+
register_function(ctx, zip_sig, zip, env);
|
|
816
|
+
register_function(ctx, list_separator_sig, list_separator, env);
|
|
817
|
+
register_function(ctx, is_bracketed_sig, is_bracketed, env);
|
|
818
|
+
// Map Functions
|
|
819
|
+
register_function(ctx, map_get_sig, map_get, env);
|
|
820
|
+
register_function(ctx, map_merge_sig, map_merge, env);
|
|
821
|
+
register_function(ctx, map_remove_sig, map_remove, env);
|
|
822
|
+
register_function(ctx, map_keys_sig, map_keys, env);
|
|
823
|
+
register_function(ctx, map_values_sig, map_values, env);
|
|
824
|
+
register_function(ctx, map_has_key_sig, map_has_key, env);
|
|
825
|
+
register_function(ctx, keywords_sig, keywords, env);
|
|
826
|
+
// Introspection Functions
|
|
827
|
+
register_function(ctx, type_of_sig, type_of, env);
|
|
828
|
+
register_function(ctx, unit_sig, unit, env);
|
|
829
|
+
register_function(ctx, unitless_sig, unitless, env);
|
|
830
|
+
register_function(ctx, comparable_sig, comparable, env);
|
|
831
|
+
register_function(ctx, variable_exists_sig, variable_exists, env);
|
|
832
|
+
register_function(ctx, global_variable_exists_sig, global_variable_exists, env);
|
|
833
|
+
register_function(ctx, function_exists_sig, function_exists, env);
|
|
834
|
+
register_function(ctx, mixin_exists_sig, mixin_exists, env);
|
|
835
|
+
register_function(ctx, feature_exists_sig, feature_exists, env);
|
|
836
|
+
register_function(ctx, call_sig, call, env);
|
|
837
|
+
register_function(ctx, content_exists_sig, content_exists, env);
|
|
838
|
+
register_function(ctx, get_function_sig, get_function, env);
|
|
839
|
+
// Boolean Functions
|
|
840
|
+
register_function(ctx, not_sig, sass_not, env);
|
|
841
|
+
register_function(ctx, if_sig, sass_if, env);
|
|
842
|
+
// Misc Functions
|
|
843
|
+
register_function(ctx, inspect_sig, inspect, env);
|
|
844
|
+
register_function(ctx, unique_id_sig, unique_id, env);
|
|
845
|
+
// Selector functions
|
|
846
|
+
register_function(ctx, selector_nest_sig, selector_nest, env);
|
|
847
|
+
register_function(ctx, selector_append_sig, selector_append, env);
|
|
848
|
+
register_function(ctx, selector_extend_sig, selector_extend, env);
|
|
849
|
+
register_function(ctx, selector_replace_sig, selector_replace, env);
|
|
850
|
+
register_function(ctx, selector_unify_sig, selector_unify, env);
|
|
851
|
+
register_function(ctx, is_superselector_sig, is_superselector, env);
|
|
852
|
+
register_function(ctx, simple_selectors_sig, simple_selectors, env);
|
|
853
|
+
register_function(ctx, selector_parse_sig, selector_parse, env);
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
void register_c_functions(Context& ctx, Env* env, Sass_Function_List descrs)
|
|
857
|
+
{
|
|
858
|
+
while (descrs && *descrs) {
|
|
859
|
+
register_c_function(ctx, env, *descrs);
|
|
860
|
+
++descrs;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
void register_c_function(Context& ctx, Env* env, Sass_Function_Entry descr)
|
|
864
|
+
{
|
|
865
|
+
Definition* def = make_c_function(descr, ctx);
|
|
866
|
+
def->environment(env);
|
|
867
|
+
(*env)[def->name() + "[f]"] = def;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
}
|