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,105 @@
|
|
|
1
|
+
#ifndef SASS_UTIL_H
|
|
2
|
+
#define SASS_UTIL_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 "sass/base.h"
|
|
9
|
+
#include "ast_fwd_decl.hpp"
|
|
10
|
+
|
|
11
|
+
#include <cmath>
|
|
12
|
+
#include <cstring>
|
|
13
|
+
#include <vector>
|
|
14
|
+
#include <string>
|
|
15
|
+
#include <assert.h>
|
|
16
|
+
|
|
17
|
+
#define SASS_ASSERT(cond, msg) assert(cond && msg)
|
|
18
|
+
|
|
19
|
+
namespace Sass {
|
|
20
|
+
|
|
21
|
+
template <typename T>
|
|
22
|
+
T clip(const T& n, const T& lower, const T& upper) {
|
|
23
|
+
return std::max(lower, std::min(n, upper));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
template <typename T>
|
|
27
|
+
T absmod(const T& n, const T& r) {
|
|
28
|
+
T m = std::fmod(n, r);
|
|
29
|
+
if (m < 0.0) m += r;
|
|
30
|
+
return m;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
double round(double val, size_t precision = 0);
|
|
34
|
+
double sass_strtod(const char* str);
|
|
35
|
+
const char* safe_str(const char *, const char* = "");
|
|
36
|
+
void free_string_array(char **);
|
|
37
|
+
char **copy_strings(const sass::vector<sass::string>&, char ***, int = 0);
|
|
38
|
+
sass::string read_css_string(const sass::string& str, bool css = true);
|
|
39
|
+
sass::string evacuate_escapes(const sass::string& str);
|
|
40
|
+
sass::string string_to_output(const sass::string& str);
|
|
41
|
+
sass::string comment_to_compact_string(const sass::string& text);
|
|
42
|
+
sass::string read_hex_escapes(const sass::string& str);
|
|
43
|
+
sass::string escape_string(const sass::string& str);
|
|
44
|
+
void newline_to_space(sass::string& str);
|
|
45
|
+
|
|
46
|
+
sass::string quote(const sass::string&, char q = 0);
|
|
47
|
+
sass::string unquote(const sass::string&, char* q = 0, bool keep_utf8_sequences = false, bool strict = true);
|
|
48
|
+
char detect_best_quotemark(const char* s, char qm = '"');
|
|
49
|
+
|
|
50
|
+
bool is_hex_doublet(double n);
|
|
51
|
+
bool is_color_doublet(double r, double g, double b);
|
|
52
|
+
|
|
53
|
+
bool peek_linefeed(const char* start);
|
|
54
|
+
|
|
55
|
+
// Returns true iff `elements` ⊆ `container`.
|
|
56
|
+
template <typename C, typename T>
|
|
57
|
+
bool contains_all(C container, T elements) {
|
|
58
|
+
for (const auto &el : elements) {
|
|
59
|
+
if (container.find(el) == container.end()) return false;
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// C++20 `starts_with` equivalent.
|
|
65
|
+
// See https://en.cppreference.com/w/cpp/string/basic_string/starts_with
|
|
66
|
+
inline bool starts_with(const sass::string& str, const char* prefix, size_t prefix_len) {
|
|
67
|
+
return str.compare(0, prefix_len, prefix) == 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
inline bool starts_with(const sass::string& str, const char* prefix) {
|
|
71
|
+
return starts_with(str, prefix, std::strlen(prefix));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// C++20 `ends_with` equivalent.
|
|
75
|
+
// See https://en.cppreference.com/w/cpp/string/basic_string/ends_with
|
|
76
|
+
inline bool ends_with(const sass::string& str, const sass::string& suffix) {
|
|
77
|
+
return suffix.size() <= str.size() && std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
inline bool ends_with(const sass::string& str, const char* suffix, size_t suffix_len) {
|
|
81
|
+
if (suffix_len > str.size()) return false;
|
|
82
|
+
const char* suffix_it = suffix + suffix_len;
|
|
83
|
+
const char* str_it = str.c_str() + str.size();
|
|
84
|
+
while (suffix_it != suffix) if (*(--suffix_it) != *(--str_it)) return false;
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
inline bool ends_with(const sass::string& str, const char* suffix) {
|
|
89
|
+
return ends_with(str, suffix, std::strlen(suffix));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
namespace Util {
|
|
93
|
+
|
|
94
|
+
bool isPrintable(StyleRule* r, Sass_Output_Style style = NESTED);
|
|
95
|
+
bool isPrintable(SupportsRule* r, Sass_Output_Style style = NESTED);
|
|
96
|
+
bool isPrintable(CssMediaRule* r, Sass_Output_Style style = NESTED);
|
|
97
|
+
bool isPrintable(Comment* b, Sass_Output_Style style = NESTED);
|
|
98
|
+
bool isPrintable(Block_Obj b, Sass_Output_Style style = NESTED);
|
|
99
|
+
bool isPrintable(String_Constant* s, Sass_Output_Style style = NESTED);
|
|
100
|
+
bool isPrintable(String_Quoted* s, Sass_Output_Style style = NESTED);
|
|
101
|
+
bool isPrintable(Declaration* d, Sass_Output_Style style = NESTED);
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
#endif
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#include "util_string.hpp"
|
|
2
|
+
|
|
3
|
+
#include <iostream>
|
|
4
|
+
#include <algorithm>
|
|
5
|
+
|
|
6
|
+
namespace Sass {
|
|
7
|
+
namespace Util {
|
|
8
|
+
|
|
9
|
+
// ##########################################################################
|
|
10
|
+
// Special case insensitive string matcher. We can optimize
|
|
11
|
+
// the more general compare case quite a bit by requiring
|
|
12
|
+
// consumers to obey some rules (lowercase and no space).
|
|
13
|
+
// - `literal` must only contain lower case ascii characters
|
|
14
|
+
// there is one edge case where this could give false positives
|
|
15
|
+
// test could contain a (non-ascii) char exactly 32 below literal
|
|
16
|
+
// ##########################################################################
|
|
17
|
+
bool equalsLiteral(const char* lit, const sass::string& test) {
|
|
18
|
+
// Work directly on characters
|
|
19
|
+
const char* src = test.c_str();
|
|
20
|
+
// There is a small chance that the search string
|
|
21
|
+
// Is longer than the rest of the string to look at
|
|
22
|
+
while (*lit && (*src == *lit || *src + 32 == *lit)) {
|
|
23
|
+
++src, ++lit;
|
|
24
|
+
}
|
|
25
|
+
// True if literal is at end
|
|
26
|
+
// If not test was too long
|
|
27
|
+
return *lit == 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
void ascii_str_tolower(sass::string* s) {
|
|
31
|
+
for (auto& ch : *s) {
|
|
32
|
+
ch = ascii_tolower(static_cast<unsigned char>(ch));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void ascii_str_toupper(sass::string* s) {
|
|
37
|
+
for (auto& ch : *s) {
|
|
38
|
+
ch = ascii_toupper(static_cast<unsigned char>(ch));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
sass::string rtrim(sass::string str) {
|
|
43
|
+
auto it = std::find_if_not(str.rbegin(), str.rend(), ascii_isspace);
|
|
44
|
+
str.erase(str.rend() - it);
|
|
45
|
+
return str;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ###########################################################################
|
|
49
|
+
// Returns [name] without a vendor prefix.
|
|
50
|
+
// If [name] has no vendor prefix, it's returned as-is.
|
|
51
|
+
// ###########################################################################
|
|
52
|
+
sass::string unvendor(const sass::string& name)
|
|
53
|
+
{
|
|
54
|
+
if (name.size() < 2) return name;
|
|
55
|
+
if (name[0] != '-') return name;
|
|
56
|
+
if (name[1] == '-') return name;
|
|
57
|
+
for (size_t i = 2; i < name.size(); i++) {
|
|
58
|
+
if (name[i] == '-') return name.substr(i + 1);
|
|
59
|
+
}
|
|
60
|
+
return name;
|
|
61
|
+
}
|
|
62
|
+
// EO unvendor
|
|
63
|
+
|
|
64
|
+
sass::string normalize_newlines(const sass::string& str) {
|
|
65
|
+
sass::string result;
|
|
66
|
+
result.reserve(str.size());
|
|
67
|
+
std::size_t pos = 0;
|
|
68
|
+
while (true) {
|
|
69
|
+
const std::size_t newline = str.find_first_of("\n\f\r", pos);
|
|
70
|
+
if (newline == sass::string::npos) break;
|
|
71
|
+
result.append(str, pos, newline - pos);
|
|
72
|
+
result += '\n';
|
|
73
|
+
if (str[newline] == '\r' && str[newline + 1] == '\n') {
|
|
74
|
+
pos = newline + 2;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
pos = newline + 1;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
result.append(str, pos, sass::string::npos);
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
sass::string normalize_underscores(const sass::string& str) {
|
|
85
|
+
sass::string normalized = str;
|
|
86
|
+
std::replace(normalized.begin(), normalized.end(), '_', '-');
|
|
87
|
+
return normalized;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
sass::string normalize_decimals(const sass::string& str) {
|
|
91
|
+
sass::string normalized;
|
|
92
|
+
if (!str.empty() && str[0] == '.') {
|
|
93
|
+
normalized.reserve(str.size() + 1);
|
|
94
|
+
normalized += '0';
|
|
95
|
+
normalized += str;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
normalized = str;
|
|
99
|
+
}
|
|
100
|
+
return normalized;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
char opening_bracket_for(char closing_bracket) {
|
|
104
|
+
switch (closing_bracket) {
|
|
105
|
+
case ')': return '(';
|
|
106
|
+
case ']': return '[';
|
|
107
|
+
case '}': return '{';
|
|
108
|
+
default: return '\0';
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
char closing_bracket_for(char opening_bracket) {
|
|
113
|
+
switch (opening_bracket) {
|
|
114
|
+
case '(': return ')';
|
|
115
|
+
case '[': return ']';
|
|
116
|
+
case '{': return '}';
|
|
117
|
+
default: return '\0';
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
}
|
|
122
|
+
// namespace Util
|
|
123
|
+
|
|
124
|
+
}
|
|
125
|
+
// namespace Sass
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#ifndef SASS_UTIL_STRING_H
|
|
2
|
+
#define SASS_UTIL_STRING_H
|
|
3
|
+
|
|
4
|
+
#include "sass.hpp"
|
|
5
|
+
#include <string>
|
|
6
|
+
|
|
7
|
+
namespace Sass {
|
|
8
|
+
namespace Util {
|
|
9
|
+
|
|
10
|
+
// ##########################################################################
|
|
11
|
+
// Special case insensitive string matcher. We can optimize
|
|
12
|
+
// the more general compare case quite a bit by requiring
|
|
13
|
+
// consumers to obey some rules (lowercase and no space).
|
|
14
|
+
// - `literal` must only contain lower case ascii characters
|
|
15
|
+
// there is one edge case where this could give false positives
|
|
16
|
+
// test could contain a (non-ascii) char exactly 32 below literal
|
|
17
|
+
// ##########################################################################
|
|
18
|
+
bool equalsLiteral(const char* lit, const sass::string& test);
|
|
19
|
+
|
|
20
|
+
// ###########################################################################
|
|
21
|
+
// Returns [name] without a vendor prefix.
|
|
22
|
+
// If [name] has no vendor prefix, it's returned as-is.
|
|
23
|
+
// ###########################################################################
|
|
24
|
+
sass::string unvendor(const sass::string& name);
|
|
25
|
+
|
|
26
|
+
sass::string rtrim(sass::string str);
|
|
27
|
+
sass::string normalize_newlines(const sass::string& str);
|
|
28
|
+
sass::string normalize_underscores(const sass::string& str);
|
|
29
|
+
sass::string normalize_decimals(const sass::string& str);
|
|
30
|
+
char opening_bracket_for(char closing_bracket);
|
|
31
|
+
char closing_bracket_for(char opening_bracket);
|
|
32
|
+
|
|
33
|
+
// Locale-independent ASCII character routines.
|
|
34
|
+
|
|
35
|
+
inline bool ascii_isalpha(unsigned char c) {
|
|
36
|
+
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
inline bool ascii_isdigit(unsigned char c) {
|
|
40
|
+
return (c >= '0' && c <= '9');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
inline bool ascii_isalnum(unsigned char c) {
|
|
44
|
+
return ascii_isalpha(c) || ascii_isdigit(c);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
inline bool ascii_isascii(unsigned char c) { return c < 128; }
|
|
48
|
+
|
|
49
|
+
inline bool ascii_isxdigit(unsigned char c) {
|
|
50
|
+
return ascii_isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
inline bool ascii_isspace(unsigned char c) {
|
|
54
|
+
return c == ' ' || c == '\t' || c == '\v' || c == '\f' || c == '\r' || c == '\n';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
inline char ascii_tolower(unsigned char c) {
|
|
58
|
+
if (c >= 'A' && c <= 'Z') return c + 32;
|
|
59
|
+
return c;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void ascii_str_tolower(sass::string* s);
|
|
63
|
+
|
|
64
|
+
inline char ascii_toupper(unsigned char c) {
|
|
65
|
+
if (c >= 'a' && c <= 'z') return c - 32;
|
|
66
|
+
return c;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
void ascii_str_toupper(sass::string* s);
|
|
70
|
+
|
|
71
|
+
} // namespace Sass
|
|
72
|
+
} // namespace Util
|
|
73
|
+
#endif // SASS_UTIL_STRING_H
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// sass.hpp must go before all system headers to get the
|
|
2
|
+
// __EXTENSIONS__ fix on Solaris.
|
|
3
|
+
#include "sass.hpp"
|
|
4
|
+
|
|
5
|
+
#include "sass.h"
|
|
6
|
+
#include "values.hpp"
|
|
7
|
+
|
|
8
|
+
#include <stdint.h>
|
|
9
|
+
|
|
10
|
+
namespace Sass {
|
|
11
|
+
|
|
12
|
+
// convert value from C++ side to C-API
|
|
13
|
+
union Sass_Value* ast_node_to_sass_value (const Expression* val)
|
|
14
|
+
{
|
|
15
|
+
if (val->concrete_type() == Expression::NUMBER)
|
|
16
|
+
{
|
|
17
|
+
const Number* res = Cast<Number>(val);
|
|
18
|
+
return sass_make_number(res->value(), res->unit().c_str());
|
|
19
|
+
}
|
|
20
|
+
else if (val->concrete_type() == Expression::COLOR)
|
|
21
|
+
{
|
|
22
|
+
if (const Color_RGBA* rgba = Cast<Color_RGBA>(val)) {
|
|
23
|
+
return sass_make_color(rgba->r(), rgba->g(), rgba->b(), rgba->a());
|
|
24
|
+
} else {
|
|
25
|
+
// ToDo: allow to also use HSLA colors!!
|
|
26
|
+
Color_RGBA_Obj col = Cast<Color>(val)->copyAsRGBA();
|
|
27
|
+
return sass_make_color(col->r(), col->g(), col->b(), col->a());
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else if (val->concrete_type() == Expression::LIST)
|
|
31
|
+
{
|
|
32
|
+
const List* l = Cast<List>(val);
|
|
33
|
+
union Sass_Value* list = sass_make_list(l->size(), l->separator(), l->is_bracketed());
|
|
34
|
+
for (size_t i = 0, L = l->length(); i < L; ++i) {
|
|
35
|
+
ExpressionObj obj = l->at(i);
|
|
36
|
+
auto val = ast_node_to_sass_value(obj);
|
|
37
|
+
sass_list_set_value(list, i, val);
|
|
38
|
+
}
|
|
39
|
+
return list;
|
|
40
|
+
}
|
|
41
|
+
else if (val->concrete_type() == Expression::MAP)
|
|
42
|
+
{
|
|
43
|
+
const Map* m = Cast<Map>(val);
|
|
44
|
+
union Sass_Value* map = sass_make_map(m->length());
|
|
45
|
+
size_t i = 0; for (ExpressionObj key : m->keys()) {
|
|
46
|
+
sass_map_set_key(map, i, ast_node_to_sass_value(key));
|
|
47
|
+
sass_map_set_value(map, i, ast_node_to_sass_value(m->at(key)));
|
|
48
|
+
++ i;
|
|
49
|
+
}
|
|
50
|
+
return map;
|
|
51
|
+
}
|
|
52
|
+
else if (val->concrete_type() == Expression::NULL_VAL)
|
|
53
|
+
{
|
|
54
|
+
return sass_make_null();
|
|
55
|
+
}
|
|
56
|
+
else if (val->concrete_type() == Expression::BOOLEAN)
|
|
57
|
+
{
|
|
58
|
+
const Boolean* res = Cast<Boolean>(val);
|
|
59
|
+
return sass_make_boolean(res->value());
|
|
60
|
+
}
|
|
61
|
+
else if (val->concrete_type() == Expression::STRING)
|
|
62
|
+
{
|
|
63
|
+
if (const String_Quoted* qstr = Cast<String_Quoted>(val))
|
|
64
|
+
{
|
|
65
|
+
return sass_make_qstring(qstr->value().c_str());
|
|
66
|
+
}
|
|
67
|
+
else if (const String_Constant* cstr = Cast<String_Constant>(val))
|
|
68
|
+
{
|
|
69
|
+
return sass_make_string(cstr->value().c_str());
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return sass_make_error("unknown sass value type");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// convert value from C-API to C++ side
|
|
76
|
+
Value* sass_value_to_ast_node (const union Sass_Value* val)
|
|
77
|
+
{
|
|
78
|
+
switch (sass_value_get_tag(val)) {
|
|
79
|
+
case SASS_NUMBER:
|
|
80
|
+
return SASS_MEMORY_NEW(Number,
|
|
81
|
+
SourceSpan("[C-VALUE]"),
|
|
82
|
+
sass_number_get_value(val),
|
|
83
|
+
sass_number_get_unit(val));
|
|
84
|
+
case SASS_BOOLEAN:
|
|
85
|
+
return SASS_MEMORY_NEW(Boolean,
|
|
86
|
+
SourceSpan("[C-VALUE]"),
|
|
87
|
+
sass_boolean_get_value(val));
|
|
88
|
+
case SASS_COLOR:
|
|
89
|
+
// ToDo: allow to also use HSLA colors!!
|
|
90
|
+
return SASS_MEMORY_NEW(Color_RGBA,
|
|
91
|
+
SourceSpan("[C-VALUE]"),
|
|
92
|
+
sass_color_get_r(val),
|
|
93
|
+
sass_color_get_g(val),
|
|
94
|
+
sass_color_get_b(val),
|
|
95
|
+
sass_color_get_a(val));
|
|
96
|
+
case SASS_STRING:
|
|
97
|
+
if (sass_string_is_quoted(val)) {
|
|
98
|
+
return SASS_MEMORY_NEW(String_Quoted,
|
|
99
|
+
SourceSpan("[C-VALUE]"),
|
|
100
|
+
sass_string_get_value(val));
|
|
101
|
+
}
|
|
102
|
+
return SASS_MEMORY_NEW(String_Constant,
|
|
103
|
+
SourceSpan("[C-VALUE]"),
|
|
104
|
+
sass_string_get_value(val));
|
|
105
|
+
case SASS_LIST: {
|
|
106
|
+
List* l = SASS_MEMORY_NEW(List,
|
|
107
|
+
SourceSpan("[C-VALUE]"),
|
|
108
|
+
sass_list_get_length(val),
|
|
109
|
+
sass_list_get_separator(val));
|
|
110
|
+
for (size_t i = 0, L = sass_list_get_length(val); i < L; ++i) {
|
|
111
|
+
l->append(sass_value_to_ast_node(sass_list_get_value(val, i)));
|
|
112
|
+
}
|
|
113
|
+
l->is_bracketed(sass_list_get_is_bracketed(val));
|
|
114
|
+
return l;
|
|
115
|
+
}
|
|
116
|
+
case SASS_MAP: {
|
|
117
|
+
Map* m = SASS_MEMORY_NEW(Map, SourceSpan("[C-VALUE]"));
|
|
118
|
+
for (size_t i = 0, L = sass_map_get_length(val); i < L; ++i) {
|
|
119
|
+
*m << std::make_pair(
|
|
120
|
+
sass_value_to_ast_node(sass_map_get_key(val, i)),
|
|
121
|
+
sass_value_to_ast_node(sass_map_get_value(val, i)));
|
|
122
|
+
}
|
|
123
|
+
return m;
|
|
124
|
+
}
|
|
125
|
+
case SASS_NULL:
|
|
126
|
+
return SASS_MEMORY_NEW(Null, SourceSpan("[C-VALUE]"));
|
|
127
|
+
case SASS_ERROR:
|
|
128
|
+
return SASS_MEMORY_NEW(Custom_Error,
|
|
129
|
+
SourceSpan("[C-VALUE]"),
|
|
130
|
+
sass_error_get_message(val));
|
|
131
|
+
case SASS_WARNING:
|
|
132
|
+
return SASS_MEMORY_NEW(Custom_Warning,
|
|
133
|
+
SourceSpan("[C-VALUE]"),
|
|
134
|
+
sass_warning_get_message(val));
|
|
135
|
+
default: break;
|
|
136
|
+
}
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SassC
|
|
4
|
+
class Dependency
|
|
5
|
+
attr_reader :filename
|
|
6
|
+
attr_reader :options
|
|
7
|
+
|
|
8
|
+
def initialize(filename)
|
|
9
|
+
@filename = filename
|
|
10
|
+
@options = { filename: @filename }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.from_filenames(filenames)
|
|
14
|
+
filenames.map { |f| new(f) }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/sassc/engine.rb
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "error"
|
|
4
|
+
|
|
5
|
+
module SassC
|
|
6
|
+
class Engine
|
|
7
|
+
OUTPUT_STYLES = %i[
|
|
8
|
+
sass_style_nested
|
|
9
|
+
sass_style_expanded
|
|
10
|
+
sass_style_compact
|
|
11
|
+
sass_style_compressed
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
attr_reader :template, :options
|
|
15
|
+
|
|
16
|
+
def initialize(template, options = {})
|
|
17
|
+
@template = template
|
|
18
|
+
@options = options
|
|
19
|
+
@functions = options.fetch(:functions, Script::Functions)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def render
|
|
23
|
+
return @template.dup if @template.empty?
|
|
24
|
+
|
|
25
|
+
data_context = Native.make_data_context(@template)
|
|
26
|
+
context = Native.data_context_get_context(data_context)
|
|
27
|
+
native_options = Native.context_get_options(context)
|
|
28
|
+
|
|
29
|
+
Native.option_set_is_indented_syntax_src(native_options, true) if sass?
|
|
30
|
+
Native.option_set_input_path(native_options, filename) if filename
|
|
31
|
+
Native.option_set_precision(native_options, precision) if precision
|
|
32
|
+
Native.option_set_include_path(native_options, load_paths)
|
|
33
|
+
Native.option_set_output_style(native_options, output_style_enum)
|
|
34
|
+
Native.option_set_source_comments(native_options, true) if line_comments?
|
|
35
|
+
Native.option_set_source_map_file(native_options, source_map_file) if source_map_file
|
|
36
|
+
Native.option_set_source_map_embed(native_options, true) if source_map_embed?
|
|
37
|
+
Native.option_set_source_map_contents(native_options, true) if source_map_contents?
|
|
38
|
+
Native.option_set_omit_source_map_url(native_options, true) if omit_source_map_url?
|
|
39
|
+
|
|
40
|
+
import_handler.setup(native_options)
|
|
41
|
+
functions_handler.setup(native_options, functions: @functions)
|
|
42
|
+
|
|
43
|
+
status = Native.compile_data_context(data_context)
|
|
44
|
+
|
|
45
|
+
if status != 0
|
|
46
|
+
message = Native.context_get_error_message(context)
|
|
47
|
+
filename = Native.context_get_error_file(context)
|
|
48
|
+
line = Native.context_get_error_line(context)
|
|
49
|
+
|
|
50
|
+
raise SyntaxError.new(message, filename: filename, line: line)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
css = Native.context_get_output_string(context)
|
|
54
|
+
|
|
55
|
+
@dependencies = Native.context_get_included_files(context)
|
|
56
|
+
@source_map = Native.context_get_source_map_string(context)
|
|
57
|
+
|
|
58
|
+
css.force_encoding(@template.encoding)
|
|
59
|
+
@source_map.force_encoding(@template.encoding) if @source_map.is_a?(String)
|
|
60
|
+
|
|
61
|
+
return css unless quiet?
|
|
62
|
+
ensure
|
|
63
|
+
Native.delete_data_context(data_context) if data_context
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def dependencies
|
|
67
|
+
raise NotRenderedError unless @dependencies
|
|
68
|
+
Dependency.from_filenames(@dependencies)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def source_map
|
|
72
|
+
raise NotRenderedError unless @source_map
|
|
73
|
+
@source_map
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def filename
|
|
77
|
+
@options[:filename]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def quiet?
|
|
83
|
+
@options[:quiet]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def precision
|
|
87
|
+
@options[:precision]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def sass?
|
|
91
|
+
@options[:syntax] && @options[:syntax].to_sym == :sass
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def line_comments?
|
|
95
|
+
@options[:line_comments]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def source_map_embed?
|
|
99
|
+
@options[:source_map_embed]
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def source_map_contents?
|
|
103
|
+
@options[:source_map_contents]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def omit_source_map_url?
|
|
107
|
+
@options[:omit_source_map_url]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def source_map_file
|
|
111
|
+
@options[:source_map_file]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def import_handler
|
|
115
|
+
@import_handler ||= ImportHandler.new(@options)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def functions_handler
|
|
119
|
+
@functions_handler = FunctionsHandler.new(@options)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def output_style_enum
|
|
123
|
+
@output_style_enum ||= Native::SassOutputStyle[output_style]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def output_style
|
|
127
|
+
@output_style ||= begin
|
|
128
|
+
style = @options.fetch(:style, :sass_style_nested).to_s
|
|
129
|
+
style = "sass_style_#{style}" unless style.include?("sass_style_")
|
|
130
|
+
style = style.to_sym
|
|
131
|
+
raise InvalidStyleError unless Native::SassOutputStyle.symbols.include?(style)
|
|
132
|
+
style
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def load_paths
|
|
137
|
+
paths = (@options[:load_paths] || []) + SassC.load_paths
|
|
138
|
+
paths.join(File::PATH_SEPARATOR) unless paths.empty?
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
data/lib/sassc/error.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "pathname"
|
|
4
|
+
|
|
5
|
+
module SassC
|
|
6
|
+
|
|
7
|
+
class BaseError < StandardError; end
|
|
8
|
+
class NotRenderedError < BaseError; end
|
|
9
|
+
class InvalidStyleError < BaseError; end
|
|
10
|
+
class UnsupportedValue < BaseError; end
|
|
11
|
+
|
|
12
|
+
# When dealing with SyntaxErrors,
|
|
13
|
+
# it's important to provide filename and line number information.
|
|
14
|
+
# This will be used in various error reports to users, including backtraces.
|
|
15
|
+
|
|
16
|
+
class SyntaxError < BaseError
|
|
17
|
+
|
|
18
|
+
def initialize(message, filename: nil, line: nil)
|
|
19
|
+
@filename = filename
|
|
20
|
+
@line = line
|
|
21
|
+
super(message)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def backtrace
|
|
25
|
+
return nil if super.nil?
|
|
26
|
+
sass_backtrace + super
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# The backtrace of the error within Sass files.
|
|
30
|
+
def sass_backtrace
|
|
31
|
+
return [] unless @filename && @line
|
|
32
|
+
["#{@filename}:#{@line}"]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|