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.
Files changed (216) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +16 -0
  5. data/CHANGELOG.md +97 -0
  6. data/CODE_OF_CONDUCT.md +10 -0
  7. data/Gemfile +2 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +80 -0
  10. data/Rakefile +51 -0
  11. data/ext/depend +4 -0
  12. data/ext/extconf.rb +92 -0
  13. data/ext/libsass/VERSION +1 -0
  14. data/ext/libsass/contrib/plugin.cpp +60 -0
  15. data/ext/libsass/include/sass/base.h +97 -0
  16. data/ext/libsass/include/sass/context.h +174 -0
  17. data/ext/libsass/include/sass/functions.h +139 -0
  18. data/ext/libsass/include/sass/values.h +145 -0
  19. data/ext/libsass/include/sass/version.h +12 -0
  20. data/ext/libsass/include/sass.h +15 -0
  21. data/ext/libsass/include/sass2scss.h +120 -0
  22. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  23. data/ext/libsass/src/ast.cpp +953 -0
  24. data/ext/libsass/src/ast.hpp +1064 -0
  25. data/ext/libsass/src/ast2c.cpp +80 -0
  26. data/ext/libsass/src/ast2c.hpp +39 -0
  27. data/ext/libsass/src/ast_def_macros.hpp +140 -0
  28. data/ext/libsass/src/ast_fwd_decl.cpp +31 -0
  29. data/ext/libsass/src/ast_fwd_decl.hpp +274 -0
  30. data/ext/libsass/src/ast_helpers.hpp +316 -0
  31. data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
  32. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  33. data/ext/libsass/src/ast_sel_unify.cpp +275 -0
  34. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  35. data/ext/libsass/src/ast_selectors.cpp +1070 -0
  36. data/ext/libsass/src/ast_selectors.hpp +523 -0
  37. data/ext/libsass/src/ast_supports.cpp +114 -0
  38. data/ext/libsass/src/ast_supports.hpp +121 -0
  39. data/ext/libsass/src/ast_values.cpp +1154 -0
  40. data/ext/libsass/src/ast_values.hpp +498 -0
  41. data/ext/libsass/src/b64/cencode.h +32 -0
  42. data/ext/libsass/src/b64/encode.h +79 -0
  43. data/ext/libsass/src/backtrace.cpp +50 -0
  44. data/ext/libsass/src/backtrace.hpp +29 -0
  45. data/ext/libsass/src/base64vlq.cpp +47 -0
  46. data/ext/libsass/src/base64vlq.hpp +30 -0
  47. data/ext/libsass/src/bind.cpp +312 -0
  48. data/ext/libsass/src/bind.hpp +15 -0
  49. data/ext/libsass/src/c2ast.cpp +64 -0
  50. data/ext/libsass/src/c2ast.hpp +14 -0
  51. data/ext/libsass/src/c99func.c +54 -0
  52. data/ext/libsass/src/cencode.c +106 -0
  53. data/ext/libsass/src/check_nesting.cpp +393 -0
  54. data/ext/libsass/src/check_nesting.hpp +70 -0
  55. data/ext/libsass/src/color_maps.cpp +652 -0
  56. data/ext/libsass/src/color_maps.hpp +323 -0
  57. data/ext/libsass/src/color_spaces.cpp +241 -0
  58. data/ext/libsass/src/color_spaces.hpp +227 -0
  59. data/ext/libsass/src/constants.cpp +199 -0
  60. data/ext/libsass/src/constants.hpp +200 -0
  61. data/ext/libsass/src/context.cpp +870 -0
  62. data/ext/libsass/src/context.hpp +140 -0
  63. data/ext/libsass/src/cssize.cpp +521 -0
  64. data/ext/libsass/src/cssize.hpp +71 -0
  65. data/ext/libsass/src/dart_helpers.hpp +199 -0
  66. data/ext/libsass/src/debug.hpp +43 -0
  67. data/ext/libsass/src/debugger.hpp +964 -0
  68. data/ext/libsass/src/emitter.cpp +297 -0
  69. data/ext/libsass/src/emitter.hpp +101 -0
  70. data/ext/libsass/src/environment.cpp +260 -0
  71. data/ext/libsass/src/environment.hpp +124 -0
  72. data/ext/libsass/src/error_handling.cpp +239 -0
  73. data/ext/libsass/src/error_handling.hpp +248 -0
  74. data/ext/libsass/src/eval.cpp +1543 -0
  75. data/ext/libsass/src/eval.hpp +110 -0
  76. data/ext/libsass/src/eval_selectors.cpp +75 -0
  77. data/ext/libsass/src/expand.cpp +875 -0
  78. data/ext/libsass/src/expand.hpp +98 -0
  79. data/ext/libsass/src/extender.cpp +1226 -0
  80. data/ext/libsass/src/extender.hpp +399 -0
  81. data/ext/libsass/src/extension.cpp +43 -0
  82. data/ext/libsass/src/extension.hpp +89 -0
  83. data/ext/libsass/src/file.cpp +531 -0
  84. data/ext/libsass/src/file.hpp +124 -0
  85. data/ext/libsass/src/fn_colors.cpp +836 -0
  86. data/ext/libsass/src/fn_colors.hpp +99 -0
  87. data/ext/libsass/src/fn_lists.cpp +285 -0
  88. data/ext/libsass/src/fn_lists.hpp +34 -0
  89. data/ext/libsass/src/fn_maps.cpp +94 -0
  90. data/ext/libsass/src/fn_maps.hpp +30 -0
  91. data/ext/libsass/src/fn_miscs.cpp +248 -0
  92. data/ext/libsass/src/fn_miscs.hpp +40 -0
  93. data/ext/libsass/src/fn_numbers.cpp +246 -0
  94. data/ext/libsass/src/fn_numbers.hpp +45 -0
  95. data/ext/libsass/src/fn_selectors.cpp +205 -0
  96. data/ext/libsass/src/fn_selectors.hpp +35 -0
  97. data/ext/libsass/src/fn_strings.cpp +268 -0
  98. data/ext/libsass/src/fn_strings.hpp +34 -0
  99. data/ext/libsass/src/fn_utils.cpp +159 -0
  100. data/ext/libsass/src/fn_utils.hpp +62 -0
  101. data/ext/libsass/src/inspect.cpp +1126 -0
  102. data/ext/libsass/src/inspect.hpp +101 -0
  103. data/ext/libsass/src/json.cpp +1436 -0
  104. data/ext/libsass/src/json.hpp +117 -0
  105. data/ext/libsass/src/kwd_arg_macros.hpp +28 -0
  106. data/ext/libsass/src/lexer.cpp +122 -0
  107. data/ext/libsass/src/lexer.hpp +304 -0
  108. data/ext/libsass/src/listize.cpp +70 -0
  109. data/ext/libsass/src/listize.hpp +37 -0
  110. data/ext/libsass/src/mapping.hpp +19 -0
  111. data/ext/libsass/src/memory/allocator.cpp +48 -0
  112. data/ext/libsass/src/memory/allocator.hpp +138 -0
  113. data/ext/libsass/src/memory/config.hpp +20 -0
  114. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  115. data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
  116. data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
  117. data/ext/libsass/src/memory.hpp +12 -0
  118. data/ext/libsass/src/operation.hpp +223 -0
  119. data/ext/libsass/src/operators.cpp +267 -0
  120. data/ext/libsass/src/operators.hpp +30 -0
  121. data/ext/libsass/src/ordered_map.hpp +112 -0
  122. data/ext/libsass/src/output.cpp +320 -0
  123. data/ext/libsass/src/output.hpp +47 -0
  124. data/ext/libsass/src/parser.cpp +3059 -0
  125. data/ext/libsass/src/parser.hpp +395 -0
  126. data/ext/libsass/src/parser_selectors.cpp +189 -0
  127. data/ext/libsass/src/permutate.hpp +164 -0
  128. data/ext/libsass/src/plugins.cpp +188 -0
  129. data/ext/libsass/src/plugins.hpp +57 -0
  130. data/ext/libsass/src/position.cpp +163 -0
  131. data/ext/libsass/src/position.hpp +147 -0
  132. data/ext/libsass/src/prelexer.cpp +1780 -0
  133. data/ext/libsass/src/prelexer.hpp +484 -0
  134. data/ext/libsass/src/remove_placeholders.cpp +86 -0
  135. data/ext/libsass/src/remove_placeholders.hpp +37 -0
  136. data/ext/libsass/src/sass.cpp +156 -0
  137. data/ext/libsass/src/sass.hpp +147 -0
  138. data/ext/libsass/src/sass2scss.cpp +895 -0
  139. data/ext/libsass/src/sass_context.cpp +742 -0
  140. data/ext/libsass/src/sass_context.hpp +129 -0
  141. data/ext/libsass/src/sass_functions.cpp +210 -0
  142. data/ext/libsass/src/sass_functions.hpp +50 -0
  143. data/ext/libsass/src/sass_values.cpp +362 -0
  144. data/ext/libsass/src/sass_values.hpp +82 -0
  145. data/ext/libsass/src/settings.hpp +19 -0
  146. data/ext/libsass/src/source.cpp +69 -0
  147. data/ext/libsass/src/source.hpp +95 -0
  148. data/ext/libsass/src/source_data.hpp +32 -0
  149. data/ext/libsass/src/source_map.cpp +202 -0
  150. data/ext/libsass/src/source_map.hpp +65 -0
  151. data/ext/libsass/src/stylesheet.cpp +22 -0
  152. data/ext/libsass/src/stylesheet.hpp +57 -0
  153. data/ext/libsass/src/to_value.cpp +114 -0
  154. data/ext/libsass/src/to_value.hpp +46 -0
  155. data/ext/libsass/src/units.cpp +507 -0
  156. data/ext/libsass/src/units.hpp +110 -0
  157. data/ext/libsass/src/utf8/checked.h +336 -0
  158. data/ext/libsass/src/utf8/core.h +332 -0
  159. data/ext/libsass/src/utf8/unchecked.h +235 -0
  160. data/ext/libsass/src/utf8.h +34 -0
  161. data/ext/libsass/src/utf8_string.cpp +104 -0
  162. data/ext/libsass/src/utf8_string.hpp +38 -0
  163. data/ext/libsass/src/util.cpp +723 -0
  164. data/ext/libsass/src/util.hpp +105 -0
  165. data/ext/libsass/src/util_string.cpp +125 -0
  166. data/ext/libsass/src/util_string.hpp +73 -0
  167. data/ext/libsass/src/values.cpp +140 -0
  168. data/ext/libsass/src/values.hpp +12 -0
  169. data/lib/sassc/dependency.rb +17 -0
  170. data/lib/sassc/engine.rb +141 -0
  171. data/lib/sassc/error.rb +37 -0
  172. data/lib/sassc/functions_handler.rb +73 -0
  173. data/lib/sassc/import_handler.rb +50 -0
  174. data/lib/sassc/importer.rb +31 -0
  175. data/lib/sassc/native/native_context_api.rb +147 -0
  176. data/lib/sassc/native/native_functions_api.rb +159 -0
  177. data/lib/sassc/native/sass2scss_api.rb +10 -0
  178. data/lib/sassc/native/sass_input_style.rb +13 -0
  179. data/lib/sassc/native/sass_output_style.rb +12 -0
  180. data/lib/sassc/native/sass_value.rb +97 -0
  181. data/lib/sassc/native/string_list.rb +10 -0
  182. data/lib/sassc/native.rb +64 -0
  183. data/lib/sassc/sass_2_scss.rb +9 -0
  184. data/lib/sassc/script/functions.rb +8 -0
  185. data/lib/sassc/script/value/bool.rb +32 -0
  186. data/lib/sassc/script/value/color.rb +95 -0
  187. data/lib/sassc/script/value/list.rb +136 -0
  188. data/lib/sassc/script/value/map.rb +69 -0
  189. data/lib/sassc/script/value/number.rb +389 -0
  190. data/lib/sassc/script/value/string.rb +96 -0
  191. data/lib/sassc/script/value.rb +137 -0
  192. data/lib/sassc/script/value_conversion/base.rb +13 -0
  193. data/lib/sassc/script/value_conversion/bool.rb +13 -0
  194. data/lib/sassc/script/value_conversion/color.rb +18 -0
  195. data/lib/sassc/script/value_conversion/list.rb +25 -0
  196. data/lib/sassc/script/value_conversion/map.rb +21 -0
  197. data/lib/sassc/script/value_conversion/number.rb +13 -0
  198. data/lib/sassc/script/value_conversion/string.rb +17 -0
  199. data/lib/sassc/script/value_conversion.rb +69 -0
  200. data/lib/sassc/script.rb +17 -0
  201. data/lib/sassc/util/normalized_map.rb +117 -0
  202. data/lib/sassc/util.rb +231 -0
  203. data/lib/sassc/version.rb +5 -0
  204. data/lib/sassc.rb +57 -0
  205. data/sassc.gemspec +69 -0
  206. data/test/css_color_level4_test.rb +168 -0
  207. data/test/custom_importer_test.rb +127 -0
  208. data/test/engine_test.rb +314 -0
  209. data/test/error_test.rb +29 -0
  210. data/test/fixtures/paths.scss +10 -0
  211. data/test/functions_test.rb +340 -0
  212. data/test/native_test.rb +213 -0
  213. data/test/output_style_test.rb +107 -0
  214. data/test/sass_2_scss_test.rb +14 -0
  215. data/test/test_helper.rb +45 -0
  216. metadata +396 -0
@@ -0,0 +1,836 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
3
+ #include "sass.hpp"
4
+
5
+ #include <iomanip>
6
+ #include "ast.hpp"
7
+ #include "fn_utils.hpp"
8
+ #include "fn_colors.hpp"
9
+ #include "color_spaces.hpp"
10
+ #include "util.hpp"
11
+ #include "util_string.hpp"
12
+
13
+ namespace Sass {
14
+
15
+ namespace Functions {
16
+
17
+ bool string_argument(AST_Node_Obj obj) {
18
+ String_Constant* s = Cast<String_Constant>(obj);
19
+ if (s == nullptr) return false;
20
+ const sass::string& str = s->value();
21
+ return starts_with(str, "calc(") ||
22
+ starts_with(str, "var(");
23
+ }
24
+
25
+ void hsla_alpha_percent_deprecation(const SourceSpan& pstate, const sass::string val)
26
+ {
27
+
28
+ sass::string msg("Passing a percentage as the alpha value to hsla() will be interpreted");
29
+ sass::string tail("differently in future versions of Sass. For now, use " + val + " instead.");
30
+
31
+ deprecated(msg, tail, false, pstate);
32
+
33
+ }
34
+
35
+ // CSS Colors Level 4: rgb() now supports optional 4th parameter for alpha
36
+ Signature rgb_sig = "rgb($red, $green, $blue, $alpha: 1)";
37
+ BUILT_IN(rgb)
38
+ {
39
+ // Check for string arguments (CSS custom properties, calc, var, etc.)
40
+ bool has_string = string_argument(env["$red"]) ||
41
+ string_argument(env["$green"]) ||
42
+ string_argument(env["$blue"]);
43
+
44
+ bool has_alpha_arg = env.has("$alpha");
45
+ bool alpha_is_string = has_alpha_arg && string_argument(env["$alpha"]);
46
+
47
+ if (has_string || alpha_is_string) {
48
+ // Output CSS syntax
49
+ sass::string result = "rgb("
50
+ + env["$red"]->to_string()
51
+ + (has_string ? ", " : " ")
52
+ + env["$green"]->to_string()
53
+ + (has_string ? ", " : " ")
54
+ + env["$blue"]->to_string();
55
+
56
+ // Add alpha if present and not default 1
57
+ if (has_alpha_arg) {
58
+ Number* alpha_num = Cast<Number>(env["$alpha"]);
59
+ if (alpha_is_string || !alpha_num || alpha_num->value() != 1.0) {
60
+ result += (has_string ? ", " : " / ") + env["$alpha"]->to_string();
61
+ }
62
+ }
63
+ result += ")";
64
+
65
+ return SASS_MEMORY_NEW(String_Constant, pstate, result);
66
+ }
67
+
68
+ // Numeric values
69
+ double alpha = has_alpha_arg ? ALPHA_NUM("$alpha") : 1.0;
70
+ return SASS_MEMORY_NEW(Color_RGBA,
71
+ pstate,
72
+ COLOR_NUM("$red"),
73
+ COLOR_NUM("$green"),
74
+ COLOR_NUM("$blue"),
75
+ alpha);
76
+ }
77
+
78
+ Signature rgba_4_sig = "rgba($red, $green, $blue, $alpha)";
79
+ BUILT_IN(rgba_4)
80
+ {
81
+ if (
82
+ string_argument(env["$red"]) ||
83
+ string_argument(env["$green"]) ||
84
+ string_argument(env["$blue"]) ||
85
+ string_argument(env["$alpha"])
86
+ ) {
87
+ return SASS_MEMORY_NEW(String_Constant, pstate, "rgba("
88
+ + env["$red"]->to_string()
89
+ + ", "
90
+ + env["$green"]->to_string()
91
+ + ", "
92
+ + env["$blue"]->to_string()
93
+ + ", "
94
+ + env["$alpha"]->to_string()
95
+ + ")"
96
+ );
97
+ }
98
+
99
+ return SASS_MEMORY_NEW(Color_RGBA,
100
+ pstate,
101
+ COLOR_NUM("$red"),
102
+ COLOR_NUM("$green"),
103
+ COLOR_NUM("$blue"),
104
+ ALPHA_NUM("$alpha"));
105
+ }
106
+
107
+ Signature rgba_2_sig = "rgba($color, $alpha)";
108
+ BUILT_IN(rgba_2)
109
+ {
110
+ if (
111
+ string_argument(env["$color"])
112
+ ) {
113
+ return SASS_MEMORY_NEW(String_Constant, pstate, "rgba("
114
+ + env["$color"]->to_string()
115
+ + ", "
116
+ + env["$alpha"]->to_string()
117
+ + ")"
118
+ );
119
+ }
120
+
121
+ Color_RGBA_Obj c_arg = ARG("$color", Color)->toRGBA();
122
+
123
+ if (
124
+ string_argument(env["$alpha"])
125
+ ) {
126
+ sass::ostream strm;
127
+ strm << "rgba("
128
+ << (int)c_arg->r() << ", "
129
+ << (int)c_arg->g() << ", "
130
+ << (int)c_arg->b() << ", "
131
+ << env["$alpha"]->to_string()
132
+ << ")";
133
+ return SASS_MEMORY_NEW(String_Constant, pstate, strm.str());
134
+ }
135
+
136
+ Color_RGBA_Obj new_c = SASS_MEMORY_COPY(c_arg);
137
+ new_c->a(ALPHA_NUM("$alpha"));
138
+ new_c->disp("");
139
+ return new_c.detach();
140
+ }
141
+
142
+ ////////////////
143
+ // RGB FUNCTIONS
144
+ ////////////////
145
+
146
+ Signature red_sig = "red($color)";
147
+ BUILT_IN(red)
148
+ {
149
+ Color_RGBA_Obj color = ARG("$color", Color)->toRGBA();
150
+ return SASS_MEMORY_NEW(Number, pstate, color->r());
151
+ }
152
+
153
+ Signature green_sig = "green($color)";
154
+ BUILT_IN(green)
155
+ {
156
+ Color_RGBA_Obj color = ARG("$color", Color)->toRGBA();
157
+ return SASS_MEMORY_NEW(Number, pstate, color->g());
158
+ }
159
+
160
+ Signature blue_sig = "blue($color)";
161
+ BUILT_IN(blue)
162
+ {
163
+ Color_RGBA_Obj color = ARG("$color", Color)->toRGBA();
164
+ return SASS_MEMORY_NEW(Number, pstate, color->b());
165
+ }
166
+
167
+ Color_RGBA* colormix(Context& ctx, SourceSpan& pstate, Color* color1, Color* color2, double weight) {
168
+ Color_RGBA_Obj c1 = color1->toRGBA();
169
+ Color_RGBA_Obj c2 = color2->toRGBA();
170
+ double p = weight/100;
171
+ double w = 2*p - 1;
172
+ double a = c1->a() - c2->a();
173
+
174
+ double w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0;
175
+ double w2 = 1 - w1;
176
+
177
+ return SASS_MEMORY_NEW(Color_RGBA,
178
+ pstate,
179
+ Sass::round(w1*c1->r() + w2*c2->r(), ctx.c_options.precision),
180
+ Sass::round(w1*c1->g() + w2*c2->g(), ctx.c_options.precision),
181
+ Sass::round(w1*c1->b() + w2*c2->b(), ctx.c_options.precision),
182
+ c1->a()*p + c2->a()*(1-p));
183
+ }
184
+
185
+ Signature mix_sig = "mix($color1, $color2, $weight: 50%)";
186
+ BUILT_IN(mix)
187
+ {
188
+ Color_Obj color1 = ARG("$color1", Color);
189
+ Color_Obj color2 = ARG("$color2", Color);
190
+ double weight = DARG_U_PRCT("$weight");
191
+ return colormix(ctx, pstate, color1, color2, weight);
192
+
193
+ }
194
+
195
+ ////////////////
196
+ // HSL FUNCTIONS
197
+ ////////////////
198
+
199
+ // CSS Colors Level 4: hsl() now supports optional 4th parameter for alpha
200
+ Signature hsl_sig = "hsl($hue, $saturation, $lightness, $alpha: 1)";
201
+ BUILT_IN(hsl)
202
+ {
203
+ // Check for string arguments (CSS custom properties, calc, var, etc.)
204
+ bool has_string = string_argument(env["$hue"]) ||
205
+ string_argument(env["$saturation"]) ||
206
+ string_argument(env["$lightness"]);
207
+
208
+ bool has_alpha_arg = env.has("$alpha");
209
+ bool alpha_is_string = has_alpha_arg && string_argument(env["$alpha"]);
210
+
211
+ if (has_string || alpha_is_string) {
212
+ // Output CSS syntax
213
+ sass::string result = "hsl("
214
+ + env["$hue"]->to_string()
215
+ + (has_string ? ", " : " ")
216
+ + env["$saturation"]->to_string()
217
+ + (has_string ? ", " : " ")
218
+ + env["$lightness"]->to_string();
219
+
220
+ // Add alpha if present and not default 1
221
+ if (has_alpha_arg) {
222
+ Number* alpha_num = Cast<Number>(env["$alpha"]);
223
+ if (alpha_is_string || !alpha_num || alpha_num->value() != 1.0) {
224
+ result += (has_string ? ", " : " / ") + env["$alpha"]->to_string();
225
+ }
226
+ }
227
+ result += ")";
228
+
229
+ return SASS_MEMORY_NEW(String_Constant, pstate, result);
230
+ }
231
+
232
+ // Numeric values
233
+ double alpha = has_alpha_arg ? ALPHA_NUM("$alpha") : 1.0;
234
+ return SASS_MEMORY_NEW(Color_HSLA,
235
+ pstate,
236
+ ARGVAL("$hue"),
237
+ ARGVAL("$saturation"),
238
+ ARGVAL("$lightness"),
239
+ alpha);
240
+ }
241
+
242
+ Signature hsla_sig = "hsla($hue, $saturation, $lightness, $alpha)";
243
+ BUILT_IN(hsla)
244
+ {
245
+ if (
246
+ string_argument(env["$hue"]) ||
247
+ string_argument(env["$saturation"]) ||
248
+ string_argument(env["$lightness"]) ||
249
+ string_argument(env["$alpha"])
250
+ ) {
251
+ return SASS_MEMORY_NEW(String_Constant, pstate, "hsla("
252
+ + env["$hue"]->to_string()
253
+ + ", "
254
+ + env["$saturation"]->to_string()
255
+ + ", "
256
+ + env["$lightness"]->to_string()
257
+ + ", "
258
+ + env["$alpha"]->to_string()
259
+ + ")"
260
+ );
261
+ }
262
+
263
+ Number* alpha = ARG("$alpha", Number);
264
+ if (alpha && alpha->unit() == "%") {
265
+ Number_Obj val = SASS_MEMORY_COPY(alpha);
266
+ val->numerators.clear(); // convert
267
+ val->value(val->value() / 100.0);
268
+ sass::string nr(val->to_string(ctx.c_options));
269
+ hsla_alpha_percent_deprecation(pstate, nr);
270
+ }
271
+
272
+ return SASS_MEMORY_NEW(Color_HSLA,
273
+ pstate,
274
+ ARGVAL("$hue"),
275
+ ARGVAL("$saturation"),
276
+ ARGVAL("$lightness"),
277
+ ARGVAL("$alpha"));
278
+
279
+ }
280
+
281
+ /////////////////////////////////////////////////////////////////////////
282
+ // Query functions
283
+ /////////////////////////////////////////////////////////////////////////
284
+
285
+ Signature hue_sig = "hue($color)";
286
+ BUILT_IN(hue)
287
+ {
288
+ Color_HSLA_Obj col = ARG("$color", Color)->toHSLA();
289
+ return SASS_MEMORY_NEW(Number, pstate, col->h(), "deg");
290
+ }
291
+
292
+ Signature saturation_sig = "saturation($color)";
293
+ BUILT_IN(saturation)
294
+ {
295
+ Color_HSLA_Obj col = ARG("$color", Color)->toHSLA();
296
+ return SASS_MEMORY_NEW(Number, pstate, col->s(), "%");
297
+ }
298
+
299
+ Signature lightness_sig = "lightness($color)";
300
+ BUILT_IN(lightness)
301
+ {
302
+ Color_HSLA_Obj col = ARG("$color", Color)->toHSLA();
303
+ return SASS_MEMORY_NEW(Number, pstate, col->l(), "%");
304
+ }
305
+
306
+ /////////////////////////////////////////////////////////////////////////
307
+ // HSL manipulation functions
308
+ /////////////////////////////////////////////////////////////////////////
309
+
310
+ Signature adjust_hue_sig = "adjust-hue($color, $degrees)";
311
+ BUILT_IN(adjust_hue)
312
+ {
313
+ Color* col = ARG("$color", Color);
314
+ double degrees = ARGVAL("$degrees");
315
+ Color_HSLA_Obj copy = col->copyAsHSLA();
316
+ copy->h(absmod(copy->h() + degrees, 360.0));
317
+ return copy.detach();
318
+ }
319
+
320
+ Signature lighten_sig = "lighten($color, $amount)";
321
+ BUILT_IN(lighten)
322
+ {
323
+ Color* col = ARG("$color", Color);
324
+ double amount = DARG_U_PRCT("$amount");
325
+ Color_HSLA_Obj copy = col->copyAsHSLA();
326
+ copy->l(clip(copy->l() + amount, 0.0, 100.0));
327
+ return copy.detach();
328
+
329
+ }
330
+
331
+ Signature darken_sig = "darken($color, $amount)";
332
+ BUILT_IN(darken)
333
+ {
334
+ Color* col = ARG("$color", Color);
335
+ double amount = DARG_U_PRCT("$amount");
336
+ Color_HSLA_Obj copy = col->copyAsHSLA();
337
+ copy->l(clip(copy->l() - amount, 0.0, 100.0));
338
+ return copy.detach();
339
+ }
340
+
341
+ Signature saturate_sig = "saturate($color, $amount: false)";
342
+ BUILT_IN(saturate)
343
+ {
344
+ // CSS3 filter function overload: pass literal through directly
345
+ if (!Cast<Number>(env["$amount"])) {
346
+ return SASS_MEMORY_NEW(String_Quoted, pstate, "saturate(" + env["$color"]->to_string(ctx.c_options) + ")");
347
+ }
348
+
349
+ Color* col = ARG("$color", Color);
350
+ double amount = DARG_U_PRCT("$amount");
351
+ Color_HSLA_Obj copy = col->copyAsHSLA();
352
+ copy->s(clip(copy->s() + amount, 0.0, 100.0));
353
+ return copy.detach();
354
+ }
355
+
356
+ Signature desaturate_sig = "desaturate($color, $amount)";
357
+ BUILT_IN(desaturate)
358
+ {
359
+ Color* col = ARG("$color", Color);
360
+ double amount = DARG_U_PRCT("$amount");
361
+ Color_HSLA_Obj copy = col->copyAsHSLA();
362
+ copy->s(clip(copy->s() - amount, 0.0, 100.0));
363
+ return copy.detach();
364
+ }
365
+
366
+ Signature grayscale_sig = "grayscale($color)";
367
+ BUILT_IN(grayscale)
368
+ {
369
+ // CSS3 filter function overload: pass literal through directly
370
+ Number* amount = Cast<Number>(env["$color"]);
371
+ if (amount) {
372
+ return SASS_MEMORY_NEW(String_Quoted, pstate, "grayscale(" + amount->to_string(ctx.c_options) + ")");
373
+ }
374
+
375
+ Color* col = ARG("$color", Color);
376
+ Color_HSLA_Obj copy = col->copyAsHSLA();
377
+ copy->s(0.0); // just reset saturation
378
+ return copy.detach();
379
+ }
380
+
381
+ /////////////////////////////////////////////////////////////////////////
382
+ // Misc manipulation functions
383
+ /////////////////////////////////////////////////////////////////////////
384
+
385
+ Signature complement_sig = "complement($color)";
386
+ BUILT_IN(complement)
387
+ {
388
+ Color* col = ARG("$color", Color);
389
+ Color_HSLA_Obj copy = col->copyAsHSLA();
390
+ copy->h(absmod(copy->h() - 180.0, 360.0));
391
+ return copy.detach();
392
+ }
393
+
394
+ Signature invert_sig = "invert($color, $weight: 100%)";
395
+ BUILT_IN(invert)
396
+ {
397
+ // CSS3 filter function overload: pass literal through directly
398
+ Number* amount = Cast<Number>(env["$color"]);
399
+ double weight = DARG_U_PRCT("$weight");
400
+ if (amount) {
401
+ // TODO: does not throw on 100% manually passed as value
402
+ if (weight < 100.0) {
403
+ error("Only one argument may be passed to the plain-CSS invert() function.", pstate, traces);
404
+ }
405
+ return SASS_MEMORY_NEW(String_Quoted, pstate, "invert(" + amount->to_string(ctx.c_options) + ")");
406
+ }
407
+
408
+ Color* col = ARG("$color", Color);
409
+ Color_RGBA_Obj inv = col->copyAsRGBA();
410
+ inv->r(clip(255.0 - inv->r(), 0.0, 255.0));
411
+ inv->g(clip(255.0 - inv->g(), 0.0, 255.0));
412
+ inv->b(clip(255.0 - inv->b(), 0.0, 255.0));
413
+ return colormix(ctx, pstate, inv, col, weight);
414
+ }
415
+
416
+ /////////////////////////////////////////////////////////////////////////
417
+ // Opacity functions
418
+ /////////////////////////////////////////////////////////////////////////
419
+
420
+ Signature alpha_sig = "alpha($color)";
421
+ Signature opacity_sig = "opacity($color)";
422
+ BUILT_IN(alpha)
423
+ {
424
+ String_Constant* ie_kwd = Cast<String_Constant>(env["$color"]);
425
+ if (ie_kwd) {
426
+ return SASS_MEMORY_NEW(String_Quoted, pstate, "alpha(" + ie_kwd->value() + ")");
427
+ }
428
+
429
+ // CSS3 filter function overload: pass literal through directly
430
+ Number* amount = Cast<Number>(env["$color"]);
431
+ if (amount) {
432
+ return SASS_MEMORY_NEW(String_Quoted, pstate, "opacity(" + amount->to_string(ctx.c_options) + ")");
433
+ }
434
+
435
+ return SASS_MEMORY_NEW(Number, pstate, ARG("$color", Color)->a());
436
+ }
437
+
438
+ Signature opacify_sig = "opacify($color, $amount)";
439
+ Signature fade_in_sig = "fade-in($color, $amount)";
440
+ BUILT_IN(opacify)
441
+ {
442
+ Color* col = ARG("$color", Color);
443
+ double amount = DARG_U_FACT("$amount");
444
+ Color_Obj copy = SASS_MEMORY_COPY(col);
445
+ copy->a(clip(col->a() + amount, 0.0, 1.0));
446
+ return copy.detach();
447
+ }
448
+
449
+ Signature transparentize_sig = "transparentize($color, $amount)";
450
+ Signature fade_out_sig = "fade-out($color, $amount)";
451
+ BUILT_IN(transparentize)
452
+ {
453
+ Color* col = ARG("$color", Color);
454
+ double amount = DARG_U_FACT("$amount");
455
+ Color_Obj copy = SASS_MEMORY_COPY(col);
456
+ copy->a(std::max(col->a() - amount, 0.0));
457
+ return copy.detach();
458
+ }
459
+
460
+ ////////////////////////
461
+ // OTHER COLOR FUNCTIONS
462
+ ////////////////////////
463
+
464
+ Signature adjust_color_sig = "adjust-color($color, $red: false, $green: false, $blue: false, $hue: false, $saturation: false, $lightness: false, $alpha: false)";
465
+ BUILT_IN(adjust_color)
466
+ {
467
+ Color* col = ARG("$color", Color);
468
+ Number* r = Cast<Number>(env["$red"]);
469
+ Number* g = Cast<Number>(env["$green"]);
470
+ Number* b = Cast<Number>(env["$blue"]);
471
+ Number* h = Cast<Number>(env["$hue"]);
472
+ Number* s = Cast<Number>(env["$saturation"]);
473
+ Number* l = Cast<Number>(env["$lightness"]);
474
+ Number* a = Cast<Number>(env["$alpha"]);
475
+
476
+ bool rgb = r || g || b;
477
+ bool hsl = h || s || l;
478
+
479
+ if (rgb && hsl) {
480
+ error("Cannot specify HSL and RGB values for a color at the same time for `adjust-color'", pstate, traces);
481
+ }
482
+ else if (rgb) {
483
+ Color_RGBA_Obj c = col->copyAsRGBA();
484
+ if (r) c->r(c->r() + DARG_R_BYTE("$red"));
485
+ if (g) c->g(c->g() + DARG_R_BYTE("$green"));
486
+ if (b) c->b(c->b() + DARG_R_BYTE("$blue"));
487
+ if (a) c->a(c->a() + DARG_R_FACT("$alpha"));
488
+ return c.detach();
489
+ }
490
+ else if (hsl) {
491
+ Color_HSLA_Obj c = col->copyAsHSLA();
492
+ if (h) c->h(c->h() + absmod(h->value(), 360.0));
493
+ if (s) c->s(c->s() + DARG_R_PRCT("$saturation"));
494
+ if (l) c->l(c->l() + DARG_R_PRCT("$lightness"));
495
+ if (a) c->a(c->a() + DARG_R_FACT("$alpha"));
496
+ return c.detach();
497
+ }
498
+ else if (a) {
499
+ Color_Obj c = SASS_MEMORY_COPY(col);
500
+ c->a(c->a() + DARG_R_FACT("$alpha"));
501
+ c->a(clip(c->a(), 0.0, 1.0));
502
+ return c.detach();
503
+ }
504
+ error("not enough arguments for `adjust-color'", pstate, traces);
505
+ // unreachable
506
+ return col;
507
+ }
508
+
509
+ Signature scale_color_sig = "scale-color($color, $red: false, $green: false, $blue: false, $hue: false, $saturation: false, $lightness: false, $alpha: false)";
510
+ BUILT_IN(scale_color)
511
+ {
512
+ Color* col = ARG("$color", Color);
513
+ Number* r = Cast<Number>(env["$red"]);
514
+ Number* g = Cast<Number>(env["$green"]);
515
+ Number* b = Cast<Number>(env["$blue"]);
516
+ Number* h = Cast<Number>(env["$hue"]);
517
+ Number* s = Cast<Number>(env["$saturation"]);
518
+ Number* l = Cast<Number>(env["$lightness"]);
519
+ Number* a = Cast<Number>(env["$alpha"]);
520
+
521
+ bool rgb = r || g || b;
522
+ bool hsl = h || s || l;
523
+
524
+ if (rgb && hsl) {
525
+ error("Cannot specify HSL and RGB values for a color at the same time for `scale-color'", pstate, traces);
526
+ }
527
+ else if (rgb) {
528
+ Color_RGBA_Obj c = col->copyAsRGBA();
529
+ double rscale = (r ? DARG_R_PRCT("$red") : 0.0) / 100.0;
530
+ double gscale = (g ? DARG_R_PRCT("$green") : 0.0) / 100.0;
531
+ double bscale = (b ? DARG_R_PRCT("$blue") : 0.0) / 100.0;
532
+ double ascale = (a ? DARG_R_PRCT("$alpha") : 0.0) / 100.0;
533
+ if (rscale) c->r(c->r() + rscale * (rscale > 0.0 ? 255.0 - c->r() : c->r()));
534
+ if (gscale) c->g(c->g() + gscale * (gscale > 0.0 ? 255.0 - c->g() : c->g()));
535
+ if (bscale) c->b(c->b() + bscale * (bscale > 0.0 ? 255.0 - c->b() : c->b()));
536
+ if (ascale) c->a(c->a() + ascale * (ascale > 0.0 ? 1.0 - c->a() : c->a()));
537
+ return c.detach();
538
+ }
539
+ else if (hsl) {
540
+ Color_HSLA_Obj c = col->copyAsHSLA();
541
+ double hscale = (h ? DARG_R_PRCT("$hue") : 0.0) / 100.0;
542
+ double sscale = (s ? DARG_R_PRCT("$saturation") : 0.0) / 100.0;
543
+ double lscale = (l ? DARG_R_PRCT("$lightness") : 0.0) / 100.0;
544
+ double ascale = (a ? DARG_R_PRCT("$alpha") : 0.0) / 100.0;
545
+ if (hscale) c->h(c->h() + hscale * (hscale > 0.0 ? 360.0 - c->h() : c->h()));
546
+ if (sscale) c->s(c->s() + sscale * (sscale > 0.0 ? 100.0 - c->s() : c->s()));
547
+ if (lscale) c->l(c->l() + lscale * (lscale > 0.0 ? 100.0 - c->l() : c->l()));
548
+ if (ascale) c->a(c->a() + ascale * (ascale > 0.0 ? 1.0 - c->a() : c->a()));
549
+ return c.detach();
550
+ }
551
+ else if (a) {
552
+ Color_Obj c = SASS_MEMORY_COPY(col);
553
+ double ascale = DARG_R_PRCT("$alpha") / 100.0;
554
+ c->a(c->a() + ascale * (ascale > 0.0 ? 1.0 - c->a() : c->a()));
555
+ c->a(clip(c->a(), 0.0, 1.0));
556
+ return c.detach();
557
+ }
558
+ error("not enough arguments for `scale-color'", pstate, traces);
559
+ // unreachable
560
+ return col;
561
+ }
562
+
563
+ Signature change_color_sig = "change-color($color, $red: false, $green: false, $blue: false, $hue: false, $saturation: false, $lightness: false, $alpha: false)";
564
+ BUILT_IN(change_color)
565
+ {
566
+ Color* col = ARG("$color", Color);
567
+ Number* r = Cast<Number>(env["$red"]);
568
+ Number* g = Cast<Number>(env["$green"]);
569
+ Number* b = Cast<Number>(env["$blue"]);
570
+ Number* h = Cast<Number>(env["$hue"]);
571
+ Number* s = Cast<Number>(env["$saturation"]);
572
+ Number* l = Cast<Number>(env["$lightness"]);
573
+ Number* a = Cast<Number>(env["$alpha"]);
574
+
575
+ bool rgb = r || g || b;
576
+ bool hsl = h || s || l;
577
+
578
+ if (rgb && hsl) {
579
+ error("Cannot specify HSL and RGB values for a color at the same time for `change-color'", pstate, traces);
580
+ }
581
+ else if (rgb) {
582
+ Color_RGBA_Obj c = col->copyAsRGBA();
583
+ if (r) c->r(DARG_U_BYTE("$red"));
584
+ if (g) c->g(DARG_U_BYTE("$green"));
585
+ if (b) c->b(DARG_U_BYTE("$blue"));
586
+ if (a) c->a(DARG_U_FACT("$alpha"));
587
+ return c.detach();
588
+ }
589
+ else if (hsl) {
590
+ Color_HSLA_Obj c = col->copyAsHSLA();
591
+ if (h) c->h(absmod(h->value(), 360.0));
592
+ if (s) c->s(DARG_U_PRCT("$saturation"));
593
+ if (l) c->l(DARG_U_PRCT("$lightness"));
594
+ if (a) c->a(DARG_U_FACT("$alpha"));
595
+ return c.detach();
596
+ }
597
+ else if (a) {
598
+ Color_Obj c = SASS_MEMORY_COPY(col);
599
+ c->a(clip(DARG_U_FACT("$alpha"), 0.0, 1.0));
600
+ return c.detach();
601
+ }
602
+ error("not enough arguments for `change-color'", pstate, traces);
603
+ // unreachable
604
+ return col;
605
+ }
606
+
607
+ Signature ie_hex_str_sig = "ie-hex-str($color)";
608
+ BUILT_IN(ie_hex_str)
609
+ {
610
+ Color* col = ARG("$color", Color);
611
+ Color_RGBA_Obj c = col->toRGBA();
612
+ double r = clip(c->r(), 0.0, 255.0);
613
+ double g = clip(c->g(), 0.0, 255.0);
614
+ double b = clip(c->b(), 0.0, 255.0);
615
+ double a = clip(c->a(), 0.0, 1.0) * 255.0;
616
+
617
+ sass::ostream ss;
618
+ ss << '#' << std::setw(2) << std::setfill('0');
619
+ ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(a, ctx.c_options.precision));
620
+ ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(r, ctx.c_options.precision));
621
+ ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(g, ctx.c_options.precision));
622
+ ss << std::hex << std::setw(2) << static_cast<unsigned long>(Sass::round(b, ctx.c_options.precision));
623
+
624
+ sass::string result = ss.str();
625
+ Util::ascii_str_toupper(&result);
626
+ return SASS_MEMORY_NEW(String_Quoted, pstate, result);
627
+ }
628
+
629
+ /////////////////////////////////////////////////////////////////////////
630
+ // CSS Colors Level 4 functions
631
+ /////////////////////////////////////////////////////////////////////////
632
+
633
+ Signature hwb_sig = "hwb($hue, $whiteness, $blackness, $alpha: 1)";
634
+ BUILT_IN(hwb)
635
+ {
636
+ // Check for string arguments (CSS custom properties, calc, var, etc.)
637
+ if (
638
+ string_argument(env["$hue"]) ||
639
+ string_argument(env["$whiteness"]) ||
640
+ string_argument(env["$blackness"])
641
+ ) {
642
+ sass::string result = "hwb("
643
+ + env["$hue"]->to_string()
644
+ + " "
645
+ + env["$whiteness"]->to_string()
646
+ + " "
647
+ + env["$blackness"]->to_string();
648
+
649
+ if (env.has("$alpha")) {
650
+ result += " / " + env["$alpha"]->to_string();
651
+ }
652
+ result += ")";
653
+
654
+ return SASS_MEMORY_NEW(String_Constant, pstate, result);
655
+ }
656
+
657
+ double hue = ARGVAL("$hue");
658
+ double whiteness = DARG_U_PRCT("$whiteness");
659
+ double blackness = DARG_U_PRCT("$blackness");
660
+ double alpha = env.has("$alpha") ? ALPHA_NUM("$alpha") : 1.0;
661
+
662
+ HWB hwb_color(hue, whiteness, blackness, alpha);
663
+ return hwb_color.toRGBA();
664
+ }
665
+
666
+ Signature lab_sig = "lab($lightness, $a, $b, $alpha: 1)";
667
+ BUILT_IN(lab)
668
+ {
669
+ if (
670
+ string_argument(env["$lightness"]) ||
671
+ string_argument(env["$a"]) ||
672
+ string_argument(env["$b"])
673
+ ) {
674
+ sass::string result = "lab("
675
+ + env["$lightness"]->to_string()
676
+ + " "
677
+ + env["$a"]->to_string()
678
+ + " "
679
+ + env["$b"]->to_string();
680
+
681
+ if (env.has("$alpha")) {
682
+ result += " / " + env["$alpha"]->to_string();
683
+ }
684
+ result += ")";
685
+
686
+ return SASS_MEMORY_NEW(String_Constant, pstate, result);
687
+ }
688
+
689
+ double lightness = DARG_U_PRCT("$lightness");
690
+ double a = ARGVAL("$a");
691
+ double b = ARGVAL("$b");
692
+ double alpha = env.has("$alpha") ? ALPHA_NUM("$alpha") : 1.0;
693
+
694
+ Lab lab_color(lightness, a, b, alpha);
695
+ return lab_color.toRGBA();
696
+ }
697
+
698
+ Signature lch_sig = "lch($lightness, $chroma, $hue, $alpha: 1)";
699
+ BUILT_IN(lch)
700
+ {
701
+ if (
702
+ string_argument(env["$lightness"]) ||
703
+ string_argument(env["$chroma"]) ||
704
+ string_argument(env["$hue"])
705
+ ) {
706
+ sass::string result = "lch("
707
+ + env["$lightness"]->to_string()
708
+ + " "
709
+ + env["$chroma"]->to_string()
710
+ + " "
711
+ + env["$hue"]->to_string();
712
+
713
+ if (env.has("$alpha")) {
714
+ result += " / " + env["$alpha"]->to_string();
715
+ }
716
+ result += ")";
717
+
718
+ return SASS_MEMORY_NEW(String_Constant, pstate, result);
719
+ }
720
+
721
+ double lightness = DARG_U_PRCT("$lightness");
722
+ double chroma = ARGVAL("$chroma");
723
+ double hue = ARGVAL("$hue");
724
+ double alpha = env.has("$alpha") ? ALPHA_NUM("$alpha") : 1.0;
725
+
726
+ LCH lch_color(lightness, chroma, hue, alpha);
727
+ return lch_color.toRGBA();
728
+ }
729
+
730
+ Signature oklab_sig = "oklab($lightness, $a, $b, $alpha: 1)";
731
+ BUILT_IN(oklab)
732
+ {
733
+ if (
734
+ string_argument(env["$lightness"]) ||
735
+ string_argument(env["$a"]) ||
736
+ string_argument(env["$b"])
737
+ ) {
738
+ sass::string result = "oklab("
739
+ + env["$lightness"]->to_string()
740
+ + " "
741
+ + env["$a"]->to_string()
742
+ + " "
743
+ + env["$b"]->to_string();
744
+
745
+ if (env.has("$alpha")) {
746
+ result += " / " + env["$alpha"]->to_string();
747
+ }
748
+ result += ")";
749
+
750
+ return SASS_MEMORY_NEW(String_Constant, pstate, result);
751
+ }
752
+
753
+ // OKLab uses 0-1 range for lightness, not percentage
754
+ double lightness = DARG_U_FACT("$lightness");
755
+ double a = ARGVAL("$a");
756
+ double b = ARGVAL("$b");
757
+ double alpha = env.has("$alpha") ? ALPHA_NUM("$alpha") : 1.0;
758
+
759
+ OKLab oklab_color(lightness, a, b, alpha);
760
+ return oklab_color.toRGBA();
761
+ }
762
+
763
+ Signature oklch_sig = "oklch($lightness, $chroma, $hue, $alpha: 1)";
764
+ BUILT_IN(oklch)
765
+ {
766
+ if (
767
+ string_argument(env["$lightness"]) ||
768
+ string_argument(env["$chroma"]) ||
769
+ string_argument(env["$hue"])
770
+ ) {
771
+ sass::string result = "oklch("
772
+ + env["$lightness"]->to_string()
773
+ + " "
774
+ + env["$chroma"]->to_string()
775
+ + " "
776
+ + env["$hue"]->to_string();
777
+
778
+ if (env.has("$alpha")) {
779
+ result += " / " + env["$alpha"]->to_string();
780
+ }
781
+ result += ")";
782
+
783
+ return SASS_MEMORY_NEW(String_Constant, pstate, result);
784
+ }
785
+
786
+ // OKLCH uses 0-1 range for lightness, not percentage
787
+ double lightness = DARG_U_FACT("$lightness");
788
+ double chroma = ARGVAL("$chroma");
789
+ double hue = ARGVAL("$hue");
790
+ double alpha = env.has("$alpha") ? ALPHA_NUM("$alpha") : 1.0;
791
+
792
+ OKLCH oklch_color(lightness, chroma, hue, alpha);
793
+ return oklch_color.toRGBA();
794
+ }
795
+
796
+ Signature color_sig = "color($space, $channel1, $channel2, $channel3, $alpha: 1)";
797
+ BUILT_IN(color)
798
+ {
799
+ // Get the color space name
800
+ String_Constant* space_str = Cast<String_Constant>(env["$space"]);
801
+ if (!space_str) {
802
+ error("$space: " + env["$space"]->to_string() + " is not a string.", pstate, traces);
803
+ }
804
+
805
+ sass::string space = space_str->value();
806
+
807
+ // For now, support the most common color spaces
808
+ // Full implementation would support: srgb, srgb-linear, display-p3, a98-rgb, prophoto-rgb, rec2020, xyz, xyz-d50, xyz-d65
809
+
810
+ if (space == "srgb" || space == "rgb") {
811
+ // sRGB is the same as legacy RGB
812
+ double r = ARGVAL("$channel1");
813
+ double g = ARGVAL("$channel2");
814
+ double b = ARGVAL("$channel3");
815
+ double alpha = env.has("$alpha") ? ALPHA_NUM("$alpha") : 1.0;
816
+
817
+ return SASS_MEMORY_NEW(Color_RGBA, pstate, r * 255.0, g * 255.0, b * 255.0, alpha);
818
+ }
819
+
820
+ // For other color spaces, output as CSS string for browser support
821
+ sass::string result = "color(" + space + " "
822
+ + env["$channel1"]->to_string() + " "
823
+ + env["$channel2"]->to_string() + " "
824
+ + env["$channel3"]->to_string();
825
+
826
+ if (env.has("$alpha")) {
827
+ result += " / " + env["$alpha"]->to_string();
828
+ }
829
+ result += ")";
830
+
831
+ return SASS_MEMORY_NEW(String_Constant, pstate, result);
832
+ }
833
+
834
+ }
835
+
836
+ }