sassc 2.0.0 → 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.
Files changed (260) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.gitmodules +1 -1
  4. data/.travis.yml +9 -3
  5. data/CHANGELOG.md +36 -0
  6. data/CODE_OF_CONDUCT.md +1 -1
  7. data/README.md +1 -1
  8. data/Rakefile +43 -7
  9. data/ext/depend +4 -0
  10. data/ext/extconf.rb +92 -0
  11. data/ext/libsass/VERSION +1 -0
  12. data/ext/libsass/include/sass/base.h +9 -1
  13. data/ext/libsass/include/sass/context.h +5 -1
  14. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  15. data/ext/libsass/src/ast.cpp +755 -2028
  16. data/ext/libsass/src/ast.hpp +492 -2477
  17. data/ext/libsass/src/{to_c.cpp → ast2c.cpp} +22 -16
  18. data/ext/libsass/src/ast2c.hpp +39 -0
  19. data/ext/libsass/src/ast_def_macros.hpp +70 -10
  20. data/ext/libsass/src/ast_fwd_decl.cpp +5 -3
  21. data/ext/libsass/src/ast_fwd_decl.hpp +107 -296
  22. data/ext/libsass/src/ast_helpers.hpp +292 -0
  23. data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
  24. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  25. data/ext/libsass/src/ast_sel_unify.cpp +275 -0
  26. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  27. data/ext/libsass/src/ast_selectors.cpp +1043 -0
  28. data/ext/libsass/src/ast_selectors.hpp +522 -0
  29. data/ext/libsass/src/ast_supports.cpp +114 -0
  30. data/ext/libsass/src/ast_supports.hpp +121 -0
  31. data/ext/libsass/src/ast_values.cpp +1154 -0
  32. data/ext/libsass/src/ast_values.hpp +498 -0
  33. data/ext/libsass/src/backtrace.cpp +11 -7
  34. data/ext/libsass/src/backtrace.hpp +5 -5
  35. data/ext/libsass/src/base64vlq.cpp +5 -2
  36. data/ext/libsass/src/base64vlq.hpp +1 -1
  37. data/ext/libsass/src/bind.cpp +35 -34
  38. data/ext/libsass/src/bind.hpp +3 -1
  39. data/ext/libsass/src/c2ast.cpp +64 -0
  40. data/ext/libsass/src/c2ast.hpp +14 -0
  41. data/ext/libsass/src/cencode.c +4 -6
  42. data/ext/libsass/src/check_nesting.cpp +83 -88
  43. data/ext/libsass/src/check_nesting.hpp +39 -34
  44. data/ext/libsass/src/color_maps.cpp +168 -164
  45. data/ext/libsass/src/color_maps.hpp +152 -160
  46. data/ext/libsass/src/constants.cpp +20 -0
  47. data/ext/libsass/src/constants.hpp +19 -0
  48. data/ext/libsass/src/context.cpp +104 -121
  49. data/ext/libsass/src/context.hpp +43 -55
  50. data/ext/libsass/src/cssize.cpp +103 -188
  51. data/ext/libsass/src/cssize.hpp +45 -51
  52. data/ext/libsass/src/dart_helpers.hpp +199 -0
  53. data/ext/libsass/src/debugger.hpp +524 -361
  54. data/ext/libsass/src/emitter.cpp +26 -26
  55. data/ext/libsass/src/emitter.hpp +20 -18
  56. data/ext/libsass/src/environment.cpp +41 -27
  57. data/ext/libsass/src/environment.hpp +33 -22
  58. data/ext/libsass/src/error_handling.cpp +92 -94
  59. data/ext/libsass/src/error_handling.hpp +73 -50
  60. data/ext/libsass/src/eval.cpp +380 -515
  61. data/ext/libsass/src/eval.hpp +64 -57
  62. data/ext/libsass/src/eval_selectors.cpp +75 -0
  63. data/ext/libsass/src/expand.cpp +322 -263
  64. data/ext/libsass/src/expand.hpp +55 -39
  65. data/ext/libsass/src/extender.cpp +1188 -0
  66. data/ext/libsass/src/extender.hpp +399 -0
  67. data/ext/libsass/src/extension.cpp +43 -0
  68. data/ext/libsass/src/extension.hpp +89 -0
  69. data/ext/libsass/src/file.cpp +134 -88
  70. data/ext/libsass/src/file.hpp +28 -37
  71. data/ext/libsass/src/fn_colors.cpp +596 -0
  72. data/ext/libsass/src/fn_colors.hpp +85 -0
  73. data/ext/libsass/src/fn_lists.cpp +285 -0
  74. data/ext/libsass/src/fn_lists.hpp +34 -0
  75. data/ext/libsass/src/fn_maps.cpp +94 -0
  76. data/ext/libsass/src/fn_maps.hpp +30 -0
  77. data/ext/libsass/src/fn_miscs.cpp +244 -0
  78. data/ext/libsass/src/fn_miscs.hpp +40 -0
  79. data/ext/libsass/src/fn_numbers.cpp +227 -0
  80. data/ext/libsass/src/fn_numbers.hpp +45 -0
  81. data/ext/libsass/src/fn_selectors.cpp +205 -0
  82. data/ext/libsass/src/fn_selectors.hpp +35 -0
  83. data/ext/libsass/src/fn_strings.cpp +268 -0
  84. data/ext/libsass/src/fn_strings.hpp +34 -0
  85. data/ext/libsass/src/fn_utils.cpp +158 -0
  86. data/ext/libsass/src/fn_utils.hpp +62 -0
  87. data/ext/libsass/src/inspect.cpp +253 -266
  88. data/ext/libsass/src/inspect.hpp +72 -74
  89. data/ext/libsass/src/json.cpp +2 -2
  90. data/ext/libsass/src/lexer.cpp +25 -84
  91. data/ext/libsass/src/lexer.hpp +5 -16
  92. data/ext/libsass/src/listize.cpp +27 -43
  93. data/ext/libsass/src/listize.hpp +14 -11
  94. data/ext/libsass/src/mapping.hpp +1 -0
  95. data/ext/libsass/src/memory.hpp +12 -0
  96. data/ext/libsass/src/memory/allocator.cpp +48 -0
  97. data/ext/libsass/src/memory/allocator.hpp +138 -0
  98. data/ext/libsass/src/memory/config.hpp +20 -0
  99. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  100. data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
  101. data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
  102. data/ext/libsass/src/operation.hpp +193 -143
  103. data/ext/libsass/src/operators.cpp +56 -29
  104. data/ext/libsass/src/operators.hpp +11 -11
  105. data/ext/libsass/src/ordered_map.hpp +112 -0
  106. data/ext/libsass/src/output.cpp +59 -75
  107. data/ext/libsass/src/output.hpp +15 -22
  108. data/ext/libsass/src/parser.cpp +662 -818
  109. data/ext/libsass/src/parser.hpp +96 -100
  110. data/ext/libsass/src/parser_selectors.cpp +189 -0
  111. data/ext/libsass/src/permutate.hpp +164 -0
  112. data/ext/libsass/src/plugins.cpp +12 -8
  113. data/ext/libsass/src/plugins.hpp +8 -8
  114. data/ext/libsass/src/position.cpp +10 -26
  115. data/ext/libsass/src/position.hpp +44 -21
  116. data/ext/libsass/src/prelexer.cpp +14 -8
  117. data/ext/libsass/src/prelexer.hpp +9 -9
  118. data/ext/libsass/src/remove_placeholders.cpp +59 -57
  119. data/ext/libsass/src/remove_placeholders.hpp +20 -18
  120. data/ext/libsass/src/sass.cpp +25 -18
  121. data/ext/libsass/src/sass.hpp +22 -14
  122. data/ext/libsass/src/sass2scss.cpp +49 -18
  123. data/ext/libsass/src/sass_context.cpp +104 -132
  124. data/ext/libsass/src/sass_context.hpp +2 -2
  125. data/ext/libsass/src/sass_functions.cpp +7 -4
  126. data/ext/libsass/src/sass_functions.hpp +1 -1
  127. data/ext/libsass/src/sass_values.cpp +26 -21
  128. data/ext/libsass/src/settings.hpp +19 -0
  129. data/ext/libsass/src/source.cpp +69 -0
  130. data/ext/libsass/src/source.hpp +95 -0
  131. data/ext/libsass/src/source_data.hpp +32 -0
  132. data/ext/libsass/src/source_map.cpp +27 -20
  133. data/ext/libsass/src/source_map.hpp +14 -11
  134. data/ext/libsass/src/stylesheet.cpp +22 -0
  135. data/ext/libsass/src/stylesheet.hpp +57 -0
  136. data/ext/libsass/src/to_value.cpp +24 -22
  137. data/ext/libsass/src/to_value.hpp +18 -22
  138. data/ext/libsass/src/units.cpp +28 -22
  139. data/ext/libsass/src/units.hpp +9 -8
  140. data/ext/libsass/src/utf8/checked.h +12 -10
  141. data/ext/libsass/src/utf8/core.h +3 -0
  142. data/ext/libsass/src/utf8_string.cpp +12 -10
  143. data/ext/libsass/src/utf8_string.hpp +7 -6
  144. data/ext/libsass/src/util.cpp +97 -107
  145. data/ext/libsass/src/util.hpp +74 -30
  146. data/ext/libsass/src/util_string.cpp +125 -0
  147. data/ext/libsass/src/util_string.hpp +73 -0
  148. data/ext/libsass/src/values.cpp +33 -24
  149. data/ext/libsass/src/values.hpp +2 -2
  150. data/lib/sassc.rb +24 -0
  151. data/lib/sassc/engine.rb +7 -5
  152. data/lib/sassc/functions_handler.rb +11 -13
  153. data/lib/sassc/native.rb +10 -9
  154. data/lib/sassc/native/native_functions_api.rb +0 -5
  155. data/lib/sassc/script.rb +4 -6
  156. data/lib/sassc/version.rb +1 -1
  157. data/sassc.gemspec +32 -12
  158. data/test/engine_test.rb +32 -2
  159. data/test/functions_test.rb +38 -1
  160. data/test/native_test.rb +4 -4
  161. metadata +95 -109
  162. data/ext/Rakefile +0 -3
  163. data/ext/libsass/.editorconfig +0 -15
  164. data/ext/libsass/.gitattributes +0 -2
  165. data/ext/libsass/.github/CONTRIBUTING.md +0 -65
  166. data/ext/libsass/.github/ISSUE_TEMPLATE.md +0 -54
  167. data/ext/libsass/.gitignore +0 -85
  168. data/ext/libsass/.travis.yml +0 -64
  169. data/ext/libsass/COPYING +0 -25
  170. data/ext/libsass/GNUmakefile.am +0 -88
  171. data/ext/libsass/INSTALL +0 -1
  172. data/ext/libsass/LICENSE +0 -25
  173. data/ext/libsass/Makefile +0 -351
  174. data/ext/libsass/Makefile.conf +0 -55
  175. data/ext/libsass/Readme.md +0 -104
  176. data/ext/libsass/SECURITY.md +0 -10
  177. data/ext/libsass/appveyor.yml +0 -91
  178. data/ext/libsass/configure.ac +0 -138
  179. data/ext/libsass/contrib/libsass.spec +0 -66
  180. data/ext/libsass/docs/README.md +0 -20
  181. data/ext/libsass/docs/api-context-example.md +0 -45
  182. data/ext/libsass/docs/api-context-internal.md +0 -163
  183. data/ext/libsass/docs/api-context.md +0 -295
  184. data/ext/libsass/docs/api-doc.md +0 -215
  185. data/ext/libsass/docs/api-function-example.md +0 -67
  186. data/ext/libsass/docs/api-function-internal.md +0 -8
  187. data/ext/libsass/docs/api-function.md +0 -74
  188. data/ext/libsass/docs/api-importer-example.md +0 -112
  189. data/ext/libsass/docs/api-importer-internal.md +0 -20
  190. data/ext/libsass/docs/api-importer.md +0 -86
  191. data/ext/libsass/docs/api-value-example.md +0 -55
  192. data/ext/libsass/docs/api-value-internal.md +0 -76
  193. data/ext/libsass/docs/api-value.md +0 -154
  194. data/ext/libsass/docs/build-on-darwin.md +0 -27
  195. data/ext/libsass/docs/build-on-gentoo.md +0 -55
  196. data/ext/libsass/docs/build-on-windows.md +0 -139
  197. data/ext/libsass/docs/build-shared-library.md +0 -35
  198. data/ext/libsass/docs/build-with-autotools.md +0 -78
  199. data/ext/libsass/docs/build-with-makefiles.md +0 -68
  200. data/ext/libsass/docs/build-with-mingw.md +0 -107
  201. data/ext/libsass/docs/build-with-visual-studio.md +0 -90
  202. data/ext/libsass/docs/build.md +0 -97
  203. data/ext/libsass/docs/compatibility-plan.md +0 -48
  204. data/ext/libsass/docs/contributing.md +0 -17
  205. data/ext/libsass/docs/custom-functions-internal.md +0 -122
  206. data/ext/libsass/docs/dev-ast-memory.md +0 -223
  207. data/ext/libsass/docs/implementations.md +0 -56
  208. data/ext/libsass/docs/plugins.md +0 -47
  209. data/ext/libsass/docs/setup-environment.md +0 -68
  210. data/ext/libsass/docs/source-map-internals.md +0 -51
  211. data/ext/libsass/docs/trace.md +0 -26
  212. data/ext/libsass/docs/triage.md +0 -17
  213. data/ext/libsass/docs/unicode.md +0 -39
  214. data/ext/libsass/extconf.rb +0 -6
  215. data/ext/libsass/include/sass/version.h.in +0 -12
  216. data/ext/libsass/m4/.gitkeep +0 -0
  217. data/ext/libsass/m4/m4-ax_cxx_compile_stdcxx_11.m4 +0 -167
  218. data/ext/libsass/res/resource.rc +0 -35
  219. data/ext/libsass/script/bootstrap +0 -13
  220. data/ext/libsass/script/branding +0 -10
  221. data/ext/libsass/script/ci-build-libsass +0 -134
  222. data/ext/libsass/script/ci-build-plugin +0 -62
  223. data/ext/libsass/script/ci-install-compiler +0 -6
  224. data/ext/libsass/script/ci-install-deps +0 -20
  225. data/ext/libsass/script/ci-report-coverage +0 -42
  226. data/ext/libsass/script/spec +0 -5
  227. data/ext/libsass/script/tap-driver +0 -652
  228. data/ext/libsass/script/tap-runner +0 -1
  229. data/ext/libsass/script/test-leaks.pl +0 -103
  230. data/ext/libsass/src/GNUmakefile.am +0 -54
  231. data/ext/libsass/src/extend.cpp +0 -2130
  232. data/ext/libsass/src/extend.hpp +0 -86
  233. data/ext/libsass/src/functions.cpp +0 -2234
  234. data/ext/libsass/src/functions.hpp +0 -198
  235. data/ext/libsass/src/memory/SharedPtr.cpp +0 -114
  236. data/ext/libsass/src/memory/SharedPtr.hpp +0 -206
  237. data/ext/libsass/src/node.cpp +0 -319
  238. data/ext/libsass/src/node.hpp +0 -118
  239. data/ext/libsass/src/paths.hpp +0 -71
  240. data/ext/libsass/src/sass_util.cpp +0 -149
  241. data/ext/libsass/src/sass_util.hpp +0 -256
  242. data/ext/libsass/src/subset_map.cpp +0 -55
  243. data/ext/libsass/src/subset_map.hpp +0 -76
  244. data/ext/libsass/src/support/libsass.pc.in +0 -11
  245. data/ext/libsass/src/to_c.hpp +0 -39
  246. data/ext/libsass/test/test_node.cpp +0 -94
  247. data/ext/libsass/test/test_paths.cpp +0 -28
  248. data/ext/libsass/test/test_selector_difference.cpp +0 -25
  249. data/ext/libsass/test/test_specificity.cpp +0 -25
  250. data/ext/libsass/test/test_subset_map.cpp +0 -472
  251. data/ext/libsass/test/test_superselector.cpp +0 -69
  252. data/ext/libsass/test/test_unification.cpp +0 -31
  253. data/ext/libsass/version.sh +0 -10
  254. data/ext/libsass/win/libsass.sln +0 -39
  255. data/ext/libsass/win/libsass.sln.DotSettings +0 -9
  256. data/ext/libsass/win/libsass.targets +0 -118
  257. data/ext/libsass/win/libsass.vcxproj +0 -188
  258. data/ext/libsass/win/libsass.vcxproj.filters +0 -357
  259. data/lib/sassc/native/lib_c.rb +0 -21
  260. data/lib/tasks/libsass.rb +0 -33
@@ -0,0 +1,34 @@
1
+ #ifndef SASS_FN_STRINGS_H
2
+ #define SASS_FN_STRINGS_H
3
+
4
+ #include "fn_utils.hpp"
5
+
6
+ namespace Sass {
7
+
8
+ namespace Functions {
9
+
10
+ extern Signature unquote_sig;
11
+ extern Signature quote_sig;
12
+ extern Signature str_length_sig;
13
+ extern Signature str_insert_sig;
14
+ extern Signature str_index_sig;
15
+ extern Signature str_slice_sig;
16
+ extern Signature to_upper_case_sig;
17
+ extern Signature to_lower_case_sig;
18
+ extern Signature length_sig;
19
+
20
+ BUILT_IN(sass_unquote);
21
+ BUILT_IN(sass_quote);
22
+ BUILT_IN(str_length);
23
+ BUILT_IN(str_insert);
24
+ BUILT_IN(str_index);
25
+ BUILT_IN(str_slice);
26
+ BUILT_IN(to_upper_case);
27
+ BUILT_IN(to_lower_case);
28
+ BUILT_IN(length);
29
+
30
+ }
31
+
32
+ }
33
+
34
+ #endif
@@ -0,0 +1,158 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
3
+ #include "sass.hpp"
4
+
5
+ #include "parser.hpp"
6
+ #include "fn_utils.hpp"
7
+ #include "util_string.hpp"
8
+
9
+ namespace Sass {
10
+
11
+ Definition* make_native_function(Signature sig, Native_Function func, Context& ctx)
12
+ {
13
+ SourceFile* source = SASS_MEMORY_NEW(SourceFile, "[built-in function]", sig, std::string::npos);
14
+ Parser sig_parser(source, ctx, ctx.traces);
15
+ sig_parser.lex<Prelexer::identifier>();
16
+ sass::string name(Util::normalize_underscores(sig_parser.lexed));
17
+ Parameters_Obj params = sig_parser.parse_parameters();
18
+ return SASS_MEMORY_NEW(Definition,
19
+ SourceSpan(source),
20
+ sig,
21
+ name,
22
+ params,
23
+ func,
24
+ false);
25
+ }
26
+
27
+ Definition* make_c_function(Sass_Function_Entry c_func, Context& ctx)
28
+ {
29
+ using namespace Prelexer;
30
+ const char* sig = sass_function_get_signature(c_func);
31
+ SourceFile* source = SASS_MEMORY_NEW(SourceFile, "[c function]", sig, std::string::npos);
32
+ Parser sig_parser(source, ctx, ctx.traces);
33
+ // allow to overload generic callback plus @warn, @error and @debug with custom functions
34
+ sig_parser.lex < alternatives < identifier, exactly <'*'>,
35
+ exactly < Constants::warn_kwd >,
36
+ exactly < Constants::error_kwd >,
37
+ exactly < Constants::debug_kwd >
38
+ > >();
39
+ sass::string name(Util::normalize_underscores(sig_parser.lexed));
40
+ Parameters_Obj params = sig_parser.parse_parameters();
41
+ return SASS_MEMORY_NEW(Definition,
42
+ SourceSpan(source),
43
+ sig,
44
+ name,
45
+ params,
46
+ c_func);
47
+ }
48
+
49
+ namespace Functions {
50
+
51
+ sass::string function_name(Signature sig)
52
+ {
53
+ sass::string str(sig);
54
+ return str.substr(0, str.find('('));
55
+ }
56
+
57
+ Map* get_arg_m(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces)
58
+ {
59
+ AST_Node* value = env[argname];
60
+ if (Map* map = Cast<Map>(value)) return map;
61
+ List* list = Cast<List>(value);
62
+ if (list && list->length() == 0) {
63
+ return SASS_MEMORY_NEW(Map, pstate, 0);
64
+ }
65
+ return get_arg<Map>(argname, env, sig, pstate, traces);
66
+ }
67
+
68
+ double get_arg_r(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, double lo, double hi)
69
+ {
70
+ Number* val = get_arg<Number>(argname, env, sig, pstate, traces);
71
+ Number tmpnr(val);
72
+ tmpnr.reduce();
73
+ double v = tmpnr.value();
74
+ if (!(lo <= v && v <= hi)) {
75
+ sass::ostream msg;
76
+ msg << "argument `" << argname << "` of `" << sig << "` must be between ";
77
+ msg << lo << " and " << hi;
78
+ error(msg.str(), pstate, traces);
79
+ }
80
+ return v;
81
+ }
82
+
83
+ Number* get_arg_n(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces)
84
+ {
85
+ Number* val = get_arg<Number>(argname, env, sig, pstate, traces);
86
+ val = SASS_MEMORY_COPY(val);
87
+ val->reduce();
88
+ return val;
89
+ }
90
+
91
+ double get_arg_val(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces)
92
+ {
93
+ Number* val = get_arg<Number>(argname, env, sig, pstate, traces);
94
+ Number tmpnr(val);
95
+ tmpnr.reduce();
96
+ return tmpnr.value();
97
+ }
98
+
99
+ double color_num(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces)
100
+ {
101
+ Number* val = get_arg<Number>(argname, env, sig, pstate, traces);
102
+ Number tmpnr(val);
103
+ tmpnr.reduce();
104
+ if (tmpnr.unit() == "%") {
105
+ return std::min(std::max(tmpnr.value() * 255 / 100.0, 0.0), 255.0);
106
+ } else {
107
+ return std::min(std::max(tmpnr.value(), 0.0), 255.0);
108
+ }
109
+ }
110
+
111
+ double alpha_num(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces) {
112
+ Number* val = get_arg<Number>(argname, env, sig, pstate, traces);
113
+ Number tmpnr(val);
114
+ tmpnr.reduce();
115
+ if (tmpnr.unit() == "%") {
116
+ return std::min(std::max(tmpnr.value(), 0.0), 100.0);
117
+ } else {
118
+ return std::min(std::max(tmpnr.value(), 0.0), 1.0);
119
+ }
120
+ }
121
+
122
+ SelectorListObj get_arg_sels(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, Context& ctx) {
123
+ ExpressionObj exp = ARG(argname, Expression);
124
+ if (exp->concrete_type() == Expression::NULL_VAL) {
125
+ sass::ostream msg;
126
+ msg << argname << ": null is not a valid selector: it must be a string,\n";
127
+ msg << "a list of strings, or a list of lists of strings for `" << function_name(sig) << "'";
128
+ error(msg.str(), exp->pstate(), traces);
129
+ }
130
+ if (String_Constant* str = Cast<String_Constant>(exp)) {
131
+ str->quote_mark(0);
132
+ }
133
+ sass::string exp_src = exp->to_string(ctx.c_options);
134
+ ItplFile* source = SASS_MEMORY_NEW(ItplFile, exp_src.c_str(), exp->pstate());
135
+ return Parser::parse_selector(source, ctx, traces, false);
136
+ }
137
+
138
+ CompoundSelectorObj get_arg_sel(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, Context& ctx) {
139
+ ExpressionObj exp = ARG(argname, Expression);
140
+ if (exp->concrete_type() == Expression::NULL_VAL) {
141
+ sass::ostream msg;
142
+ msg << argname << ": null is not a string for `" << function_name(sig) << "'";
143
+ error(msg.str(), exp->pstate(), traces);
144
+ }
145
+ if (String_Constant* str = Cast<String_Constant>(exp)) {
146
+ str->quote_mark(0);
147
+ }
148
+ sass::string exp_src = exp->to_string(ctx.c_options);
149
+ ItplFile* source = SASS_MEMORY_NEW(ItplFile, exp_src.c_str(), exp->pstate());
150
+ SelectorListObj sel_list = Parser::parse_selector(source, ctx, traces, false);
151
+ if (sel_list->length() == 0) return {};
152
+ return sel_list->first()->first();
153
+ }
154
+
155
+
156
+ }
157
+
158
+ }
@@ -0,0 +1,62 @@
1
+ #ifndef SASS_FN_UTILS_H
2
+ #define SASS_FN_UTILS_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 "units.hpp"
9
+ #include "backtrace.hpp"
10
+ #include "environment.hpp"
11
+ #include "ast_fwd_decl.hpp"
12
+ #include "error_handling.hpp"
13
+
14
+ namespace Sass {
15
+
16
+ #define FN_PROTOTYPE \
17
+ Env& env, \
18
+ Env& d_env, \
19
+ Context& ctx, \
20
+ Signature sig, \
21
+ SourceSpan pstate, \
22
+ Backtraces& traces, \
23
+ SelectorStack selector_stack, \
24
+ SelectorStack original_stack \
25
+
26
+ typedef const char* Signature;
27
+ typedef PreValue* (*Native_Function)(FN_PROTOTYPE);
28
+ #define BUILT_IN(name) PreValue* name(FN_PROTOTYPE)
29
+
30
+ #define ARG(argname, argtype) get_arg<argtype>(argname, env, sig, pstate, traces)
31
+ // special function for weird hsla percent (10px == 10% == 10 != 0.1)
32
+ #define ARGVAL(argname) get_arg_val(argname, env, sig, pstate, traces) // double
33
+
34
+ Definition* make_native_function(Signature, Native_Function, Context& ctx);
35
+ Definition* make_c_function(Sass_Function_Entry c_func, Context& ctx);
36
+
37
+ namespace Functions {
38
+
39
+ template <typename T>
40
+ T* get_arg(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces)
41
+ {
42
+ T* val = Cast<T>(env[argname]);
43
+ if (!val) {
44
+ error("argument `" + argname + "` of `" + sig + "` must be a " + T::type_name(), pstate, traces);
45
+ }
46
+ return val;
47
+ }
48
+
49
+ Map* get_arg_m(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces); // maps only
50
+ Number* get_arg_n(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces); // numbers only
51
+ double alpha_num(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces); // colors only
52
+ double color_num(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces); // colors only
53
+ double get_arg_r(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, double lo, double hi); // colors only
54
+ double get_arg_val(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces); // shared
55
+ SelectorListObj get_arg_sels(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, Context& ctx); // selectors only
56
+ CompoundSelectorObj get_arg_sel(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, Context& ctx); // selectors only
57
+
58
+ }
59
+
60
+ }
61
+
62
+ #endif
@@ -1,4 +1,7 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
1
3
  #include "sass.hpp"
4
+
2
5
  #include <cmath>
3
6
  #include <string>
4
7
  #include <iostream>
@@ -21,7 +24,7 @@ namespace Sass {
21
24
  Inspect::~Inspect() { }
22
25
 
23
26
  // statements
24
- void Inspect::operator()(Block_Ptr block)
27
+ void Inspect::operator()(Block* block)
25
28
  {
26
29
  if (!block->is_root()) {
27
30
  add_open_mapping(block);
@@ -39,25 +42,23 @@ namespace Sass {
39
42
 
40
43
  }
41
44
 
42
- void Inspect::operator()(Ruleset_Ptr ruleset)
45
+ void Inspect::operator()(StyleRule* ruleset)
43
46
  {
44
47
  if (ruleset->selector()) {
45
- opt.in_selector = true;
46
48
  ruleset->selector()->perform(this);
47
- opt.in_selector = false;
48
49
  }
49
50
  if (ruleset->block()) {
50
51
  ruleset->block()->perform(this);
51
52
  }
52
53
  }
53
54
 
54
- void Inspect::operator()(Keyframe_Rule_Ptr rule)
55
+ void Inspect::operator()(Keyframe_Rule* rule)
55
56
  {
56
57
  if (rule->name()) rule->name()->perform(this);
57
58
  if (rule->block()) rule->block()->perform(this);
58
59
  }
59
60
 
60
- void Inspect::operator()(Bubble_Ptr bubble)
61
+ void Inspect::operator()(Bubble* bubble)
61
62
  {
62
63
  append_indentation();
63
64
  append_token("::BUBBLE", bubble);
@@ -66,18 +67,64 @@ namespace Sass {
66
67
  append_scope_closer();
67
68
  }
68
69
 
69
- void Inspect::operator()(Media_Block_Ptr media_block)
70
+ void Inspect::operator()(MediaRule* rule)
71
+ {
72
+ append_indentation();
73
+ append_token("@media", rule);
74
+ append_mandatory_space();
75
+ if (rule->block()) {
76
+ rule->block()->perform(this);
77
+ }
78
+ }
79
+
80
+ void Inspect::operator()(CssMediaRule* rule)
70
81
  {
82
+ if (output_style() == NESTED)
83
+ indentation += rule->tabs();
71
84
  append_indentation();
72
- append_token("@media", media_block);
85
+ append_token("@media", rule);
73
86
  append_mandatory_space();
74
87
  in_media_block = true;
75
- media_block->media_queries()->perform(this);
88
+ bool joinIt = false;
89
+ for (auto query : rule->elements()) {
90
+ if (joinIt) {
91
+ append_comma_separator();
92
+ append_optional_space();
93
+ }
94
+ operator()(query);
95
+ joinIt = true;
96
+ }
97
+ if (rule->block()) {
98
+ rule->block()->perform(this);
99
+ }
76
100
  in_media_block = false;
77
- media_block->block()->perform(this);
101
+ if (output_style() == NESTED)
102
+ indentation -= rule->tabs();
103
+ }
104
+
105
+ void Inspect::operator()(CssMediaQuery* query)
106
+ {
107
+ bool joinIt = false;
108
+ if (!query->modifier().empty()) {
109
+ append_string(query->modifier());
110
+ append_mandatory_space();
111
+ }
112
+ if (!query->type().empty()) {
113
+ append_string(query->type());
114
+ joinIt = true;
115
+ }
116
+ for (auto feature : query->features()) {
117
+ if (joinIt) {
118
+ append_mandatory_space();
119
+ append_string("and");
120
+ append_mandatory_space();
121
+ }
122
+ append_string(feature);
123
+ joinIt = true;
124
+ }
78
125
  }
79
126
 
80
- void Inspect::operator()(Supports_Block_Ptr feature_block)
127
+ void Inspect::operator()(SupportsRule* feature_block)
81
128
  {
82
129
  append_indentation();
83
130
  append_token("@supports", feature_block);
@@ -86,7 +133,7 @@ namespace Sass {
86
133
  feature_block->block()->perform(this);
87
134
  }
88
135
 
89
- void Inspect::operator()(At_Root_Block_Ptr at_root_block)
136
+ void Inspect::operator()(AtRootRule* at_root_block)
90
137
  {
91
138
  append_indentation();
92
139
  append_token("@at-root ", at_root_block);
@@ -95,7 +142,7 @@ namespace Sass {
95
142
  if(at_root_block->block()) at_root_block->block()->perform(this);
96
143
  }
97
144
 
98
- void Inspect::operator()(Directive_Ptr at_rule)
145
+ void Inspect::operator()(AtRule* at_rule)
99
146
  {
100
147
  append_indentation();
101
148
  append_token(at_rule->keyword(), at_rule);
@@ -118,7 +165,7 @@ namespace Sass {
118
165
  }
119
166
  }
120
167
 
121
- void Inspect::operator()(Declaration_Ptr dec)
168
+ void Inspect::operator()(Declaration* dec)
122
169
  {
123
170
  if (dec->value()->concrete_type() == Expression::NULL_VAL) return;
124
171
  bool was_decl = in_declaration;
@@ -133,8 +180,7 @@ namespace Sass {
133
180
  append_colon_separator();
134
181
 
135
182
  if (dec->value()->concrete_type() == Expression::SELECTOR) {
136
- Listize listize;
137
- Expression_Obj ls = dec->value()->perform(&listize);
183
+ ExpressionObj ls = Listize::perform(dec->value());
138
184
  ls->perform(this);
139
185
  } else {
140
186
  dec->value()->perform(this);
@@ -150,7 +196,7 @@ namespace Sass {
150
196
  in_declaration = was_decl;
151
197
  }
152
198
 
153
- void Inspect::operator()(Assignment_Ptr assn)
199
+ void Inspect::operator()(Assignment* assn)
154
200
  {
155
201
  append_token(assn->variable(), assn);
156
202
  append_colon_separator();
@@ -162,7 +208,7 @@ namespace Sass {
162
208
  append_delimiter();
163
209
  }
164
210
 
165
- void Inspect::operator()(Import_Ptr import)
211
+ void Inspect::operator()(Import* import)
166
212
  {
167
213
  if (!import->urls().empty()) {
168
214
  append_token("@import", import);
@@ -193,7 +239,7 @@ namespace Sass {
193
239
  }
194
240
  }
195
241
 
196
- void Inspect::operator()(Import_Stub_Ptr import)
242
+ void Inspect::operator()(Import_Stub* import)
197
243
  {
198
244
  append_indentation();
199
245
  append_token("@import", import);
@@ -202,7 +248,7 @@ namespace Sass {
202
248
  append_delimiter();
203
249
  }
204
250
 
205
- void Inspect::operator()(Warning_Ptr warning)
251
+ void Inspect::operator()(WarningRule* warning)
206
252
  {
207
253
  append_indentation();
208
254
  append_token("@warn", warning);
@@ -211,7 +257,7 @@ namespace Sass {
211
257
  append_delimiter();
212
258
  }
213
259
 
214
- void Inspect::operator()(Error_Ptr error)
260
+ void Inspect::operator()(ErrorRule* error)
215
261
  {
216
262
  append_indentation();
217
263
  append_token("@error", error);
@@ -220,7 +266,7 @@ namespace Sass {
220
266
  append_delimiter();
221
267
  }
222
268
 
223
- void Inspect::operator()(Debug_Ptr debug)
269
+ void Inspect::operator()(DebugRule* debug)
224
270
  {
225
271
  append_indentation();
226
272
  append_token("@debug", debug);
@@ -229,14 +275,14 @@ namespace Sass {
229
275
  append_delimiter();
230
276
  }
231
277
 
232
- void Inspect::operator()(Comment_Ptr comment)
278
+ void Inspect::operator()(Comment* comment)
233
279
  {
234
280
  in_comment = true;
235
281
  comment->text()->perform(this);
236
282
  in_comment = false;
237
283
  }
238
284
 
239
- void Inspect::operator()(If_Ptr cond)
285
+ void Inspect::operator()(If* cond)
240
286
  {
241
287
  append_indentation();
242
288
  append_token("@if", cond);
@@ -251,7 +297,7 @@ namespace Sass {
251
297
  }
252
298
  }
253
299
 
254
- void Inspect::operator()(For_Ptr loop)
300
+ void Inspect::operator()(ForRule* loop)
255
301
  {
256
302
  append_indentation();
257
303
  append_token("@for", loop);
@@ -264,7 +310,7 @@ namespace Sass {
264
310
  loop->block()->perform(this);
265
311
  }
266
312
 
267
- void Inspect::operator()(Each_Ptr loop)
313
+ void Inspect::operator()(EachRule* loop)
268
314
  {
269
315
  append_indentation();
270
316
  append_token("@each", loop);
@@ -279,7 +325,7 @@ namespace Sass {
279
325
  loop->block()->perform(this);
280
326
  }
281
327
 
282
- void Inspect::operator()(While_Ptr loop)
328
+ void Inspect::operator()(WhileRule* loop)
283
329
  {
284
330
  append_indentation();
285
331
  append_token("@while", loop);
@@ -288,7 +334,7 @@ namespace Sass {
288
334
  loop->block()->perform(this);
289
335
  }
290
336
 
291
- void Inspect::operator()(Return_Ptr ret)
337
+ void Inspect::operator()(Return* ret)
292
338
  {
293
339
  append_indentation();
294
340
  append_token("@return", ret);
@@ -297,7 +343,7 @@ namespace Sass {
297
343
  append_delimiter();
298
344
  }
299
345
 
300
- void Inspect::operator()(Extension_Ptr extend)
346
+ void Inspect::operator()(ExtendRule* extend)
301
347
  {
302
348
  append_indentation();
303
349
  append_token("@extend", extend);
@@ -306,7 +352,7 @@ namespace Sass {
306
352
  append_delimiter();
307
353
  }
308
354
 
309
- void Inspect::operator()(Definition_Ptr def)
355
+ void Inspect::operator()(Definition* def)
310
356
  {
311
357
  append_indentation();
312
358
  if (def->type() == Definition::MIXIN) {
@@ -321,7 +367,7 @@ namespace Sass {
321
367
  def->block()->perform(this);
322
368
  }
323
369
 
324
- void Inspect::operator()(Mixin_Call_Ptr call)
370
+ void Inspect::operator()(Mixin_Call* call)
325
371
  {
326
372
  append_indentation();
327
373
  append_token("@include", call);
@@ -337,14 +383,14 @@ namespace Sass {
337
383
  if (!call->block()) append_delimiter();
338
384
  }
339
385
 
340
- void Inspect::operator()(Content_Ptr content)
386
+ void Inspect::operator()(Content* content)
341
387
  {
342
388
  append_indentation();
343
389
  append_token("@content", content);
344
390
  append_delimiter();
345
391
  }
346
392
 
347
- void Inspect::operator()(Map_Ptr map)
393
+ void Inspect::operator()(Map* map)
348
394
  {
349
395
  if (output_style() == TO_SASS && map->empty()) {
350
396
  append_string("()");
@@ -366,22 +412,22 @@ namespace Sass {
366
412
  append_string(")");
367
413
  }
368
414
 
369
- std::string Inspect::lbracket(List_Ptr list) {
415
+ sass::string Inspect::lbracket(List* list) {
370
416
  return list->is_bracketed() ? "[" : "(";
371
417
  }
372
418
 
373
- std::string Inspect::rbracket(List_Ptr list) {
419
+ sass::string Inspect::rbracket(List* list) {
374
420
  return list->is_bracketed() ? "]" : ")";
375
421
  }
376
422
 
377
- void Inspect::operator()(List_Ptr list)
423
+ void Inspect::operator()(List* list)
378
424
  {
379
425
  if (list->empty() && (output_style() == TO_SASS || list->is_bracketed())) {
380
426
  append_string(lbracket(list));
381
427
  append_string(rbracket(list));
382
428
  return;
383
429
  }
384
- std::string sep(list->separator() == SASS_SPACE ? " " : ",");
430
+ sass::string sep(list->separator() == SASS_SPACE ? " " : ",");
385
431
  if ((output_style() != COMPRESSED) && sep == ",") sep += " ";
386
432
  else if (in_media_block && sep != " ") sep += " "; // verified
387
433
  if (list->empty()) return;
@@ -398,7 +444,7 @@ namespace Sass {
398
444
  list->length() == 1 &&
399
445
  !list->from_selector() &&
400
446
  !Cast<List>(list->at(0)) &&
401
- !Cast<Selector_List>(list->at(0))
447
+ !Cast<SelectorList>(list->at(0))
402
448
  ) {
403
449
  append_string(lbracket(list));
404
450
  }
@@ -415,7 +461,7 @@ namespace Sass {
415
461
  for (size_t i = 0, L = list->size(); i < L; ++i) {
416
462
  if (list->separator() == SASS_HASH)
417
463
  { sep[0] = i % 2 ? ':' : ','; }
418
- Expression_Obj list_item = list->at(i);
464
+ ExpressionObj list_item = list->at(i);
419
465
  if (output_style() != TO_SASS) {
420
466
  if (list_item->is_invisible()) {
421
467
  // this fixes an issue with "" in a list
@@ -448,7 +494,7 @@ namespace Sass {
448
494
  list->length() == 1 &&
449
495
  !list->from_selector() &&
450
496
  !Cast<List>(list->at(0)) &&
451
- !Cast<Selector_List>(list->at(0))
497
+ !Cast<SelectorList>(list->at(0))
452
498
  ) {
453
499
  append_string(",");
454
500
  append_string(rbracket(list));
@@ -462,7 +508,7 @@ namespace Sass {
462
508
 
463
509
  }
464
510
 
465
- void Inspect::operator()(Binary_Expression_Ptr expr)
511
+ void Inspect::operator()(Binary_Expression* expr)
466
512
  {
467
513
  expr->left()->perform(this);
468
514
  if ( in_media_block ||
@@ -499,7 +545,7 @@ namespace Sass {
499
545
  expr->right()->perform(this);
500
546
  }
501
547
 
502
- void Inspect::operator()(Unary_Expression_Ptr expr)
548
+ void Inspect::operator()(Unary_Expression* expr)
503
549
  {
504
550
  if (expr->optype() == Unary_Expression::PLUS) append_string("+");
505
551
  else if (expr->optype() == Unary_Expression::SLASH) append_string("/");
@@ -507,91 +553,42 @@ namespace Sass {
507
553
  expr->operand()->perform(this);
508
554
  }
509
555
 
510
- void Inspect::operator()(Function_Call_Ptr call)
556
+ void Inspect::operator()(Function_Call* call)
511
557
  {
512
558
  append_token(call->name(), call);
513
559
  call->arguments()->perform(this);
514
560
  }
515
561
 
516
- void Inspect::operator()(Function_Call_Schema_Ptr call)
517
- {
518
- call->name()->perform(this);
519
- call->arguments()->perform(this);
520
- }
521
-
522
- void Inspect::operator()(Variable_Ptr var)
562
+ void Inspect::operator()(Variable* var)
523
563
  {
524
564
  append_token(var->name(), var);
525
565
  }
526
566
 
527
- void Inspect::operator()(Number_Ptr n)
567
+ void Inspect::operator()(Number* n)
528
568
  {
529
569
 
530
- std::string res;
531
-
532
570
  // reduce units
533
571
  n->reduce();
534
572
 
535
- // check if the fractional part of the value equals to zero
536
- // neat trick from http://stackoverflow.com/a/1521682/1550314
537
- // double int_part; bool is_int = modf(value, &int_part) == 0.0;
538
-
539
- // this all cannot be done with one run only, since fixed
540
- // output differs from normal output and regular output
541
- // can contain scientific notation which we do not want!
573
+ sass::ostream ss;
574
+ ss.precision(opt.precision);
575
+ ss << std::fixed << n->value();
542
576
 
543
- // first sample
544
- std::stringstream ss;
545
- ss.precision(12);
546
- ss << n->value();
577
+ sass::string res = ss.str();
578
+ size_t s = res.length();
547
579
 
548
- // check if we got scientific notation in result
549
- if (ss.str().find_first_of("e") != std::string::npos) {
550
- ss.clear(); ss.str(std::string());
551
- ss.precision(std::max(12, opt.precision));
552
- ss << std::fixed << n->value();
553
- }
554
-
555
- std::string tmp = ss.str();
556
- size_t pos_point = tmp.find_first_of(".,");
557
- size_t pos_fract = tmp.find_last_not_of("0");
558
- bool is_int = pos_point == pos_fract ||
559
- pos_point == std::string::npos;
560
-
561
- // reset stream for another run
562
- ss.clear(); ss.str(std::string());
563
-
564
- // take a shortcut for integers
565
- if (is_int)
580
+ // delete trailing zeros
581
+ for(s = s - 1; s > 0; --s)
566
582
  {
567
- ss.precision(0);
568
- ss << std::fixed << n->value();
569
- res = std::string(ss.str());
570
- }
571
- // process floats
572
- else
573
- {
574
- // do we have have too much precision?
575
- if (pos_fract < opt.precision + pos_point)
576
- { ss.precision((int)(pos_fract - pos_point)); }
577
- else { ss.precision(opt.precision); }
578
- // round value again
579
- ss << std::fixed << n->value();
580
- res = std::string(ss.str());
581
- // maybe we truncated up to decimal point
582
- size_t pos = res.find_last_not_of("0");
583
- // handle case where we have a "0"
584
- if (pos == std::string::npos) {
585
- res = "0.0";
586
- } else {
587
- bool at_dec_point = res[pos] == '.' ||
588
- res[pos] == ',';
589
- // don't leave a blank point
590
- if (at_dec_point) ++ pos;
591
- res.resize (pos + 1);
592
- }
583
+ if(res[s] == '0') {
584
+ res.erase(s, 1);
585
+ }
586
+ else break;
593
587
  }
594
588
 
589
+ // delete trailing decimal separator
590
+ if(res[s] == '.') res.erase(s, 1);
591
+
595
592
  // some final cosmetics
596
593
  if (res == "0.0") res = "0";
597
594
  else if (res == "") res = "0";
@@ -599,15 +596,22 @@ namespace Sass {
599
596
  else if (res == "-0.0") res = "0";
600
597
  else if (opt.output_style == COMPRESSED)
601
598
  {
602
- // check if handling negative nr
603
- size_t off = res[0] == '-' ? 1 : 0;
604
- // remove leading zero from floating point in compressed mode
605
- if (n->zero() && res[off] == '0' && res[off+1] == '.') res.erase(off, 1);
599
+ if (n->zero()) {
600
+ // check if handling negative nr
601
+ size_t off = res[0] == '-' ? 1 : 0;
602
+ // remove leading zero from floating point in compressed mode
603
+ if (res[off] == '0' && res[off+1] == '.') res.erase(off, 1);
604
+ }
606
605
  }
607
606
 
608
607
  // add unit now
609
608
  res += n->unit();
610
609
 
610
+ if (opt.output_style == TO_CSS && !n->is_valid_css_unit()) {
611
+ // traces.push_back(Backtrace(nr->pstate()));
612
+ throw Exception::InvalidValue({}, *n);
613
+ }
614
+
611
615
  // output the final token
612
616
  append_token(res, n);
613
617
  }
@@ -620,22 +624,17 @@ namespace Sass {
620
624
  else return c;
621
625
  }
622
626
 
623
- void Inspect::operator()(Color_Ptr c)
627
+ void Inspect::operator()(Color_RGBA* c)
624
628
  {
625
629
  // output the final token
626
- std::stringstream ss;
630
+ sass::ostream ss;
627
631
 
628
632
  // original color name
629
633
  // maybe an unknown token
630
- std::string name = c->disp();
631
-
632
- if (opt.in_selector && name != "") {
633
- append_token(name, c);
634
- return;
635
- }
634
+ sass::string name = c->disp();
636
635
 
637
636
  // resolved color
638
- std::string res_name = name;
637
+ sass::string res_name = name;
639
638
 
640
639
  double r = Sass::round(cap_channel<0xff>(c->r()), opt.precision);
641
640
  double g = Sass::round(cap_channel<0xff>(c->g()), opt.precision);
@@ -644,7 +643,7 @@ namespace Sass {
644
643
 
645
644
  // get color from given name (if one was given at all)
646
645
  if (name != "" && name_to_color(name)) {
647
- Color_Ptr_Const n = name_to_color(name);
646
+ const Color_RGBA* n = name_to_color(name);
648
647
  r = Sass::round(cap_channel<0xff>(n->r()), opt.precision);
649
648
  g = Sass::round(cap_channel<0xff>(n->g()), opt.precision);
650
649
  b = Sass::round(cap_channel<0xff>(n->b()), opt.precision);
@@ -657,7 +656,10 @@ namespace Sass {
657
656
  res_name = color_to_name(numval);
658
657
  }
659
658
 
660
- std::stringstream hexlet;
659
+ sass::ostream hexlet;
660
+ // dart sass compressed all colors in regular css always
661
+ // ruby sass and libsass does it only when not delayed
662
+ // since color math is going to be removed, this can go too
661
663
  bool compressed = opt.output_style == COMPRESSED;
662
664
  hexlet << '#' << std::setw(1) << std::setfill('0');
663
665
  // create a short color hexlet if there is any need for it
@@ -681,9 +683,6 @@ namespace Sass {
681
683
  if (name != "") {
682
684
  ss << name;
683
685
  }
684
- else if (r == 0 && g == 0 && b == 0 && a == 0) {
685
- ss << "transparent";
686
- }
687
686
  else if (a >= 1) {
688
687
  if (res_name != "") {
689
688
  if (compressed && hexlet.str().size() < res_name.size()) {
@@ -711,13 +710,19 @@ namespace Sass {
711
710
 
712
711
  }
713
712
 
714
- void Inspect::operator()(Boolean_Ptr b)
713
+ void Inspect::operator()(Color_HSLA* c)
714
+ {
715
+ Color_RGBA_Obj rgba = c->toRGBA();
716
+ operator()(rgba);
717
+ }
718
+
719
+ void Inspect::operator()(Boolean* b)
715
720
  {
716
721
  // output the final token
717
722
  append_token(b->value() ? "true" : "false", b);
718
723
  }
719
724
 
720
- void Inspect::operator()(String_Schema_Ptr ss)
725
+ void Inspect::operator()(String_Schema* ss)
721
726
  {
722
727
  // Evaluation should turn these into String_Constants,
723
728
  // so this method is only for inspection purposes.
@@ -728,12 +733,12 @@ namespace Sass {
728
733
  }
729
734
  }
730
735
 
731
- void Inspect::operator()(String_Constant_Ptr s)
736
+ void Inspect::operator()(String_Constant* s)
732
737
  {
733
738
  append_token(s->value(), s);
734
739
  }
735
740
 
736
- void Inspect::operator()(String_Quoted_Ptr s)
741
+ void Inspect::operator()(String_Quoted* s)
737
742
  {
738
743
  if (const char q = s->quote_mark()) {
739
744
  append_token(quote(s->value(), q), s);
@@ -742,28 +747,28 @@ namespace Sass {
742
747
  }
743
748
  }
744
749
 
745
- void Inspect::operator()(Custom_Error_Ptr e)
750
+ void Inspect::operator()(Custom_Error* e)
746
751
  {
747
752
  append_token(e->message(), e);
748
753
  }
749
754
 
750
- void Inspect::operator()(Custom_Warning_Ptr w)
755
+ void Inspect::operator()(Custom_Warning* w)
751
756
  {
752
757
  append_token(w->message(), w);
753
758
  }
754
759
 
755
- void Inspect::operator()(Supports_Operator_Ptr so)
760
+ void Inspect::operator()(SupportsOperation* so)
756
761
  {
757
762
 
758
763
  if (so->needs_parens(so->left())) append_string("(");
759
764
  so->left()->perform(this);
760
765
  if (so->needs_parens(so->left())) append_string(")");
761
766
 
762
- if (so->operand() == Supports_Operator::AND) {
767
+ if (so->operand() == SupportsOperation::AND) {
763
768
  append_mandatory_space();
764
769
  append_token("and", so);
765
770
  append_mandatory_space();
766
- } else if (so->operand() == Supports_Operator::OR) {
771
+ } else if (so->operand() == SupportsOperation::OR) {
767
772
  append_mandatory_space();
768
773
  append_token("or", so);
769
774
  append_mandatory_space();
@@ -774,7 +779,7 @@ namespace Sass {
774
779
  if (so->needs_parens(so->right())) append_string(")");
775
780
  }
776
781
 
777
- void Inspect::operator()(Supports_Negation_Ptr sn)
782
+ void Inspect::operator()(SupportsNegation* sn)
778
783
  {
779
784
  append_token("not", sn);
780
785
  append_mandatory_space();
@@ -783,7 +788,7 @@ namespace Sass {
783
788
  if (sn->needs_parens(sn->condition())) append_string(")");
784
789
  }
785
790
 
786
- void Inspect::operator()(Supports_Declaration_Ptr sd)
791
+ void Inspect::operator()(SupportsDeclaration* sd)
787
792
  {
788
793
  append_string("(");
789
794
  sd->feature()->perform(this);
@@ -792,12 +797,12 @@ namespace Sass {
792
797
  append_string(")");
793
798
  }
794
799
 
795
- void Inspect::operator()(Supports_Interpolation_Ptr sd)
800
+ void Inspect::operator()(Supports_Interpolation* sd)
796
801
  {
797
802
  sd->value()->perform(this);
798
803
  }
799
804
 
800
- void Inspect::operator()(Media_Query_Ptr mq)
805
+ void Inspect::operator()(Media_Query* mq)
801
806
  {
802
807
  size_t i = 0;
803
808
  if (mq->media_type()) {
@@ -814,7 +819,7 @@ namespace Sass {
814
819
  }
815
820
  }
816
821
 
817
- void Inspect::operator()(Media_Query_Expression_Ptr mqe)
822
+ void Inspect::operator()(Media_Query_Expression* mqe)
818
823
  {
819
824
  if (mqe->is_interpolated()) {
820
825
  mqe->feature()->perform(this);
@@ -830,7 +835,7 @@ namespace Sass {
830
835
  }
831
836
  }
832
837
 
833
- void Inspect::operator()(At_Root_Query_Ptr ae)
838
+ void Inspect::operator()(At_Root_Query* ae)
834
839
  {
835
840
  if (ae->feature()) {
836
841
  append_string("(");
@@ -843,7 +848,7 @@ namespace Sass {
843
848
  }
844
849
  }
845
850
 
846
- void Inspect::operator()(Function_Ptr f)
851
+ void Inspect::operator()(Function* f)
847
852
  {
848
853
  append_token("get-function", f);
849
854
  append_string("(");
@@ -851,14 +856,14 @@ namespace Sass {
851
856
  append_string(")");
852
857
  }
853
858
 
854
- void Inspect::operator()(Null_Ptr n)
859
+ void Inspect::operator()(Null* n)
855
860
  {
856
861
  // output the final token
857
862
  append_token("null", n);
858
863
  }
859
864
 
860
865
  // parameters and arguments
861
- void Inspect::operator()(Parameter_Ptr p)
866
+ void Inspect::operator()(Parameter* p)
862
867
  {
863
868
  append_token(p->name(), p);
864
869
  if (p->default_value()) {
@@ -870,7 +875,7 @@ namespace Sass {
870
875
  }
871
876
  }
872
877
 
873
- void Inspect::operator()(Parameters_Ptr p)
878
+ void Inspect::operator()(Parameters* p)
874
879
  {
875
880
  append_string("(");
876
881
  if (!p->empty()) {
@@ -883,7 +888,7 @@ namespace Sass {
883
888
  append_string(")");
884
889
  }
885
890
 
886
- void Inspect::operator()(Argument_Ptr a)
891
+ void Inspect::operator()(Argument* a)
887
892
  {
888
893
  if (!a->name().empty()) {
889
894
  append_token(a->name(), a);
@@ -895,7 +900,7 @@ namespace Sass {
895
900
  return;
896
901
  }
897
902
  if (a->value()->concrete_type() == Expression::STRING) {
898
- String_Constant_Ptr s = Cast<String_Constant>(a->value());
903
+ String_Constant* s = Cast<String_Constant>(a->value());
899
904
  if (s) s->perform(this);
900
905
  } else {
901
906
  a->value()->perform(this);
@@ -905,7 +910,7 @@ namespace Sass {
905
910
  }
906
911
  }
907
912
 
908
- void Inspect::operator()(Arguments_Ptr a)
913
+ void Inspect::operator()(Arguments* a)
909
914
  {
910
915
  append_string("(");
911
916
  if (!a->empty()) {
@@ -919,46 +924,38 @@ namespace Sass {
919
924
  append_string(")");
920
925
  }
921
926
 
922
- void Inspect::operator()(Selector_Schema_Ptr s)
927
+ void Inspect::operator()(Selector_Schema* s)
923
928
  {
924
- opt.in_selector = true;
925
929
  s->contents()->perform(this);
926
- opt.in_selector = false;
927
930
  }
928
931
 
929
- void Inspect::operator()(Parent_Selector_Ptr p)
932
+ void Inspect::operator()(Parent_Reference* p)
930
933
  {
931
- if (p->is_real_parent_ref()) append_string("&");
934
+ append_string("&");
932
935
  }
933
936
 
934
- void Inspect::operator()(Placeholder_Selector_Ptr s)
937
+ void Inspect::operator()(PlaceholderSelector* s)
935
938
  {
936
939
  append_token(s->name(), s);
937
- if (s->has_line_break()) append_optional_linefeed();
938
- if (s->has_line_break()) append_indentation();
939
940
 
940
941
  }
941
942
 
942
- void Inspect::operator()(Element_Selector_Ptr s)
943
+ void Inspect::operator()(TypeSelector* s)
943
944
  {
944
945
  append_token(s->ns_name(), s);
945
946
  }
946
947
 
947
- void Inspect::operator()(Class_Selector_Ptr s)
948
+ void Inspect::operator()(ClassSelector* s)
948
949
  {
949
950
  append_token(s->ns_name(), s);
950
- if (s->has_line_break()) append_optional_linefeed();
951
- if (s->has_line_break()) append_indentation();
952
951
  }
953
952
 
954
- void Inspect::operator()(Id_Selector_Ptr s)
953
+ void Inspect::operator()(IDSelector* s)
955
954
  {
956
955
  append_token(s->ns_name(), s);
957
- if (s->has_line_break()) append_optional_linefeed();
958
- if (s->has_line_break()) append_indentation();
959
956
  }
960
957
 
961
- void Inspect::operator()(Attribute_Selector_Ptr s)
958
+ void Inspect::operator()(AttributeSelector* s)
962
959
  {
963
960
  append_string("[");
964
961
  add_open_mapping(s);
@@ -977,111 +974,38 @@ namespace Sass {
977
974
  append_string("]");
978
975
  }
979
976
 
980
- void Inspect::operator()(Pseudo_Selector_Ptr s)
977
+ void Inspect::operator()(PseudoSelector* s)
981
978
  {
982
- append_token(s->ns_name(), s);
983
- if (s->expression()) {
984
- append_string("(");
985
- s->expression()->perform(this);
986
- append_string(")");
987
- }
988
- }
989
979
 
990
- void Inspect::operator()(Wrapped_Selector_Ptr s)
991
- {
992
- if (s->name() == " ") {
993
- append_string("");
994
- } else {
995
- bool was = in_wrapped;
996
- in_wrapped = true;
997
- append_token(s->name(), s);
998
- append_string("(");
999
- bool was_comma_array = in_comma_array;
1000
- in_comma_array = false;
1001
- s->selector()->perform(this);
1002
- in_comma_array = was_comma_array;
1003
- append_string(")");
1004
- in_wrapped = was;
1005
- }
1006
- }
1007
-
1008
- void Inspect::operator()(Compound_Selector_Ptr s)
1009
- {
1010
- for (size_t i = 0, L = s->length(); i < L; ++i) {
1011
- (*s)[i]->perform(this);
1012
- }
1013
- if (s->has_line_break()) {
1014
- if (output_style() != COMPACT) {
1015
- append_optional_linefeed();
1016
- }
1017
- }
1018
- }
1019
-
1020
- void Inspect::operator()(Complex_Selector_Ptr c)
1021
- {
1022
- Compound_Selector_Obj head = c->head();
1023
- Complex_Selector_Obj tail = c->tail();
1024
- Complex_Selector::Combinator comb = c->combinator();
1025
-
1026
- if (comb == Complex_Selector::ANCESTOR_OF && (!head || head->empty())) {
1027
- if (tail) tail->perform(this);
1028
- return;
1029
- }
1030
-
1031
- if (c->has_line_feed()) {
1032
- if (!(c->has_parent_ref())) {
1033
- append_optional_linefeed();
1034
- append_indentation();
980
+ if (s->name() != "") {
981
+ append_string(":");
982
+ if (s->isSyntacticElement()) {
983
+ append_string(":");
1035
984
  }
1036
- }
1037
-
1038
- if (head && head->length() != 0) head->perform(this);
1039
- bool is_empty = !head || head->length() == 0 || head->is_empty_reference();
1040
- bool is_tail = head && !head->is_empty_reference() && tail;
1041
- if (output_style() == COMPRESSED && comb != Complex_Selector::ANCESTOR_OF) scheduled_space = 0;
1042
-
1043
- switch (comb) {
1044
- case Complex_Selector::ANCESTOR_OF:
1045
- if (is_tail) append_mandatory_space();
1046
- break;
1047
- case Complex_Selector::PARENT_OF:
1048
- append_optional_space();
1049
- append_string(">");
1050
- append_optional_space();
1051
- break;
1052
- case Complex_Selector::ADJACENT_TO:
1053
- append_optional_space();
1054
- append_string("+");
1055
- append_optional_space();
1056
- break;
1057
- case Complex_Selector::REFERENCE:
1058
- append_mandatory_space();
1059
- append_string("/");
1060
- c->reference()->perform(this);
1061
- append_string("/");
1062
- append_mandatory_space();
1063
- break;
1064
- case Complex_Selector::PRECEDES:
1065
- if (is_empty) append_optional_space();
1066
- else append_mandatory_space();
1067
- append_string("~");
1068
- if (tail) append_mandatory_space();
1069
- else append_optional_space();
1070
- break;
1071
- default: break;
1072
- }
1073
- if (tail && comb != Complex_Selector::ANCESTOR_OF) {
1074
- if (c->has_line_break()) append_optional_linefeed();
1075
- }
1076
- if (tail) tail->perform(this);
1077
- if (!tail && c->has_line_break()) {
1078
- if (output_style() == COMPACT) {
1079
- append_mandatory_space();
985
+ append_token(s->ns_name(), s);
986
+ if (s->selector() || s->argument()) {
987
+ bool was = in_wrapped;
988
+ in_wrapped = true;
989
+ append_string("(");
990
+ if (s->argument()) {
991
+ s->argument()->perform(this);
992
+ }
993
+ if (s->selector() && s->argument()) {
994
+ append_mandatory_space();
995
+ }
996
+ bool was_comma_array = in_comma_array;
997
+ in_comma_array = false;
998
+ if (s->selector()) {
999
+ s->selector()->perform(this);
1000
+ }
1001
+ in_comma_array = was_comma_array;
1002
+ append_string(")");
1003
+ in_wrapped = was;
1080
1004
  }
1081
1005
  }
1082
1006
  }
1083
1007
 
1084
- void Inspect::operator()(Selector_List_Ptr g)
1008
+ void Inspect::operator()(SelectorList* g)
1085
1009
  {
1086
1010
 
1087
1011
  if (g->empty()) {
@@ -1096,7 +1020,7 @@ namespace Sass {
1096
1020
  // probably ruby sass eqivalent of element_needs_parens
1097
1021
  if (output_style() == TO_SASS && g->length() == 1 &&
1098
1022
  (!Cast<List>((*g)[0]) &&
1099
- !Cast<Selector_List>((*g)[0]))) {
1023
+ !Cast<SelectorList>((*g)[0]))) {
1100
1024
  append_string("(");
1101
1025
  }
1102
1026
  else if (!in_declaration && in_comma_array) {
@@ -1106,8 +1030,10 @@ namespace Sass {
1106
1030
  if (in_declaration) in_comma_array = true;
1107
1031
 
1108
1032
  for (size_t i = 0, L = g->length(); i < L; ++i) {
1033
+
1109
1034
  if (!in_wrapped && i == 0) append_indentation();
1110
- if ((*g)[i] == 0) continue;
1035
+ if ((*g)[i] == nullptr) continue;
1036
+ if (g->at(i)->length() == 0) continue;
1111
1037
  schedule_mapping(g->at(i)->last());
1112
1038
  // add_open_mapping((*g)[i]->last());
1113
1039
  (*g)[i]->perform(this);
@@ -1122,7 +1048,7 @@ namespace Sass {
1122
1048
  // probably ruby sass eqivalent of element_needs_parens
1123
1049
  if (output_style() == TO_SASS && g->length() == 1 &&
1124
1050
  (!Cast<List>((*g)[0]) &&
1125
- !Cast<Selector_List>((*g)[0]))) {
1051
+ !Cast<SelectorList>((*g)[0]))) {
1126
1052
  append_string(",)");
1127
1053
  }
1128
1054
  else if (!in_declaration && in_comma_array) {
@@ -1130,9 +1056,70 @@ namespace Sass {
1130
1056
  }
1131
1057
 
1132
1058
  }
1059
+ void Inspect::operator()(ComplexSelector* sel)
1060
+ {
1061
+ if (sel->hasPreLineFeed()) {
1062
+ append_optional_linefeed();
1063
+ if (!in_wrapped && output_style() == NESTED) {
1064
+ append_indentation();
1065
+ }
1066
+ }
1067
+ const SelectorComponent* prev = nullptr;
1068
+ for (auto& item : sel->elements()) {
1069
+ if (prev != nullptr) {
1070
+ if (item->getCombinator() || prev->getCombinator()) {
1071
+ append_optional_space();
1072
+ } else {
1073
+ append_mandatory_space();
1074
+ }
1075
+ }
1076
+ item->perform(this);
1077
+ prev = item.ptr();
1078
+ }
1079
+ }
1133
1080
 
1134
- void Inspect::fallback_impl(AST_Node_Ptr n)
1081
+ void Inspect::operator()(SelectorComponent* sel)
1135
1082
  {
1083
+ // You should probably never call this method directly
1084
+ // But in case anyone does, we will do the upcasting
1085
+ if (auto comp = Cast<CompoundSelector>(sel)) operator()(comp);
1086
+ if (auto comb = Cast<SelectorCombinator>(sel)) operator()(comb);
1087
+ }
1088
+
1089
+ void Inspect::operator()(CompoundSelector* sel)
1090
+ {
1091
+ if (sel->hasRealParent()) {
1092
+ append_string("&");
1093
+ }
1094
+ sel->sortChildren();
1095
+ for (auto& item : sel->elements()) {
1096
+ item->perform(this);
1097
+ }
1098
+ // Add the post line break (from ruby sass)
1099
+ // Dart sass uses another logic for newlines
1100
+ if (sel->hasPostLineBreak()) {
1101
+ if (output_style() != COMPACT) {
1102
+ append_optional_linefeed();
1103
+ }
1104
+ }
1105
+ }
1106
+
1107
+ void Inspect::operator()(SelectorCombinator* sel)
1108
+ {
1109
+ append_optional_space();
1110
+ switch (sel->combinator()) {
1111
+ case SelectorCombinator::Combinator::CHILD: append_string(">"); break;
1112
+ case SelectorCombinator::Combinator::GENERAL: append_string("~"); break;
1113
+ case SelectorCombinator::Combinator::ADJACENT: append_string("+"); break;
1114
+ }
1115
+ append_optional_space();
1116
+ // Add the post line break (from ruby sass)
1117
+ // Dart sass uses another logic for newlines
1118
+ if (sel->hasPostLineBreak()) {
1119
+ if (output_style() != COMPACT) {
1120
+ // append_optional_linefeed();
1121
+ }
1122
+ }
1136
1123
  }
1137
1124
 
1138
1125
  }