sassc 0.0.9 → 0.0.10
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 +4 -4
- data/Rakefile +1 -1
- data/ext/libsass/.gitignore +13 -6
- data/ext/libsass/Makefile +42 -26
- data/ext/libsass/Makefile.am +43 -30
- data/ext/libsass/Readme.md +4 -2
- data/ext/libsass/appveyor.yml +10 -14
- data/ext/libsass/ast.cpp +54 -44
- data/ext/libsass/ast.hpp +404 -236
- data/ext/libsass/ast_def_macros.hpp +5 -0
- data/ext/libsass/ast_factory.hpp +6 -3
- data/ext/libsass/ast_fwd_decl.hpp +12 -0
- data/ext/libsass/b64/encode.h +2 -2
- data/ext/libsass/backtrace.hpp +13 -17
- data/ext/libsass/base64vlq.hpp +4 -1
- data/ext/libsass/bind.cpp +12 -15
- data/ext/libsass/bind.hpp +6 -6
- data/ext/libsass/color_names.hpp +4 -1
- data/ext/libsass/configure.ac +7 -21
- data/ext/libsass/constants.cpp +6 -4
- data/ext/libsass/constants.hpp +10 -4
- data/ext/libsass/context.cpp +89 -58
- data/ext/libsass/context.hpp +28 -35
- data/ext/libsass/contextualize.cpp +20 -10
- data/ext/libsass/contextualize.hpp +8 -23
- data/ext/libsass/contrib/libsass.spec +66 -0
- data/ext/libsass/cssize.cpp +547 -0
- data/ext/libsass/cssize.hpp +82 -0
- data/ext/libsass/debug.hpp +3 -3
- data/ext/libsass/debugger.hpp +358 -0
- data/ext/libsass/emitter.cpp +255 -0
- data/ext/libsass/emitter.hpp +83 -0
- data/ext/libsass/environment.hpp +7 -3
- data/ext/libsass/error_handling.cpp +11 -14
- data/ext/libsass/error_handling.hpp +9 -7
- data/ext/libsass/eval.cpp +253 -161
- data/ext/libsass/eval.hpp +13 -13
- data/ext/libsass/expand.cpp +135 -64
- data/ext/libsass/expand.hpp +11 -13
- data/ext/libsass/extend.cpp +66 -20
- data/ext/libsass/extend.hpp +6 -11
- data/ext/libsass/file.cpp +31 -26
- data/ext/libsass/file.hpp +6 -1
- data/ext/libsass/functions.cpp +270 -287
- data/ext/libsass/functions.hpp +8 -11
- data/ext/libsass/inspect.cpp +385 -255
- data/ext/libsass/inspect.hpp +15 -26
- data/ext/libsass/kwd_arg_macros.hpp +5 -0
- data/ext/libsass/mapping.hpp +4 -3
- data/ext/libsass/memory_manager.hpp +5 -2
- data/ext/libsass/node.cpp +50 -50
- data/ext/libsass/node.hpp +26 -27
- data/ext/libsass/operation.hpp +15 -4
- data/ext/libsass/output.cpp +401 -0
- data/ext/libsass/output.hpp +56 -0
- data/ext/libsass/parser.cpp +573 -399
- data/ext/libsass/parser.hpp +122 -88
- data/ext/libsass/paths.hpp +7 -2
- data/ext/libsass/plugins.cpp +155 -0
- data/ext/libsass/plugins.hpp +56 -0
- data/ext/libsass/position.cpp +128 -0
- data/ext/libsass/position.hpp +108 -11
- data/ext/libsass/prelexer.cpp +184 -110
- data/ext/libsass/prelexer.hpp +131 -24
- data/ext/libsass/remove_placeholders.cpp +1 -1
- data/ext/libsass/remove_placeholders.hpp +6 -6
- data/ext/libsass/sass.cpp +3 -3
- data/ext/libsass/sass.h +12 -4
- data/ext/libsass/sass2scss.cpp +3 -2
- data/ext/libsass/sass2scss.h +5 -0
- data/ext/libsass/sass_context.cpp +136 -37
- data/ext/libsass/sass_context.h +19 -10
- data/ext/libsass/sass_functions.cpp +29 -2
- data/ext/libsass/sass_functions.h +8 -2
- data/ext/libsass/sass_interface.cpp +32 -23
- data/ext/libsass/sass_interface.h +9 -4
- data/ext/libsass/sass_util.cpp +19 -23
- data/ext/libsass/sass_util.hpp +28 -27
- data/ext/libsass/sass_values.cpp +6 -4
- data/ext/libsass/sass_values.h +3 -3
- data/ext/libsass/script/ci-build-libsass +13 -1
- data/ext/libsass/script/ci-report-coverage +2 -1
- data/ext/libsass/source_map.cpp +79 -28
- data/ext/libsass/source_map.hpp +35 -16
- data/ext/libsass/subset_map.hpp +6 -4
- data/ext/libsass/to_c.hpp +4 -4
- data/ext/libsass/to_string.cpp +13 -8
- data/ext/libsass/to_string.hpp +6 -4
- data/ext/libsass/units.cpp +2 -1
- data/ext/libsass/units.hpp +6 -1
- data/ext/libsass/utf8_string.cpp +0 -5
- data/ext/libsass/utf8_string.hpp +3 -2
- data/ext/libsass/util.cpp +461 -49
- data/ext/libsass/util.hpp +34 -13
- data/ext/libsass/version.sh +10 -0
- data/ext/libsass/win/libsass.filters +20 -11
- data/ext/libsass/win/libsass.vcxproj +11 -8
- data/lib/sassc/importer.rb +1 -8
- data/lib/sassc/native.rb +7 -0
- data/lib/sassc/native/native_context_api.rb +5 -5
- data/lib/sassc/version.rb +1 -1
- data/test/native_test.rb +1 -1
- metadata +14 -10
- data/ext/libsass/copy_c_str.cpp +0 -13
- data/ext/libsass/copy_c_str.hpp +0 -5
- data/ext/libsass/output_compressed.cpp +0 -401
- data/ext/libsass/output_compressed.hpp +0 -95
- data/ext/libsass/output_nested.cpp +0 -364
- data/ext/libsass/output_nested.hpp +0 -108
- data/ext/libsass/test-driver +0 -127
- data/ext/libsass/token.hpp +0 -32
data/ext/libsass/subset_map.hpp
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
#ifndef SASS_SUBSET_MAP_H
|
|
2
|
+
#define SASS_SUBSET_MAP_H
|
|
2
3
|
|
|
3
|
-
#include <vector>
|
|
4
4
|
#include <map>
|
|
5
5
|
#include <set>
|
|
6
|
+
#include <vector>
|
|
6
7
|
#include <algorithm>
|
|
7
8
|
#include <iterator>
|
|
8
9
|
#include <iostream>
|
|
@@ -81,6 +82,7 @@ namespace Sass {
|
|
|
81
82
|
vector<V> get_v(const vector<K>& s);
|
|
82
83
|
bool empty() { return values_.empty(); }
|
|
83
84
|
void clear() { values_.clear(); hash_.clear(); }
|
|
85
|
+
const vector<V> values(void) { return values_; }
|
|
84
86
|
};
|
|
85
87
|
|
|
86
88
|
template<typename K, typename V>
|
|
@@ -106,9 +108,7 @@ namespace Sass {
|
|
|
106
108
|
sort(sorted.begin(), sorted.end());
|
|
107
109
|
vector<pair<size_t, vector<K> > > indices;
|
|
108
110
|
for (size_t i = 0, S = s.size(); i < S; ++i) {
|
|
109
|
-
// cerr << "looking for " << s[i] << endl;
|
|
110
111
|
if (!hash_.count(s[i])) {
|
|
111
|
-
// cerr << "didn't find " << s[i] << endl;
|
|
112
112
|
continue;
|
|
113
113
|
}
|
|
114
114
|
vector<triple<vector<K>, set<K>, size_t> > subsets = hash_[s[i]];
|
|
@@ -143,3 +143,5 @@ namespace Sass {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
}
|
|
146
|
+
|
|
147
|
+
#endif
|
data/ext/libsass/to_c.hpp
CHANGED
data/ext/libsass/to_string.cpp
CHANGED
|
@@ -1,29 +1,34 @@
|
|
|
1
1
|
#include <cmath>
|
|
2
2
|
#include <sstream>
|
|
3
3
|
#include <iomanip>
|
|
4
|
+
#include <iostream>
|
|
4
5
|
|
|
5
|
-
#ifndef SASS_TO_STRING
|
|
6
|
-
#include "to_string.hpp"
|
|
7
|
-
#endif
|
|
8
|
-
|
|
9
|
-
#include "inspect.hpp"
|
|
10
6
|
#include "ast.hpp"
|
|
7
|
+
#include "inspect.hpp"
|
|
11
8
|
#include "context.hpp"
|
|
12
|
-
#include
|
|
9
|
+
#include "to_string.hpp"
|
|
13
10
|
|
|
14
11
|
namespace Sass {
|
|
15
12
|
using namespace std;
|
|
16
13
|
|
|
17
|
-
To_String::To_String(Context* ctx)
|
|
14
|
+
To_String::To_String(Context* ctx)
|
|
15
|
+
: ctx(ctx) { }
|
|
18
16
|
To_String::~To_String() { }
|
|
19
17
|
|
|
20
18
|
inline string To_String::fallback_impl(AST_Node* n)
|
|
21
19
|
{
|
|
22
|
-
|
|
20
|
+
Emitter emitter(ctx);
|
|
21
|
+
Inspect i(emitter);
|
|
22
|
+
i.in_declaration_list = true;
|
|
23
23
|
n->perform(&i);
|
|
24
24
|
return i.get_buffer();
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
inline string To_String::operator()(String_Constant* s)
|
|
28
|
+
{
|
|
29
|
+
return s->value();
|
|
30
|
+
}
|
|
31
|
+
|
|
27
32
|
inline string To_String::operator()(Null* n)
|
|
28
33
|
{ return ""; }
|
|
29
34
|
}
|
data/ext/libsass/to_string.hpp
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
#ifndef SASS_TO_STRING_H
|
|
2
|
+
#define SASS_TO_STRING_H
|
|
2
3
|
|
|
3
4
|
#include <string>
|
|
4
5
|
|
|
5
|
-
#ifndef SASS_OPERATION
|
|
6
6
|
#include "operation.hpp"
|
|
7
|
-
#endif
|
|
8
7
|
|
|
9
8
|
namespace Sass {
|
|
10
9
|
using namespace std;
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
class Context;
|
|
13
12
|
class Null;
|
|
14
13
|
|
|
15
14
|
class To_String : public Operation_CRTP<string, To_String> {
|
|
@@ -25,8 +24,11 @@ namespace Sass {
|
|
|
25
24
|
virtual ~To_String();
|
|
26
25
|
|
|
27
26
|
string operator()(Null* n);
|
|
27
|
+
string operator()(String_Constant*);
|
|
28
28
|
|
|
29
29
|
template <typename U>
|
|
30
30
|
string fallback(U n) { return fallback_impl(n); }
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
+
|
|
34
|
+
#endif
|
data/ext/libsass/units.cpp
CHANGED
|
@@ -45,10 +45,11 @@ namespace Sass {
|
|
|
45
45
|
return factor;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/* not used anymore - remove?
|
|
48
49
|
double convert(double n, const string& from, const string& to)
|
|
49
50
|
{
|
|
50
51
|
double factor = conversion_factor(from, to);
|
|
51
52
|
return factor ? factor * n : n;
|
|
52
|
-
}
|
|
53
|
+
} */
|
|
53
54
|
|
|
54
55
|
}
|
data/ext/libsass/units.hpp
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
#ifndef SASS_UNITS_H
|
|
2
|
+
#define SASS_UNITS_H
|
|
3
|
+
|
|
1
4
|
#include <string>
|
|
2
5
|
|
|
3
6
|
namespace Sass {
|
|
@@ -6,5 +9,7 @@ namespace Sass {
|
|
|
6
9
|
extern double conversion_factors[10][10];
|
|
7
10
|
Unit string_to_unit(const string&);
|
|
8
11
|
double conversion_factor(const string&, const string&);
|
|
9
|
-
double convert(double, const string&, const string&);
|
|
12
|
+
// double convert(double, const string&, const string&);
|
|
10
13
|
}
|
|
14
|
+
|
|
15
|
+
#endif
|
data/ext/libsass/utf8_string.cpp
CHANGED
data/ext/libsass/utf8_string.hpp
CHANGED
data/ext/libsass/util.cpp
CHANGED
|
@@ -1,6 +1,391 @@
|
|
|
1
|
+
#include<stdint.h>
|
|
2
|
+
#include "ast.hpp"
|
|
1
3
|
#include "util.hpp"
|
|
4
|
+
#include "prelexer.hpp"
|
|
5
|
+
#include "utf8/checked.h"
|
|
2
6
|
|
|
3
7
|
namespace Sass {
|
|
8
|
+
|
|
9
|
+
#define out_of_memory() do { \
|
|
10
|
+
fprintf(stderr, "Out of memory.\n"); \
|
|
11
|
+
exit(EXIT_FAILURE); \
|
|
12
|
+
} while (0)
|
|
13
|
+
|
|
14
|
+
/* Sadly, sass_strdup is not portable. */
|
|
15
|
+
char *sass_strdup(const char *str)
|
|
16
|
+
{
|
|
17
|
+
char *ret = (char*) malloc(strlen(str) + 1);
|
|
18
|
+
if (ret == NULL)
|
|
19
|
+
out_of_memory();
|
|
20
|
+
strcpy(ret, str);
|
|
21
|
+
return ret;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Locale unspecific atof function. */
|
|
25
|
+
double sass_atof(const char *str)
|
|
26
|
+
{
|
|
27
|
+
char separator = *(localeconv()->decimal_point);
|
|
28
|
+
if(separator != '.'){
|
|
29
|
+
// The current locale specifies another
|
|
30
|
+
// separator. convert the separator to the
|
|
31
|
+
// one understood by the locale if needed
|
|
32
|
+
const char *found = strchr(str, '.');
|
|
33
|
+
if(found != NULL){
|
|
34
|
+
// substitution is required. perform the substitution on a copy
|
|
35
|
+
// of the string. This is slower but it is thread safe.
|
|
36
|
+
char *copy = sass_strdup(str);
|
|
37
|
+
*(copy + (found - str)) = separator;
|
|
38
|
+
double res = atof(copy);
|
|
39
|
+
free(copy);
|
|
40
|
+
return res;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return atof(str);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// double escape every escape sequences
|
|
48
|
+
// escape unescaped quotes and backslashes
|
|
49
|
+
string string_escape(const string& str)
|
|
50
|
+
{
|
|
51
|
+
string out("");
|
|
52
|
+
for (auto i : str) {
|
|
53
|
+
// escape some characters
|
|
54
|
+
if (i == '"') out += '\\';
|
|
55
|
+
if (i == '\'') out += '\\';
|
|
56
|
+
if (i == '\\') out += '\\';
|
|
57
|
+
out += i;
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// unescape every escape sequence
|
|
63
|
+
// only removes unescaped backslashes
|
|
64
|
+
string string_unescape(const string& str)
|
|
65
|
+
{
|
|
66
|
+
string out("");
|
|
67
|
+
bool esc = false;
|
|
68
|
+
for (auto i : str) {
|
|
69
|
+
if (esc || i != '\\') {
|
|
70
|
+
esc = false;
|
|
71
|
+
out += i;
|
|
72
|
+
} else {
|
|
73
|
+
esc = true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// open escape sequence at end
|
|
77
|
+
// maybe it should thow an error
|
|
78
|
+
if (esc) { out += '\\'; }
|
|
79
|
+
return out;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// evacuate unescaped quoted
|
|
83
|
+
// leave everything else untouched
|
|
84
|
+
string evacuate_quotes(const string& str)
|
|
85
|
+
{
|
|
86
|
+
string out("");
|
|
87
|
+
bool esc = false;
|
|
88
|
+
for (auto i : str) {
|
|
89
|
+
if (!esc) {
|
|
90
|
+
// ignore next character
|
|
91
|
+
if (i == '\\') esc = true;
|
|
92
|
+
// evacuate unescaped quotes
|
|
93
|
+
else if (i == '"') out += '\\';
|
|
94
|
+
else if (i == '\'') out += '\\';
|
|
95
|
+
}
|
|
96
|
+
// get escaped char now
|
|
97
|
+
else { esc = false; }
|
|
98
|
+
// remove nothing
|
|
99
|
+
out += i;
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// double escape all escape sequences
|
|
105
|
+
// keep unescaped quotes and backslashes
|
|
106
|
+
string evacuate_escapes(const string& str)
|
|
107
|
+
{
|
|
108
|
+
string out("");
|
|
109
|
+
bool esc = false;
|
|
110
|
+
for (auto i : str) {
|
|
111
|
+
if (i == '\\' && !esc) {
|
|
112
|
+
out += '\\';
|
|
113
|
+
out += '\\';
|
|
114
|
+
esc = true;
|
|
115
|
+
} else if (esc && i == '"') {
|
|
116
|
+
out += '\\';
|
|
117
|
+
out += i;
|
|
118
|
+
esc = false;
|
|
119
|
+
} else if (esc && i == '\'') {
|
|
120
|
+
out += '\\';
|
|
121
|
+
out += i;
|
|
122
|
+
esc = false;
|
|
123
|
+
} else if (esc && i == '\\') {
|
|
124
|
+
out += '\\';
|
|
125
|
+
out += i;
|
|
126
|
+
esc = false;
|
|
127
|
+
} else {
|
|
128
|
+
esc = false;
|
|
129
|
+
out += i;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// happens when parsing does not correctly skip
|
|
133
|
+
// over escaped sequences for ie. interpolations
|
|
134
|
+
// one example: foo\#{interpolate}
|
|
135
|
+
// if (esc) out += '\\';
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// bell character is replaces with space
|
|
140
|
+
string string_to_output(const string& str)
|
|
141
|
+
{
|
|
142
|
+
string out("");
|
|
143
|
+
for (auto i : str) {
|
|
144
|
+
if (i == 10) {
|
|
145
|
+
out += ' ';
|
|
146
|
+
} else {
|
|
147
|
+
out += i;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
string comment_to_string(const string& text)
|
|
154
|
+
{
|
|
155
|
+
string str = "";
|
|
156
|
+
size_t has = 0;
|
|
157
|
+
bool clean = false;
|
|
158
|
+
for (auto i : text) {
|
|
159
|
+
if (clean) {
|
|
160
|
+
if (i == '\n') { has = 0; }
|
|
161
|
+
else if (i == '\r') { has = 0; }
|
|
162
|
+
else if (i == '\t') { ++ has; }
|
|
163
|
+
else if (i == ' ') { ++ has; }
|
|
164
|
+
else if (i == '*') {}
|
|
165
|
+
else {
|
|
166
|
+
clean = false;
|
|
167
|
+
str += ' ';
|
|
168
|
+
str += i;
|
|
169
|
+
}
|
|
170
|
+
} else if (i == '\n') {
|
|
171
|
+
clean = true;
|
|
172
|
+
} else if (i == '\r') {
|
|
173
|
+
clean = true;
|
|
174
|
+
} else {
|
|
175
|
+
str += i;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (has) return str;
|
|
179
|
+
else return text;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
string normalize_wspace(const string& str)
|
|
183
|
+
{
|
|
184
|
+
bool ws = false;
|
|
185
|
+
bool esc = false;
|
|
186
|
+
char inside_str = 0;
|
|
187
|
+
string text = "";
|
|
188
|
+
for(auto i : str) {
|
|
189
|
+
if (!esc && i == '\\') {
|
|
190
|
+
esc = true;
|
|
191
|
+
text += i;
|
|
192
|
+
} else if (esc) {
|
|
193
|
+
esc = false;
|
|
194
|
+
text += i;
|
|
195
|
+
} else if (!inside_str && (i == '"' || i == '\'')) {
|
|
196
|
+
inside_str = i;
|
|
197
|
+
text += i;
|
|
198
|
+
} else if (inside_str) {
|
|
199
|
+
if (i == inside_str)
|
|
200
|
+
inside_str = false;
|
|
201
|
+
text += i;
|
|
202
|
+
} else if (
|
|
203
|
+
i == ' ' ||
|
|
204
|
+
i == '\r' ||
|
|
205
|
+
i == '\n' ||
|
|
206
|
+
i == ' '
|
|
207
|
+
) {
|
|
208
|
+
// only add one space
|
|
209
|
+
if (!ws) text += ' ';
|
|
210
|
+
ws = true;
|
|
211
|
+
} else {
|
|
212
|
+
ws = false;
|
|
213
|
+
text += i;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (esc) text += '\\';
|
|
217
|
+
return text;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// find best quote_mark by detecting if the string contains any single
|
|
221
|
+
// or double quotes. When a single quote is found, we not we want a double
|
|
222
|
+
// quote as quote_mark. Otherwise we check if the string cotains any double
|
|
223
|
+
// quotes, which will trigger the use of single quotes as best quote_mark.
|
|
224
|
+
char detect_best_quotemark(const char* s, char qm)
|
|
225
|
+
{
|
|
226
|
+
// ensure valid fallback quote_mark
|
|
227
|
+
char quote_mark = qm && qm != '*' ? qm : '"';
|
|
228
|
+
while (*s) {
|
|
229
|
+
// force double quotes as soon
|
|
230
|
+
// as one single quote is found
|
|
231
|
+
if (*s == '\'') { return '"'; }
|
|
232
|
+
// a single does not force quote_mark
|
|
233
|
+
// maybe we see a double quote later
|
|
234
|
+
else if (*s == '"') { quote_mark = '\''; }
|
|
235
|
+
++ s;
|
|
236
|
+
}
|
|
237
|
+
return quote_mark;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
string unquote(const string& s, char* qd)
|
|
241
|
+
{
|
|
242
|
+
|
|
243
|
+
// not enough room for quotes
|
|
244
|
+
// no possibility to unquote
|
|
245
|
+
if (s.length() < 2) return s;
|
|
246
|
+
|
|
247
|
+
char q;
|
|
248
|
+
bool skipped = false;
|
|
249
|
+
|
|
250
|
+
// this is no guarantee that the unquoting will work
|
|
251
|
+
// what about whitespace before/after the quote_mark?
|
|
252
|
+
if (*s.begin() == '"' && *s.rbegin() == '"') q = '"';
|
|
253
|
+
else if (*s.begin() == '\'' && *s.rbegin() == '\'') q = '\'';
|
|
254
|
+
else return s;
|
|
255
|
+
|
|
256
|
+
string unq;
|
|
257
|
+
unq.reserve(s.length()-2);
|
|
258
|
+
|
|
259
|
+
for (size_t i = 1, L = s.length() - 1; i < L; ++i) {
|
|
260
|
+
|
|
261
|
+
// implement the same strange ruby sass behavior
|
|
262
|
+
// an escape sequence can also mean a unicode char
|
|
263
|
+
if (s[i] == '\\' && !skipped) {
|
|
264
|
+
// remember
|
|
265
|
+
skipped = true;
|
|
266
|
+
|
|
267
|
+
// skip it
|
|
268
|
+
// ++ i;
|
|
269
|
+
|
|
270
|
+
// if (i == L) break;
|
|
271
|
+
|
|
272
|
+
// escape length
|
|
273
|
+
size_t len = 1;
|
|
274
|
+
|
|
275
|
+
// parse as many sequence chars as possible
|
|
276
|
+
// ToDo: Check if ruby aborts after possible max
|
|
277
|
+
while (i + len < L && s[i + len] && isxdigit(s[i + len])) ++ len;
|
|
278
|
+
|
|
279
|
+
// hex string?
|
|
280
|
+
if (len > 1) {
|
|
281
|
+
|
|
282
|
+
// convert the extracted hex string to code point value
|
|
283
|
+
// ToDo: Maybe we could do this without creating a substring
|
|
284
|
+
uint32_t cp = strtol(s.substr (i + 1, len - 1).c_str(), nullptr, 16);
|
|
285
|
+
|
|
286
|
+
// assert invalid code points
|
|
287
|
+
if (cp == 0) cp = 0xFFFD;
|
|
288
|
+
// replace bell character
|
|
289
|
+
// if (cp == 10) cp = 32;
|
|
290
|
+
|
|
291
|
+
// use a very simple approach to convert via utf8 lib
|
|
292
|
+
// maybe there is a more elegant way; maybe we shoud
|
|
293
|
+
// convert the whole output from string to a stream!?
|
|
294
|
+
// allocate memory for utf8 char and convert to utf8
|
|
295
|
+
unsigned char u[5] = {0,0,0,0,0}; utf8::append(cp, u);
|
|
296
|
+
for(size_t m = 0; u[m] && m < 5; m++) unq.push_back(u[m]);
|
|
297
|
+
|
|
298
|
+
// skip some more chars?
|
|
299
|
+
i += len - 1; skipped = false;
|
|
300
|
+
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
}
|
|
305
|
+
// check for unexpected delimiter
|
|
306
|
+
// be strict and throw error back
|
|
307
|
+
else if (!skipped && q == s[i]) {
|
|
308
|
+
// don't be that strict
|
|
309
|
+
return s;
|
|
310
|
+
// this basically always means an internal error and not users fault
|
|
311
|
+
error("Unescaped delimiter in string to unquote found. [" + s + "]", ParserState("[UNQUOTE]", -1));
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
skipped = false;
|
|
315
|
+
unq.push_back(s[i]);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
}
|
|
319
|
+
if (skipped) { return s; }
|
|
320
|
+
if (qd) *qd = q;
|
|
321
|
+
return unq;
|
|
322
|
+
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
string quote(const string& s, char q)
|
|
326
|
+
{
|
|
327
|
+
|
|
328
|
+
// return an empty quoted string
|
|
329
|
+
if (s.empty()) return string(2, q ? q : '"');
|
|
330
|
+
|
|
331
|
+
// autodetect with fallback to given quote
|
|
332
|
+
q = detect_best_quotemark(s.c_str(), q);
|
|
333
|
+
|
|
334
|
+
string quoted;
|
|
335
|
+
quoted.reserve(s.length()+2);
|
|
336
|
+
quoted.push_back(q);
|
|
337
|
+
|
|
338
|
+
const char* it = s.c_str();
|
|
339
|
+
const char* end = it + strlen(it) + 1;
|
|
340
|
+
while (*it && it < end) {
|
|
341
|
+
const char* now = it;
|
|
342
|
+
|
|
343
|
+
if (*it == q) {
|
|
344
|
+
quoted.push_back('\\');
|
|
345
|
+
} else if (*it == '\\') {
|
|
346
|
+
quoted.push_back('\\');
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
int cp = utf8::next(it, end);
|
|
350
|
+
|
|
351
|
+
if (cp == 10) {
|
|
352
|
+
quoted.push_back('\\');
|
|
353
|
+
quoted.push_back('a');
|
|
354
|
+
} else if (cp < 127) {
|
|
355
|
+
quoted.push_back((char) cp);
|
|
356
|
+
} else {
|
|
357
|
+
while (now < it) {
|
|
358
|
+
quoted.push_back(*now);
|
|
359
|
+
++ now;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
quoted.push_back(q);
|
|
365
|
+
return quoted;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
bool is_hex_doublet(double n)
|
|
369
|
+
{
|
|
370
|
+
return n == 0x00 || n == 0x11 || n == 0x22 || n == 0x33 ||
|
|
371
|
+
n == 0x44 || n == 0x55 || n == 0x66 || n == 0x77 ||
|
|
372
|
+
n == 0x88 || n == 0x99 || n == 0xAA || n == 0xBB ||
|
|
373
|
+
n == 0xCC || n == 0xDD || n == 0xEE || n == 0xFF ;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
bool is_color_doublet(double r, double g, double b)
|
|
377
|
+
{
|
|
378
|
+
return is_hex_doublet(r) && is_hex_doublet(g) && is_hex_doublet(b);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
bool peek_linefeed(const char* start)
|
|
382
|
+
{
|
|
383
|
+
if(*start == '\n' || *start == '\r') return true;;
|
|
384
|
+
const char* linefeed = Prelexer::wspaces(start);
|
|
385
|
+
if (linefeed == 0) return false;
|
|
386
|
+
return *linefeed == '\n' || *linefeed == '\r';
|
|
387
|
+
}
|
|
388
|
+
|
|
4
389
|
namespace Util {
|
|
5
390
|
using std::string;
|
|
6
391
|
|
|
@@ -37,7 +422,7 @@ namespace Sass {
|
|
|
37
422
|
}
|
|
38
423
|
}
|
|
39
424
|
|
|
40
|
-
bool isPrintable(Ruleset* r) {
|
|
425
|
+
bool isPrintable(Ruleset* r, Output_Style style) {
|
|
41
426
|
if (r == NULL) {
|
|
42
427
|
return false;
|
|
43
428
|
}
|
|
@@ -47,7 +432,7 @@ namespace Sass {
|
|
|
47
432
|
bool hasSelectors = static_cast<Selector_List*>(r->selector())->length() > 0;
|
|
48
433
|
|
|
49
434
|
if (!hasSelectors) {
|
|
50
|
-
|
|
435
|
+
return false;
|
|
51
436
|
}
|
|
52
437
|
|
|
53
438
|
bool hasDeclarations = false;
|
|
@@ -55,23 +440,29 @@ namespace Sass {
|
|
|
55
440
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
|
56
441
|
Statement* stm = (*b)[i];
|
|
57
442
|
if (dynamic_cast<Has_Block*>(stm)) {
|
|
58
|
-
|
|
59
|
-
if (isPrintable(pChildBlock)) {
|
|
443
|
+
Block* pChildBlock = ((Has_Block*)stm)->block();
|
|
444
|
+
if (isPrintable(pChildBlock, style)) {
|
|
60
445
|
hasPrintableChildBlocks = true;
|
|
61
446
|
}
|
|
447
|
+
} else if (Comment* c = dynamic_cast<Comment*>(stm)) {
|
|
448
|
+
if (style == COMPRESSED) {
|
|
449
|
+
hasDeclarations = c->is_important();
|
|
450
|
+
} else {
|
|
451
|
+
hasDeclarations = true;
|
|
452
|
+
}
|
|
62
453
|
} else {
|
|
63
|
-
|
|
454
|
+
hasDeclarations = true;
|
|
64
455
|
}
|
|
65
456
|
|
|
66
457
|
if (hasDeclarations || hasPrintableChildBlocks) {
|
|
67
|
-
|
|
458
|
+
return true;
|
|
68
459
|
}
|
|
69
460
|
}
|
|
70
461
|
|
|
71
462
|
return false;
|
|
72
463
|
}
|
|
73
464
|
|
|
74
|
-
bool isPrintable(Feature_Block* f) {
|
|
465
|
+
bool isPrintable(Feature_Block* f, Output_Style style) {
|
|
75
466
|
if (f == NULL) {
|
|
76
467
|
return false;
|
|
77
468
|
}
|
|
@@ -95,7 +486,7 @@ namespace Sass {
|
|
|
95
486
|
}
|
|
96
487
|
else if (dynamic_cast<Has_Block*>(stm)) {
|
|
97
488
|
Block* pChildBlock = ((Has_Block*)stm)->block();
|
|
98
|
-
if (isPrintable(pChildBlock)) {
|
|
489
|
+
if (isPrintable(pChildBlock, style)) {
|
|
99
490
|
hasPrintableChildBlocks = true;
|
|
100
491
|
}
|
|
101
492
|
}
|
|
@@ -108,7 +499,7 @@ namespace Sass {
|
|
|
108
499
|
return false;
|
|
109
500
|
}
|
|
110
501
|
|
|
111
|
-
bool isPrintable(Media_Block* m) {
|
|
502
|
+
bool isPrintable(Media_Block* m, Output_Style style) {
|
|
112
503
|
if (m == NULL) {
|
|
113
504
|
return false;
|
|
114
505
|
}
|
|
@@ -122,7 +513,7 @@ namespace Sass {
|
|
|
122
513
|
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
|
123
514
|
Statement* stm = (*b)[i];
|
|
124
515
|
if (!stm->is_hoistable() && m->selector() != NULL && !hasSelectors) {
|
|
125
|
-
|
|
516
|
+
// If a statement isn't hoistable, the selectors apply to it. If there are no selectors (a selector list of length 0),
|
|
126
517
|
// then those statements aren't considered printable. That means there was a placeholder that was removed. If the selector
|
|
127
518
|
// is NULL, then that means there was never a wrapping selector and it is printable (think of a top level media block with
|
|
128
519
|
// a declaration in it).
|
|
@@ -131,55 +522,76 @@ namespace Sass {
|
|
|
131
522
|
hasDeclarations = true;
|
|
132
523
|
}
|
|
133
524
|
else if (dynamic_cast<Has_Block*>(stm)) {
|
|
134
|
-
|
|
135
|
-
if (isPrintable(pChildBlock)) {
|
|
525
|
+
Block* pChildBlock = ((Has_Block*)stm)->block();
|
|
526
|
+
if (isPrintable(pChildBlock, style)) {
|
|
136
527
|
hasPrintableChildBlocks = true;
|
|
137
528
|
}
|
|
138
529
|
}
|
|
139
530
|
|
|
140
|
-
|
|
141
|
-
|
|
531
|
+
if (hasDeclarations || hasPrintableChildBlocks) {
|
|
532
|
+
return true;
|
|
142
533
|
}
|
|
143
534
|
}
|
|
144
535
|
|
|
145
536
|
return false;
|
|
146
537
|
}
|
|
147
538
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
539
|
+
bool isPrintable(Block* b, Output_Style style) {
|
|
540
|
+
if (b == NULL) {
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
for (size_t i = 0, L = b->length(); i < L; ++i) {
|
|
545
|
+
Statement* stm = (*b)[i];
|
|
546
|
+
if (typeid(*stm) == typeid(Declaration) || typeid(*stm) == typeid(At_Rule)) {
|
|
547
|
+
return true;
|
|
548
|
+
}
|
|
549
|
+
else if (typeid(*stm) == typeid(Comment)) {
|
|
550
|
+
|
|
551
|
+
}
|
|
552
|
+
else if (typeid(*stm) == typeid(Ruleset)) {
|
|
553
|
+
Ruleset* r = (Ruleset*) stm;
|
|
554
|
+
if (isPrintable(r, style)) {
|
|
555
|
+
return true;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
else if (typeid(*stm) == typeid(Feature_Block)) {
|
|
559
|
+
Feature_Block* f = (Feature_Block*) stm;
|
|
560
|
+
if (isPrintable(f, style)) {
|
|
561
|
+
return true;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
else if (typeid(*stm) == typeid(Media_Block)) {
|
|
565
|
+
Media_Block* m = (Media_Block*) stm;
|
|
566
|
+
if (isPrintable(m, style)) {
|
|
567
|
+
return true;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
else if (dynamic_cast<Has_Block*>(stm) && isPrintable(((Has_Block*)stm)->block(), style)) {
|
|
571
|
+
return true;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
string vecJoin(const vector<string>& vec, const string& sep)
|
|
579
|
+
{
|
|
580
|
+
switch (vec.size())
|
|
581
|
+
{
|
|
582
|
+
case 0:
|
|
583
|
+
return string("");
|
|
584
|
+
case 1:
|
|
585
|
+
return vec[0];
|
|
586
|
+
default:
|
|
587
|
+
std::ostringstream os;
|
|
588
|
+
os << vec[0];
|
|
589
|
+
for (size_t i = 1; i < vec.size(); i++) {
|
|
590
|
+
os << sep << vec[i];
|
|
591
|
+
}
|
|
592
|
+
return os.str();
|
|
593
|
+
}
|
|
594
|
+
}
|
|
183
595
|
|
|
184
596
|
bool isAscii(int ch) {
|
|
185
597
|
return ch >= 0 && ch < 128;
|