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,531 @@
|
|
|
1
|
+
// sass.hpp must go before all system headers to get the
|
|
2
|
+
// __EXTENSIONS__ fix on Solaris.
|
|
3
|
+
#include "sass.hpp"
|
|
4
|
+
|
|
5
|
+
#ifdef _WIN32
|
|
6
|
+
# ifdef __MINGW32__
|
|
7
|
+
# ifndef off64_t
|
|
8
|
+
# define off64_t _off64_t /* Workaround for http://sourceforge.net/p/mingw/bugs/2024/ */
|
|
9
|
+
# endif
|
|
10
|
+
# endif
|
|
11
|
+
# include <direct.h>
|
|
12
|
+
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
|
13
|
+
#else
|
|
14
|
+
# include <unistd.h>
|
|
15
|
+
#endif
|
|
16
|
+
#include <cstdio>
|
|
17
|
+
#include <vector>
|
|
18
|
+
#include <algorithm>
|
|
19
|
+
#include <sys/stat.h>
|
|
20
|
+
#include "file.hpp"
|
|
21
|
+
#include "context.hpp"
|
|
22
|
+
#include "prelexer.hpp"
|
|
23
|
+
#include "utf8_string.hpp"
|
|
24
|
+
#include "sass_functions.hpp"
|
|
25
|
+
#include "error_handling.hpp"
|
|
26
|
+
#include "util.hpp"
|
|
27
|
+
#include "util_string.hpp"
|
|
28
|
+
#include "sass2scss.h"
|
|
29
|
+
|
|
30
|
+
#ifdef _WIN32
|
|
31
|
+
# include <windows.h>
|
|
32
|
+
|
|
33
|
+
# ifdef _MSC_VER
|
|
34
|
+
# include <codecvt>
|
|
35
|
+
inline static Sass::sass::string wstring_to_string(const std::wstring& wstr)
|
|
36
|
+
{
|
|
37
|
+
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wchar_converter;
|
|
38
|
+
return wchar_converter.to_bytes(wstr);
|
|
39
|
+
}
|
|
40
|
+
# else // mingw(/gcc) does not support C++11's codecvt yet.
|
|
41
|
+
inline static Sass::sass::string wstring_to_string(const std::wstring &wstr)
|
|
42
|
+
{
|
|
43
|
+
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
|
|
44
|
+
Sass::sass::string strTo(size_needed, 0);
|
|
45
|
+
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
|
|
46
|
+
return strTo;
|
|
47
|
+
}
|
|
48
|
+
# endif
|
|
49
|
+
#endif
|
|
50
|
+
|
|
51
|
+
namespace Sass {
|
|
52
|
+
namespace File {
|
|
53
|
+
|
|
54
|
+
// return the current directory
|
|
55
|
+
// always with forward slashes
|
|
56
|
+
// always with trailing slash
|
|
57
|
+
sass::string get_cwd()
|
|
58
|
+
{
|
|
59
|
+
const size_t wd_len = 4096;
|
|
60
|
+
#ifndef _WIN32
|
|
61
|
+
char wd[wd_len];
|
|
62
|
+
char* pwd = getcwd(wd, wd_len);
|
|
63
|
+
// we should check error for more detailed info (e.g. ENOENT)
|
|
64
|
+
// http://man7.org/linux/man-pages/man2/getcwd.2.html#ERRORS
|
|
65
|
+
if (pwd == NULL) throw Exception::OperationError("cwd gone missing");
|
|
66
|
+
sass::string cwd = pwd;
|
|
67
|
+
#else
|
|
68
|
+
wchar_t wd[wd_len];
|
|
69
|
+
wchar_t* pwd = _wgetcwd(wd, wd_len);
|
|
70
|
+
if (pwd == NULL) throw Exception::OperationError("cwd gone missing");
|
|
71
|
+
sass::string cwd = wstring_to_string(pwd);
|
|
72
|
+
//convert backslashes to forward slashes
|
|
73
|
+
replace(cwd.begin(), cwd.end(), '\\', '/');
|
|
74
|
+
#endif
|
|
75
|
+
if (cwd[cwd.length() - 1] != '/') cwd += '/';
|
|
76
|
+
return cwd;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// test if path exists and is a file
|
|
80
|
+
bool file_exists(const sass::string& path)
|
|
81
|
+
{
|
|
82
|
+
#ifdef _WIN32
|
|
83
|
+
wchar_t resolved[32768];
|
|
84
|
+
// windows unicode filepaths are encoded in utf16
|
|
85
|
+
sass::string abspath(join_paths(get_cwd(), path));
|
|
86
|
+
if (!(abspath[0] == '/' && abspath[1] == '/')) {
|
|
87
|
+
abspath = "//?/" + abspath;
|
|
88
|
+
}
|
|
89
|
+
std::wstring wpath(UTF_8::convert_to_utf16(abspath));
|
|
90
|
+
std::replace(wpath.begin(), wpath.end(), '/', '\\');
|
|
91
|
+
DWORD rv = GetFullPathNameW(wpath.c_str(), 32767, resolved, NULL);
|
|
92
|
+
if (rv > 32767) throw Exception::OperationError("Path is too long");
|
|
93
|
+
if (rv == 0) throw Exception::OperationError("Path could not be resolved");
|
|
94
|
+
DWORD dwAttrib = GetFileAttributesW(resolved);
|
|
95
|
+
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
|
|
96
|
+
(!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)));
|
|
97
|
+
#else
|
|
98
|
+
struct stat st_buf;
|
|
99
|
+
return (stat (path.c_str(), &st_buf) == 0) &&
|
|
100
|
+
(!S_ISDIR (st_buf.st_mode));
|
|
101
|
+
#endif
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// return if given path is absolute
|
|
105
|
+
// works with *nix and windows paths
|
|
106
|
+
bool is_absolute_path(const sass::string& path)
|
|
107
|
+
{
|
|
108
|
+
#ifdef _WIN32
|
|
109
|
+
if (path.length() >= 2 && Util::ascii_isalpha(path[0]) && path[1] == ':') return true;
|
|
110
|
+
#endif
|
|
111
|
+
size_t i = 0;
|
|
112
|
+
// check if we have a protocol
|
|
113
|
+
if (path[i] && Util::ascii_isalpha(static_cast<unsigned char>(path[i]))) {
|
|
114
|
+
// skip over all alphanumeric characters
|
|
115
|
+
while (path[i] && Util::ascii_isalnum(static_cast<unsigned char>(path[i]))) ++i;
|
|
116
|
+
i = i && path[i] == ':' ? i + 1 : 0;
|
|
117
|
+
}
|
|
118
|
+
return path[i] == '/';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// helper function to find the last directory separator
|
|
122
|
+
inline size_t find_last_folder_separator(const sass::string& path, size_t limit = sass::string::npos)
|
|
123
|
+
{
|
|
124
|
+
size_t pos;
|
|
125
|
+
size_t pos_p = path.find_last_of('/', limit);
|
|
126
|
+
#ifdef _WIN32
|
|
127
|
+
size_t pos_w = path.find_last_of('\\', limit);
|
|
128
|
+
#else
|
|
129
|
+
size_t pos_w = sass::string::npos;
|
|
130
|
+
#endif
|
|
131
|
+
if (pos_p != sass::string::npos && pos_w != sass::string::npos) {
|
|
132
|
+
pos = std::max(pos_p, pos_w);
|
|
133
|
+
}
|
|
134
|
+
else if (pos_p != sass::string::npos) {
|
|
135
|
+
pos = pos_p;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
pos = pos_w;
|
|
139
|
+
}
|
|
140
|
+
return pos;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// return only the directory part of path
|
|
144
|
+
sass::string dir_name(const sass::string& path)
|
|
145
|
+
{
|
|
146
|
+
size_t pos = find_last_folder_separator(path);
|
|
147
|
+
if (pos == sass::string::npos) return "";
|
|
148
|
+
else return path.substr(0, pos+1);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// return only the filename part of path
|
|
152
|
+
sass::string base_name(const sass::string& path)
|
|
153
|
+
{
|
|
154
|
+
size_t pos = find_last_folder_separator(path);
|
|
155
|
+
if (pos == sass::string::npos) return path;
|
|
156
|
+
else return path.substr(pos+1);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// do a logical clean up of the path
|
|
160
|
+
// no physical check on the filesystem
|
|
161
|
+
sass::string make_canonical_path (sass::string path)
|
|
162
|
+
{
|
|
163
|
+
|
|
164
|
+
// declarations
|
|
165
|
+
size_t pos;
|
|
166
|
+
|
|
167
|
+
#ifdef _WIN32
|
|
168
|
+
//convert backslashes to forward slashes
|
|
169
|
+
replace(path.begin(), path.end(), '\\', '/');
|
|
170
|
+
#endif
|
|
171
|
+
|
|
172
|
+
pos = 0; // remove all self references inside the path string
|
|
173
|
+
while((pos = path.find("/./", pos)) != sass::string::npos) path.erase(pos, 2);
|
|
174
|
+
|
|
175
|
+
// remove all leading and trailing self references
|
|
176
|
+
while(path.size() >= 2 && path[0] == '.' && path[1] == '/') path.erase(0, 2);
|
|
177
|
+
while((pos = path.length()) > 1 && path[pos - 2] == '/' && path[pos - 1] == '.') path.erase(pos - 2);
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
size_t proto = 0;
|
|
181
|
+
// check if we have a protocol
|
|
182
|
+
if (path[proto] && Util::ascii_isalpha(static_cast<unsigned char>(path[proto]))) {
|
|
183
|
+
// skip over all alphanumeric characters
|
|
184
|
+
while (path[proto] && Util::ascii_isalnum(static_cast<unsigned char>(path[proto++]))) {}
|
|
185
|
+
// then skip over the mandatory colon
|
|
186
|
+
if (proto && path[proto] == ':') ++ proto;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// then skip over start slashes
|
|
190
|
+
while (path[proto++] == '/') {}
|
|
191
|
+
|
|
192
|
+
pos = proto; // collapse multiple delimiters into a single one
|
|
193
|
+
while((pos = path.find("//", pos)) != sass::string::npos) path.erase(pos, 1);
|
|
194
|
+
|
|
195
|
+
return path;
|
|
196
|
+
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// join two path segments cleanly together
|
|
200
|
+
// but only if right side is not absolute yet
|
|
201
|
+
sass::string join_paths(sass::string l, sass::string r)
|
|
202
|
+
{
|
|
203
|
+
|
|
204
|
+
#ifdef _WIN32
|
|
205
|
+
// convert Windows backslashes to URL forward slashes
|
|
206
|
+
replace(l.begin(), l.end(), '\\', '/');
|
|
207
|
+
replace(r.begin(), r.end(), '\\', '/');
|
|
208
|
+
#endif
|
|
209
|
+
|
|
210
|
+
if (l.empty()) return r;
|
|
211
|
+
if (r.empty()) return l;
|
|
212
|
+
|
|
213
|
+
if (is_absolute_path(r)) return r;
|
|
214
|
+
if (l[l.length()-1] != '/') l += '/';
|
|
215
|
+
|
|
216
|
+
// this does a logical cleanup of the right hand path
|
|
217
|
+
// Note that this does collapse x/../y sections into y.
|
|
218
|
+
// This is by design. If /foo on your system is a symlink
|
|
219
|
+
// to /bar/baz, then /foo/../cd is actually /bar/cd,
|
|
220
|
+
// not /cd as a naive ../ removal would give you.
|
|
221
|
+
// will only work on leading double dot dirs on rhs
|
|
222
|
+
// therefore it is safe if lhs is already resolved cwd
|
|
223
|
+
while ((r.length() > 3) && ((r.substr(0, 3) == "../") || (r.substr(0, 3)) == "..\\")) {
|
|
224
|
+
size_t L = l.length(), pos = find_last_folder_separator(l, L - 2);
|
|
225
|
+
bool is_slash = pos + 2 == L && (l[pos+1] == '/' || l[pos+1] == '\\');
|
|
226
|
+
bool is_self = pos + 3 == L && (l[pos+1] == '.');
|
|
227
|
+
if (!is_self && !is_slash) r = r.substr(3);
|
|
228
|
+
else if (pos == sass::string::npos) break;
|
|
229
|
+
l = l.substr(0, pos == sass::string::npos ? pos : pos + 1);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return l + r;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
sass::string path_for_console(const sass::string& rel_path, const sass::string& abs_path, const sass::string& orig_path)
|
|
236
|
+
{
|
|
237
|
+
// magic algorithm goes here!!
|
|
238
|
+
|
|
239
|
+
// if the file is outside this directory show the absolute path
|
|
240
|
+
if (rel_path.substr(0, 3) == "../") {
|
|
241
|
+
return orig_path;
|
|
242
|
+
}
|
|
243
|
+
// this seems to work most of the time
|
|
244
|
+
return abs_path == orig_path ? abs_path : rel_path;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// create an absolute path by resolving relative paths with cwd
|
|
248
|
+
sass::string rel2abs(const sass::string& path, const sass::string& base, const sass::string& cwd)
|
|
249
|
+
{
|
|
250
|
+
sass::string rv = make_canonical_path(join_paths(join_paths(cwd + "/", base + "/"), path));
|
|
251
|
+
#ifdef _WIN32
|
|
252
|
+
// On windows we may get an absolute path without directory
|
|
253
|
+
// In that case we should prepend the directory from the root
|
|
254
|
+
if (rv[0] == '/' && rv[1] != '/') {
|
|
255
|
+
rv.insert(0, cwd, 0, 2);
|
|
256
|
+
}
|
|
257
|
+
#endif
|
|
258
|
+
return rv;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// create a path that is relative to the given base directory
|
|
262
|
+
// path and base will first be resolved against cwd to make them absolute
|
|
263
|
+
sass::string abs2rel(const sass::string& path, const sass::string& base, const sass::string& cwd)
|
|
264
|
+
{
|
|
265
|
+
|
|
266
|
+
sass::string abs_path = rel2abs(path, cwd);
|
|
267
|
+
sass::string abs_base = rel2abs(base, cwd);
|
|
268
|
+
|
|
269
|
+
size_t proto = 0;
|
|
270
|
+
// check if we have a protocol
|
|
271
|
+
if (path[proto] && Util::ascii_isalpha(static_cast<unsigned char>(path[proto]))) {
|
|
272
|
+
// skip over all alphanumeric characters
|
|
273
|
+
while (path[proto] && Util::ascii_isalnum(static_cast<unsigned char>(path[proto++]))) {}
|
|
274
|
+
// then skip over the mandatory colon
|
|
275
|
+
if (proto && path[proto] == ':') ++ proto;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// distinguish between windows absolute paths and valid protocols
|
|
279
|
+
// we assume that protocols must at least have two chars to be valid
|
|
280
|
+
if (proto && path[proto++] == '/' && proto > 3) return path;
|
|
281
|
+
|
|
282
|
+
#ifdef _WIN32
|
|
283
|
+
// absolute link must have a drive letter, and we know that we
|
|
284
|
+
// can only create relative links if both are on the same drive
|
|
285
|
+
if (abs_base[0] != abs_path[0]) return abs_path;
|
|
286
|
+
#endif
|
|
287
|
+
|
|
288
|
+
sass::string stripped_uri = "";
|
|
289
|
+
sass::string stripped_base = "";
|
|
290
|
+
|
|
291
|
+
size_t index = 0;
|
|
292
|
+
size_t minSize = std::min(abs_path.size(), abs_base.size());
|
|
293
|
+
for (size_t i = 0; i < minSize; ++i) {
|
|
294
|
+
#ifdef FS_CASE_SENSITIVE
|
|
295
|
+
if (abs_path[i] != abs_base[i]) break;
|
|
296
|
+
#else
|
|
297
|
+
// compare the charactes in a case insensitive manner
|
|
298
|
+
// windows fs is only case insensitive in ascii ranges
|
|
299
|
+
if (Util::ascii_tolower(static_cast<unsigned char>(abs_path[i])) !=
|
|
300
|
+
Util::ascii_tolower(static_cast<unsigned char>(abs_base[i]))) break;
|
|
301
|
+
#endif
|
|
302
|
+
if (abs_path[i] == '/') index = i + 1;
|
|
303
|
+
}
|
|
304
|
+
for (size_t i = index; i < abs_path.size(); ++i) {
|
|
305
|
+
stripped_uri += abs_path[i];
|
|
306
|
+
}
|
|
307
|
+
for (size_t i = index; i < abs_base.size(); ++i) {
|
|
308
|
+
stripped_base += abs_base[i];
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
size_t left = 0;
|
|
312
|
+
size_t directories = 0;
|
|
313
|
+
for (size_t right = 0; right < stripped_base.size(); ++right) {
|
|
314
|
+
if (stripped_base[right] == '/') {
|
|
315
|
+
if (stripped_base.substr(left, 2) != "..") {
|
|
316
|
+
++directories;
|
|
317
|
+
}
|
|
318
|
+
else if (directories > 1) {
|
|
319
|
+
--directories;
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
directories = 0;
|
|
323
|
+
}
|
|
324
|
+
left = right + 1;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
sass::string result = "";
|
|
329
|
+
for (size_t i = 0; i < directories; ++i) {
|
|
330
|
+
result += "../";
|
|
331
|
+
}
|
|
332
|
+
result += stripped_uri;
|
|
333
|
+
|
|
334
|
+
return result;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Resolution order for ambiguous imports:
|
|
338
|
+
// (1) filename as given
|
|
339
|
+
// (2) underscore + given
|
|
340
|
+
// (3) underscore + given + extension
|
|
341
|
+
// (4) given + extension
|
|
342
|
+
// (5) given + _index.scss
|
|
343
|
+
// (6) given + _index.sass
|
|
344
|
+
sass::vector<Include> resolve_includes(const sass::string& root, const sass::string& file, const sass::vector<sass::string>& exts)
|
|
345
|
+
{
|
|
346
|
+
sass::string filename = join_paths(root, file);
|
|
347
|
+
// split the filename
|
|
348
|
+
sass::string base(dir_name(file));
|
|
349
|
+
sass::string name(base_name(file));
|
|
350
|
+
sass::vector<Include> includes;
|
|
351
|
+
// create full path (maybe relative)
|
|
352
|
+
sass::string rel_path(join_paths(base, name));
|
|
353
|
+
sass::string abs_path(join_paths(root, rel_path));
|
|
354
|
+
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
|
|
355
|
+
// next test variation with underscore
|
|
356
|
+
rel_path = join_paths(base, "_" + name);
|
|
357
|
+
abs_path = join_paths(root, rel_path);
|
|
358
|
+
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
|
|
359
|
+
// next test exts plus underscore
|
|
360
|
+
for(auto ext : exts) {
|
|
361
|
+
rel_path = join_paths(base, "_" + name + ext);
|
|
362
|
+
abs_path = join_paths(root, rel_path);
|
|
363
|
+
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
|
|
364
|
+
}
|
|
365
|
+
// next test plain name with exts
|
|
366
|
+
for(auto ext : exts) {
|
|
367
|
+
rel_path = join_paths(base, name + ext);
|
|
368
|
+
abs_path = join_paths(root, rel_path);
|
|
369
|
+
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
|
|
370
|
+
}
|
|
371
|
+
// index files
|
|
372
|
+
if (includes.size() == 0) {
|
|
373
|
+
// ignore directories that look like @import'able filename
|
|
374
|
+
for(auto ext : exts) {
|
|
375
|
+
if (ends_with(name, ext)) return includes;
|
|
376
|
+
}
|
|
377
|
+
// next test underscore index exts
|
|
378
|
+
for(auto ext : exts) {
|
|
379
|
+
rel_path = join_paths(base, join_paths(name, "_index" + ext));
|
|
380
|
+
abs_path = join_paths(root, rel_path);
|
|
381
|
+
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
|
|
382
|
+
}
|
|
383
|
+
// next test plain index exts
|
|
384
|
+
for(auto ext : exts) {
|
|
385
|
+
rel_path = join_paths(base, join_paths(name, "index" + ext));
|
|
386
|
+
abs_path = join_paths(root, rel_path);
|
|
387
|
+
if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
// nothing found
|
|
391
|
+
return includes;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
sass::vector<sass::string> find_files(const sass::string& file, const sass::vector<sass::string> paths)
|
|
395
|
+
{
|
|
396
|
+
sass::vector<sass::string> includes;
|
|
397
|
+
for (sass::string path : paths) {
|
|
398
|
+
sass::string abs_path(join_paths(path, file));
|
|
399
|
+
if (file_exists(abs_path)) includes.push_back(abs_path);
|
|
400
|
+
}
|
|
401
|
+
return includes;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
sass::vector<sass::string> find_files(const sass::string& file, struct Sass_Compiler* compiler)
|
|
405
|
+
{
|
|
406
|
+
// get the last import entry to get current base directory
|
|
407
|
+
// struct Sass_Options* options = sass_compiler_get_options(compiler);
|
|
408
|
+
Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
|
|
409
|
+
const sass::vector<sass::string>& incs = compiler->cpp_ctx->include_paths;
|
|
410
|
+
// create the vector with paths to lookup
|
|
411
|
+
sass::vector<sass::string> paths(1 + incs.size());
|
|
412
|
+
paths.push_back(dir_name(import->abs_path));
|
|
413
|
+
paths.insert(paths.end(), incs.begin(), incs.end());
|
|
414
|
+
// dispatch to find files in paths
|
|
415
|
+
return find_files(file, paths);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// helper function to search one file in all include paths
|
|
419
|
+
// this is normally not used internally by libsass (C-API sugar)
|
|
420
|
+
sass::string find_file(const sass::string& file, const sass::vector<sass::string> paths)
|
|
421
|
+
{
|
|
422
|
+
if (file.empty()) return file;
|
|
423
|
+
auto res = find_files(file, paths);
|
|
424
|
+
return res.empty() ? "" : res.front();
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// helper function to resolve a filename
|
|
428
|
+
sass::string find_include(const sass::string& file, const sass::vector<sass::string> paths)
|
|
429
|
+
{
|
|
430
|
+
// search in every include path for a match
|
|
431
|
+
for (size_t i = 0, S = paths.size(); i < S; ++i)
|
|
432
|
+
{
|
|
433
|
+
sass::vector<Include> resolved(resolve_includes(paths[i], file));
|
|
434
|
+
if (resolved.size()) return resolved[0].abs_path;
|
|
435
|
+
}
|
|
436
|
+
// nothing found
|
|
437
|
+
return sass::string("");
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// try to load the given filename
|
|
441
|
+
// returned memory must be freed
|
|
442
|
+
// will auto convert .sass files
|
|
443
|
+
char* read_file(const sass::string& path)
|
|
444
|
+
{
|
|
445
|
+
#ifdef _WIN32
|
|
446
|
+
BYTE* pBuffer;
|
|
447
|
+
DWORD dwBytes;
|
|
448
|
+
wchar_t resolved[32768];
|
|
449
|
+
// windows unicode filepaths are encoded in utf16
|
|
450
|
+
sass::string abspath(join_paths(get_cwd(), path));
|
|
451
|
+
if (!(abspath[0] == '/' && abspath[1] == '/')) {
|
|
452
|
+
abspath = "//?/" + abspath;
|
|
453
|
+
}
|
|
454
|
+
std::wstring wpath(UTF_8::convert_to_utf16(abspath));
|
|
455
|
+
std::replace(wpath.begin(), wpath.end(), '/', '\\');
|
|
456
|
+
DWORD rv = GetFullPathNameW(wpath.c_str(), 32767, resolved, NULL);
|
|
457
|
+
if (rv > 32767) throw Exception::OperationError("Path is too long");
|
|
458
|
+
if (rv == 0) throw Exception::OperationError("Path could not be resolved");
|
|
459
|
+
HANDLE hFile = CreateFileW(resolved, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
|
460
|
+
if (hFile == INVALID_HANDLE_VALUE) return 0;
|
|
461
|
+
DWORD dwFileLength = GetFileSize(hFile, NULL);
|
|
462
|
+
if (dwFileLength == INVALID_FILE_SIZE) return 0;
|
|
463
|
+
// allocate an extra byte for the null char
|
|
464
|
+
// and another one for edge-cases in lexer
|
|
465
|
+
pBuffer = (BYTE*)malloc((dwFileLength+2)*sizeof(BYTE));
|
|
466
|
+
ReadFile(hFile, pBuffer, dwFileLength, &dwBytes, NULL);
|
|
467
|
+
pBuffer[dwFileLength+0] = '\0';
|
|
468
|
+
pBuffer[dwFileLength+1] = '\0';
|
|
469
|
+
CloseHandle(hFile);
|
|
470
|
+
// just convert from unsigned char*
|
|
471
|
+
char* contents = (char*) pBuffer;
|
|
472
|
+
#else
|
|
473
|
+
// Read the file using `<cstdio>` instead of `<fstream>` for better portability.
|
|
474
|
+
// The `<fstream>` header initializes `<locale>` and this buggy in GCC4/5 with static linking.
|
|
475
|
+
// See:
|
|
476
|
+
// https://www.spinics.net/lists/gcchelp/msg46851.html
|
|
477
|
+
// https://github.com/sass/sassc-ruby/issues/128
|
|
478
|
+
struct stat st;
|
|
479
|
+
if (stat(path.c_str(), &st) == -1 || S_ISDIR(st.st_mode)) return 0;
|
|
480
|
+
FILE* fd = std::fopen(path.c_str(), "rb");
|
|
481
|
+
if (fd == nullptr) return nullptr;
|
|
482
|
+
const std::size_t size = st.st_size;
|
|
483
|
+
char* contents = static_cast<char*>(malloc(st.st_size + 2 * sizeof(char)));
|
|
484
|
+
if (std::fread(static_cast<void*>(contents), 1, size, fd) != size) {
|
|
485
|
+
free(contents);
|
|
486
|
+
std::fclose(fd);
|
|
487
|
+
return nullptr;
|
|
488
|
+
}
|
|
489
|
+
if (std::fclose(fd) != 0) {
|
|
490
|
+
free(contents);
|
|
491
|
+
return nullptr;
|
|
492
|
+
}
|
|
493
|
+
contents[size] = '\0';
|
|
494
|
+
contents[size + 1] = '\0';
|
|
495
|
+
#endif
|
|
496
|
+
sass::string extension;
|
|
497
|
+
if (path.length() > 5) {
|
|
498
|
+
extension = path.substr(path.length() - 5, 5);
|
|
499
|
+
}
|
|
500
|
+
Util::ascii_str_tolower(&extension);
|
|
501
|
+
if (extension == ".sass" && contents != 0) {
|
|
502
|
+
char * converted = sass2scss(contents, SASS2SCSS_PRETTIFY_1 | SASS2SCSS_KEEP_COMMENT);
|
|
503
|
+
free(contents); // free the indented contents
|
|
504
|
+
return converted; // should be freed by caller
|
|
505
|
+
} else {
|
|
506
|
+
return contents;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// split a path string delimited by semicolons or colons (OS dependent)
|
|
511
|
+
sass::vector<sass::string> split_path_list(const char* str)
|
|
512
|
+
{
|
|
513
|
+
sass::vector<sass::string> paths;
|
|
514
|
+
if (str == NULL) return paths;
|
|
515
|
+
// find delimiter via prelexer (return zero at end)
|
|
516
|
+
const char* end = Prelexer::find_first<PATH_SEP>(str);
|
|
517
|
+
// search until null delimiter
|
|
518
|
+
while (end) {
|
|
519
|
+
// add path from current position to delimiter
|
|
520
|
+
paths.push_back(sass::string(str, end - str));
|
|
521
|
+
str = end + 1; // skip delimiter
|
|
522
|
+
end = Prelexer::find_first<PATH_SEP>(str);
|
|
523
|
+
}
|
|
524
|
+
// add path from current position to end
|
|
525
|
+
paths.push_back(sass::string(str));
|
|
526
|
+
// return back
|
|
527
|
+
return paths;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
}
|
|
531
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#ifndef SASS_FILE_H
|
|
2
|
+
#define SASS_FILE_H
|
|
3
|
+
|
|
4
|
+
// sass.hpp must go before all system headers to get the
|
|
5
|
+
// __EXTENSIONS__ fix on Solaris.
|
|
6
|
+
#include "sass.hpp"
|
|
7
|
+
|
|
8
|
+
#include <string>
|
|
9
|
+
#include <vector>
|
|
10
|
+
|
|
11
|
+
#include "sass/context.h"
|
|
12
|
+
#include "ast_fwd_decl.hpp"
|
|
13
|
+
|
|
14
|
+
namespace Sass {
|
|
15
|
+
|
|
16
|
+
namespace File {
|
|
17
|
+
|
|
18
|
+
// return the current directory
|
|
19
|
+
// always with forward slashes
|
|
20
|
+
sass::string get_cwd();
|
|
21
|
+
|
|
22
|
+
// test if path exists and is a file
|
|
23
|
+
bool file_exists(const sass::string& file);
|
|
24
|
+
|
|
25
|
+
// return if given path is absolute
|
|
26
|
+
// works with *nix and windows paths
|
|
27
|
+
bool is_absolute_path(const sass::string& path);
|
|
28
|
+
|
|
29
|
+
// return only the directory part of path
|
|
30
|
+
sass::string dir_name(const sass::string& path);
|
|
31
|
+
|
|
32
|
+
// return only the filename part of path
|
|
33
|
+
sass::string base_name(const sass::string&);
|
|
34
|
+
|
|
35
|
+
// do a locigal clean up of the path
|
|
36
|
+
// no physical check on the filesystem
|
|
37
|
+
sass::string make_canonical_path (sass::string path);
|
|
38
|
+
|
|
39
|
+
// join two path segments cleanly together
|
|
40
|
+
// but only if right side is not absolute yet
|
|
41
|
+
sass::string join_paths(sass::string root, sass::string name);
|
|
42
|
+
|
|
43
|
+
// if the relative path is outside of the cwd we want want to
|
|
44
|
+
// show the absolute path in console messages
|
|
45
|
+
sass::string path_for_console(const sass::string& rel_path, const sass::string& abs_path, const sass::string& orig_path);
|
|
46
|
+
|
|
47
|
+
// create an absolute path by resolving relative paths with cwd
|
|
48
|
+
sass::string rel2abs(const sass::string& path, const sass::string& base = ".", const sass::string& cwd = get_cwd());
|
|
49
|
+
|
|
50
|
+
// create a path that is relative to the given base directory
|
|
51
|
+
// path and base will first be resolved against cwd to make them absolute
|
|
52
|
+
sass::string abs2rel(const sass::string& path, const sass::string& base = ".", const sass::string& cwd = get_cwd());
|
|
53
|
+
|
|
54
|
+
// helper function to resolve a filename
|
|
55
|
+
// searching without variations in all paths
|
|
56
|
+
sass::string find_file(const sass::string& file, struct Sass_Compiler* options);
|
|
57
|
+
sass::string find_file(const sass::string& file, const sass::vector<sass::string> paths);
|
|
58
|
+
|
|
59
|
+
// helper function to resolve a include filename
|
|
60
|
+
// this has the original resolve logic for sass include
|
|
61
|
+
sass::string find_include(const sass::string& file, const sass::vector<sass::string> paths);
|
|
62
|
+
|
|
63
|
+
// split a path string delimited by semicolons or colons (OS dependent)
|
|
64
|
+
sass::vector<sass::string> split_path_list(const char* paths);
|
|
65
|
+
|
|
66
|
+
// try to load the given filename
|
|
67
|
+
// returned memory must be freed
|
|
68
|
+
// will auto convert .sass files
|
|
69
|
+
char* read_file(const sass::string& file);
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// requested import
|
|
74
|
+
class Importer {
|
|
75
|
+
public:
|
|
76
|
+
// requested import path
|
|
77
|
+
sass::string imp_path;
|
|
78
|
+
// parent context path
|
|
79
|
+
sass::string ctx_path;
|
|
80
|
+
// base derived from context path
|
|
81
|
+
// this really just acts as a cache
|
|
82
|
+
sass::string base_path;
|
|
83
|
+
public:
|
|
84
|
+
Importer(sass::string imp_path, sass::string ctx_path)
|
|
85
|
+
: imp_path(File::make_canonical_path(imp_path)),
|
|
86
|
+
ctx_path(File::make_canonical_path(ctx_path)),
|
|
87
|
+
base_path(File::dir_name(ctx_path))
|
|
88
|
+
{ }
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// a resolved include (final import)
|
|
92
|
+
class Include : public Importer {
|
|
93
|
+
public:
|
|
94
|
+
// resolved absolute path
|
|
95
|
+
sass::string abs_path;
|
|
96
|
+
public:
|
|
97
|
+
Include(const Importer& imp, sass::string abs_path)
|
|
98
|
+
: Importer(imp), abs_path(abs_path)
|
|
99
|
+
{ }
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// a loaded resource
|
|
103
|
+
class Resource {
|
|
104
|
+
public:
|
|
105
|
+
// the file contents
|
|
106
|
+
char* contents;
|
|
107
|
+
// connected sourcemap
|
|
108
|
+
char* srcmap;
|
|
109
|
+
public:
|
|
110
|
+
Resource(char* contents, char* srcmap)
|
|
111
|
+
: contents(contents), srcmap(srcmap)
|
|
112
|
+
{ }
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
namespace File {
|
|
116
|
+
|
|
117
|
+
sass::vector<Include> resolve_includes(const sass::string& root, const sass::string& file,
|
|
118
|
+
const sass::vector<sass::string>& exts = { ".scss", ".sass", ".css" });
|
|
119
|
+
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
#endif
|