sassc4 2.4.0 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/libsass/VERSION +1 -1
- data/ext/libsass/src/color_spaces.cpp +51 -51
- data/ext/libsass/src/color_spaces.hpp +36 -36
- data/ext/libsass/src/constants.cpp +7 -0
- data/ext/libsass/src/constants.hpp +7 -0
- data/ext/libsass/src/fn_colors.cpp +98 -27
- data/ext/libsass/src/parser.cpp +63 -1
- data/ext/libsass/src/parser.hpp +1 -0
- data/ext/libsass/src/prelexer.cpp +13 -0
- data/ext/libsass/src/prelexer.hpp +2 -0
- data/lib/sassc/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39063f8c86eb4a6f48ae21e121d6ae96593e336c861dadd2b3c0734d66f8b200
|
4
|
+
data.tar.gz: ee927ad9e16142bcac97d25fbc8b451d57706e30f1990f5837bfe9e356eefd75
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9348e6f46dcb7170a8114ffad46093a0093f84c4f2bc1d4eef4b60640c5b43542b28fef5ce027849e76b88549ac30a2bc86a2ec0d2403abef0abd4033c75119b
|
7
|
+
data.tar.gz: e9e80f3d0e2fd227eb382ee53ced7e2f00acb4b72d2d63575ec39d1eaf89af83fbec7df04834fee2031baf02decef5de9ea81eefd946d231504dacf56c927a1b
|
data/ext/libsass/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.0.
|
1
|
+
4.0.3
|
@@ -13,46 +13,46 @@ namespace Sass {
|
|
13
13
|
// ============================================================================
|
14
14
|
// HWB Conversions
|
15
15
|
// ============================================================================
|
16
|
-
|
16
|
+
|
17
17
|
Color_RGBA* HWB::toRGBA() const {
|
18
18
|
// From https://www.w3.org/TR/css-color-4/#hwb-to-rgb
|
19
19
|
double hue = std::fmod(h, 360.0);
|
20
20
|
if (hue < 0) hue += 360.0;
|
21
21
|
double scaledHue = hue / 360.0;
|
22
|
-
|
22
|
+
|
23
23
|
double white = w / 100.0;
|
24
24
|
double black = b / 100.0;
|
25
|
-
|
25
|
+
|
26
26
|
// Normalize if sum > 1
|
27
27
|
double sum = white + black;
|
28
28
|
if (sum > 1.0) {
|
29
29
|
white /= sum;
|
30
30
|
black /= sum;
|
31
31
|
}
|
32
|
-
|
32
|
+
|
33
33
|
double factor = 1.0 - white - black;
|
34
|
-
|
34
|
+
|
35
35
|
// Convert to RGB using HSL-like formula
|
36
36
|
auto toRgb = [&](double hue) -> double {
|
37
37
|
return ColorSpaces::hueToRgb(0, 1, hue) * factor + white;
|
38
38
|
};
|
39
|
-
|
39
|
+
|
40
40
|
double r = toRgb(scaledHue + 1.0 / 3.0) * 255.0;
|
41
41
|
double g = toRgb(scaledHue) * 255.0;
|
42
42
|
double b = toRgb(scaledHue - 1.0 / 3.0) * 255.0;
|
43
|
-
|
43
|
+
|
44
44
|
return SASS_MEMORY_NEW(Color_RGBA, SourceSpan("[hwb]"), r, g, b, a);
|
45
45
|
}
|
46
|
-
|
46
|
+
|
47
47
|
HWB HWB::fromRGBA(const Color_RGBA* rgb) {
|
48
48
|
double r = rgb->r() / 255.0;
|
49
49
|
double g = rgb->g() / 255.0;
|
50
50
|
double b = rgb->b() / 255.0;
|
51
|
-
|
51
|
+
|
52
52
|
double max = std::max({r, g, b});
|
53
53
|
double min = std::min({r, g, b});
|
54
54
|
double chroma = max - min;
|
55
|
-
|
55
|
+
|
56
56
|
double hue = 0;
|
57
57
|
if (chroma != 0) {
|
58
58
|
if (max == r) {
|
@@ -65,177 +65,177 @@ namespace Sass {
|
|
65
65
|
hue *= 60.0;
|
66
66
|
if (hue < 0) hue += 360.0;
|
67
67
|
}
|
68
|
-
|
68
|
+
|
69
69
|
double whiteness = min * 100.0;
|
70
70
|
double blackness = (1.0 - max) * 100.0;
|
71
|
-
|
71
|
+
|
72
72
|
return HWB(hue, whiteness, blackness, rgb->a());
|
73
73
|
}
|
74
|
-
|
74
|
+
|
75
75
|
// ============================================================================
|
76
76
|
// Lab Conversions
|
77
77
|
// ============================================================================
|
78
|
-
|
78
|
+
|
79
79
|
Color_RGBA* Lab::toRGBA() const {
|
80
80
|
// Lab -> XYZ D50
|
81
81
|
double fy = (l + 16.0) / 116.0;
|
82
82
|
double fx = a / 500.0 + fy;
|
83
83
|
double fz = fy - b / 200.0;
|
84
|
-
|
84
|
+
|
85
85
|
double xr = ColorSpaces::labFinv(fx);
|
86
|
-
double yr = l > ColorSpaces::LAB_KAPPA * ColorSpaces::LAB_EPSILON
|
87
|
-
? std::pow((l + 16.0) / 116.0, 3.0)
|
86
|
+
double yr = l > ColorSpaces::LAB_KAPPA * ColorSpaces::LAB_EPSILON
|
87
|
+
? std::pow((l + 16.0) / 116.0, 3.0)
|
88
88
|
: l / ColorSpaces::LAB_KAPPA;
|
89
89
|
double zr = ColorSpaces::labFinv(fz);
|
90
|
-
|
90
|
+
|
91
91
|
double x = xr * ColorSpaces::D50[0];
|
92
92
|
double y = yr * ColorSpaces::D50[1];
|
93
93
|
double z = zr * ColorSpaces::D50[2];
|
94
|
-
|
94
|
+
|
95
95
|
// XYZ D50 -> Linear sRGB
|
96
96
|
auto linear = ColorSpaces::multiplyMatrix(ColorSpaces::XYZ_D50_TO_LINEAR_SRGB, x, y, z);
|
97
|
-
|
97
|
+
|
98
98
|
// Linear sRGB -> sRGB (gamma encoding)
|
99
99
|
double r = ColorSpaces::gammaEncode(linear[0]) * 255.0;
|
100
100
|
double g = ColorSpaces::gammaEncode(linear[1]) * 255.0;
|
101
101
|
double b = ColorSpaces::gammaEncode(linear[2]) * 255.0;
|
102
|
-
|
102
|
+
|
103
103
|
// Clamp to valid range
|
104
104
|
r = clip(r, 0.0, 255.0);
|
105
105
|
g = clip(g, 0.0, 255.0);
|
106
106
|
b = clip(b, 0.0, 255.0);
|
107
|
-
|
107
|
+
|
108
108
|
return SASS_MEMORY_NEW(Color_RGBA, SourceSpan("[lab]"), r, g, b, alpha);
|
109
109
|
}
|
110
|
-
|
110
|
+
|
111
111
|
Lab Lab::fromRGBA(const Color_RGBA* rgb) {
|
112
112
|
// sRGB -> Linear sRGB (gamma decoding)
|
113
113
|
double r = ColorSpaces::gammaDecode(rgb->r() / 255.0);
|
114
114
|
double g = ColorSpaces::gammaDecode(rgb->g() / 255.0);
|
115
115
|
double b = ColorSpaces::gammaDecode(rgb->b() / 255.0);
|
116
|
-
|
116
|
+
|
117
117
|
// Linear sRGB -> XYZ D50
|
118
118
|
auto xyz = ColorSpaces::multiplyMatrix(ColorSpaces::LINEAR_SRGB_TO_XYZ_D50, r, g, b);
|
119
|
-
|
119
|
+
|
120
120
|
// Normalize by D50 white point
|
121
121
|
double xr = xyz[0] / ColorSpaces::D50[0];
|
122
122
|
double yr = xyz[1] / ColorSpaces::D50[1];
|
123
123
|
double zr = xyz[2] / ColorSpaces::D50[2];
|
124
|
-
|
124
|
+
|
125
125
|
// XYZ D50 -> Lab
|
126
126
|
double fx = ColorSpaces::labF(xr);
|
127
127
|
double fy = ColorSpaces::labF(yr);
|
128
128
|
double fz = ColorSpaces::labF(zr);
|
129
|
-
|
129
|
+
|
130
130
|
double L = 116.0 * fy - 16.0;
|
131
131
|
double a = 500.0 * (fx - fy);
|
132
132
|
double b_val = 200.0 * (fy - fz);
|
133
|
-
|
133
|
+
|
134
134
|
return Lab(L, a, b_val, rgb->a());
|
135
135
|
}
|
136
|
-
|
136
|
+
|
137
137
|
// ============================================================================
|
138
138
|
// LCH Conversions
|
139
139
|
// ============================================================================
|
140
|
-
|
140
|
+
|
141
141
|
Color_RGBA* LCH::toRGBA() const {
|
142
142
|
Lab lab = toLab();
|
143
143
|
return lab.toRGBA();
|
144
144
|
}
|
145
|
-
|
145
|
+
|
146
146
|
LCH LCH::fromRGBA(const Color_RGBA* rgb) {
|
147
147
|
Lab lab = Lab::fromRGBA(rgb);
|
148
148
|
return fromLab(lab);
|
149
149
|
}
|
150
|
-
|
150
|
+
|
151
151
|
Lab LCH::toLab() const {
|
152
152
|
double L, a, b;
|
153
153
|
ColorSpaces::lchToLab(l, c, h, L, a, b);
|
154
154
|
return Lab(L, a, b, alpha);
|
155
155
|
}
|
156
|
-
|
156
|
+
|
157
157
|
LCH LCH::fromLab(const Lab& lab) {
|
158
158
|
double l, c, h;
|
159
159
|
ColorSpaces::labToLch(lab.l, lab.a, lab.b, l, c, h);
|
160
160
|
return LCH(l, c, h, lab.alpha);
|
161
161
|
}
|
162
|
-
|
162
|
+
|
163
163
|
// ============================================================================
|
164
164
|
// OKLab Conversions
|
165
165
|
// ============================================================================
|
166
|
-
|
166
|
+
|
167
167
|
Color_RGBA* OKLab::toRGBA() const {
|
168
168
|
// OKLab -> LMS
|
169
169
|
auto lms = ColorSpaces::multiplyMatrix(ColorSpaces::OKLAB_TO_LMS, l, a, b);
|
170
|
-
|
170
|
+
|
171
171
|
// Cube LMS values
|
172
172
|
double lCubed = lms[0] * lms[0] * lms[0];
|
173
173
|
double mCubed = lms[1] * lms[1] * lms[1];
|
174
174
|
double sCubed = lms[2] * lms[2] * lms[2];
|
175
|
-
|
175
|
+
|
176
176
|
// LMS -> Linear sRGB
|
177
177
|
auto linear = ColorSpaces::multiplyMatrix(ColorSpaces::LMS_TO_LINEAR_SRGB, lCubed, mCubed, sCubed);
|
178
|
-
|
178
|
+
|
179
179
|
// Linear sRGB -> sRGB (gamma encoding)
|
180
180
|
double r = ColorSpaces::gammaEncode(linear[0]) * 255.0;
|
181
181
|
double g = ColorSpaces::gammaEncode(linear[1]) * 255.0;
|
182
182
|
double b = ColorSpaces::gammaEncode(linear[2]) * 255.0;
|
183
|
-
|
183
|
+
|
184
184
|
// Clamp to valid range
|
185
185
|
r = clip(r, 0.0, 255.0);
|
186
186
|
g = clip(g, 0.0, 255.0);
|
187
187
|
b = clip(b, 0.0, 255.0);
|
188
|
-
|
188
|
+
|
189
189
|
return SASS_MEMORY_NEW(Color_RGBA, SourceSpan("[oklab]"), r, g, b, alpha);
|
190
190
|
}
|
191
|
-
|
191
|
+
|
192
192
|
OKLab OKLab::fromRGBA(const Color_RGBA* rgb) {
|
193
193
|
// sRGB -> Linear sRGB (gamma decoding)
|
194
194
|
double r = ColorSpaces::gammaDecode(rgb->r() / 255.0);
|
195
195
|
double g = ColorSpaces::gammaDecode(rgb->g() / 255.0);
|
196
196
|
double b = ColorSpaces::gammaDecode(rgb->b() / 255.0);
|
197
|
-
|
197
|
+
|
198
198
|
// Linear sRGB -> LMS
|
199
199
|
auto lms = ColorSpaces::multiplyMatrix(ColorSpaces::LINEAR_SRGB_TO_LMS, r, g, b);
|
200
|
-
|
200
|
+
|
201
201
|
// Cube root LMS values
|
202
202
|
double lCbrt = std::cbrt(lms[0]);
|
203
203
|
double mCbrt = std::cbrt(lms[1]);
|
204
204
|
double sCbrt = std::cbrt(lms[2]);
|
205
|
-
|
205
|
+
|
206
206
|
// LMS -> OKLab
|
207
207
|
auto oklab = ColorSpaces::multiplyMatrix(ColorSpaces::LMS_TO_OKLAB, lCbrt, mCbrt, sCbrt);
|
208
|
-
|
208
|
+
|
209
209
|
return OKLab(oklab[0], oklab[1], oklab[2], rgb->a());
|
210
210
|
}
|
211
|
-
|
211
|
+
|
212
212
|
// ============================================================================
|
213
213
|
// OKLCH Conversions
|
214
214
|
// ============================================================================
|
215
|
-
|
215
|
+
|
216
216
|
Color_RGBA* OKLCH::toRGBA() const {
|
217
217
|
OKLab oklab = toOKLab();
|
218
218
|
return oklab.toRGBA();
|
219
219
|
}
|
220
|
-
|
220
|
+
|
221
221
|
OKLCH OKLCH::fromRGBA(const Color_RGBA* rgb) {
|
222
222
|
OKLab oklab = OKLab::fromRGBA(rgb);
|
223
223
|
return fromOKLab(oklab);
|
224
224
|
}
|
225
|
-
|
225
|
+
|
226
226
|
OKLab OKLCH::toOKLab() const {
|
227
227
|
double hRad = h * M_PI / 180.0;
|
228
228
|
double a = c * std::cos(hRad);
|
229
229
|
double b = c * std::sin(hRad);
|
230
230
|
return OKLab(l, a, b, alpha);
|
231
231
|
}
|
232
|
-
|
232
|
+
|
233
233
|
OKLCH OKLCH::fromOKLab(const OKLab& oklab) {
|
234
234
|
double c = std::sqrt(oklab.a * oklab.a + oklab.b * oklab.b);
|
235
235
|
double h = std::atan2(oklab.b, oklab.a) * 180.0 / M_PI;
|
236
236
|
if (h < 0) h += 360.0;
|
237
237
|
return OKLCH(oklab.l, c, h, oklab.alpha);
|
238
238
|
}
|
239
|
-
|
239
|
+
|
240
240
|
} // namespace Sass
|
241
241
|
|
@@ -14,14 +14,14 @@ namespace Sass {
|
|
14
14
|
|
15
15
|
// Color space constants for CSS Color Level 4
|
16
16
|
namespace ColorSpaces {
|
17
|
-
|
17
|
+
|
18
18
|
// Constants from https://www.w3.org/TR/css-color-4/
|
19
19
|
constexpr double D50[3] = {0.3457 / 0.3585, 1.00000, (1.0 - 0.3457 - 0.3585) / 0.3585};
|
20
|
-
|
20
|
+
|
21
21
|
// Lab constants
|
22
22
|
constexpr double LAB_KAPPA = 24389.0 / 27.0; // 29^3/3^3
|
23
23
|
constexpr double LAB_EPSILON = 216.0 / 24389.0; // 6^3/29^3
|
24
|
-
|
24
|
+
|
25
25
|
// Conversion matrices
|
26
26
|
// Matrix for converting linear sRGB to XYZ D50
|
27
27
|
constexpr double LINEAR_SRGB_TO_XYZ_D50[9] = {
|
@@ -29,56 +29,56 @@ namespace Sass {
|
|
29
29
|
0.22249317711056518, 0.71688701309448240, 0.06061980979495235,
|
30
30
|
0.01392392146316939, 0.09708132423141015, 0.71409935681588070
|
31
31
|
};
|
32
|
-
|
32
|
+
|
33
33
|
// Matrix for converting XYZ D50 to linear sRGB
|
34
34
|
constexpr double XYZ_D50_TO_LINEAR_SRGB[9] = {
|
35
35
|
3.13413585290011780, -1.61738599801804200, -0.49066221791109754,
|
36
36
|
-0.97879547655577770, 1.91625437739598840, 0.03344287339036693,
|
37
37
|
0.07195539255794733, -0.22897675981518200, 1.40538603511311820
|
38
38
|
};
|
39
|
-
|
39
|
+
|
40
40
|
// Matrix for converting linear sRGB to XYZ D65
|
41
41
|
constexpr double LINEAR_SRGB_TO_XYZ_D65[9] = {
|
42
42
|
0.41239079926595950, 0.35758433938387796, 0.18048078840183430,
|
43
43
|
0.21263900587151036, 0.71516867876775590, 0.07219231536073371,
|
44
44
|
0.01933081871559185, 0.11919477979462598, 0.95053215224966060
|
45
45
|
};
|
46
|
-
|
46
|
+
|
47
47
|
// Matrix for converting XYZ D65 to linear sRGB
|
48
48
|
constexpr double XYZ_D65_TO_LINEAR_SRGB[9] = {
|
49
49
|
3.24096994190452130, -1.53738317757009350, -0.49861076029300330,
|
50
50
|
-0.96924363628087980, 1.87596750150772060, 0.04155505740717561,
|
51
51
|
0.05563007969699360, -0.20397695888897657, 1.05697151424287860
|
52
52
|
};
|
53
|
-
|
53
|
+
|
54
54
|
// Matrix for converting linear sRGB to LMS
|
55
55
|
constexpr double LINEAR_SRGB_TO_LMS[9] = {
|
56
56
|
0.41222146947076300, 0.53633253726173480, 0.05144599326750220,
|
57
57
|
0.21190349581782520, 0.68069955064523420, 0.10739695353694050,
|
58
58
|
0.08830245919005641, 0.28171883913612150, 0.62997870167382210
|
59
59
|
};
|
60
|
-
|
60
|
+
|
61
61
|
// Matrix for converting LMS to linear sRGB
|
62
62
|
constexpr double LMS_TO_LINEAR_SRGB[9] = {
|
63
63
|
4.07674163607595800, -3.30771153925806200, 0.23096990318210417,
|
64
64
|
-1.26843797328503200, 2.60975734928768900, -0.34131937600265710,
|
65
65
|
-0.00419607613867551, -0.70341861793593630, 1.70761469407461200
|
66
66
|
};
|
67
|
-
|
67
|
+
|
68
68
|
// Matrix for converting LMS to OKLab
|
69
69
|
constexpr double LMS_TO_OKLAB[9] = {
|
70
70
|
0.21045426830931400, 0.79361777470230540, -0.00407204301161930,
|
71
71
|
1.97799853243116840, -2.42859224204858000, 0.45059370961741100,
|
72
72
|
0.02590404246554780, 0.78277171245752960, -0.80867575492307740
|
73
73
|
};
|
74
|
-
|
74
|
+
|
75
75
|
// Matrix for converting OKLab to LMS
|
76
76
|
constexpr double OKLAB_TO_LMS[9] = {
|
77
77
|
1.00000000000000020, 0.39633777737617490, 0.21580375730991360,
|
78
78
|
0.99999999999999980, -0.10556134581565854, -0.06385417282581334,
|
79
79
|
0.99999999999999990, -0.08948417752981180, -1.29148554801940940
|
80
80
|
};
|
81
|
-
|
81
|
+
|
82
82
|
// Utility functions for matrix multiplication
|
83
83
|
inline std::array<double, 3> multiplyMatrix(const double matrix[9], double a, double b, double c) {
|
84
84
|
return {
|
@@ -87,7 +87,7 @@ namespace Sass {
|
|
87
87
|
matrix[6] * a + matrix[7] * b + matrix[8] * c
|
88
88
|
};
|
89
89
|
}
|
90
|
-
|
90
|
+
|
91
91
|
// sRGB gamma encoding/decoding
|
92
92
|
inline double gammaEncode(double linear) {
|
93
93
|
if (linear <= 0.0031308) {
|
@@ -95,14 +95,14 @@ namespace Sass {
|
|
95
95
|
}
|
96
96
|
return 1.055 * std::pow(linear, 1.0 / 2.4) - 0.055;
|
97
97
|
}
|
98
|
-
|
98
|
+
|
99
99
|
inline double gammaDecode(double encoded) {
|
100
100
|
if (encoded <= 0.04045) {
|
101
101
|
return encoded / 12.92;
|
102
102
|
}
|
103
103
|
return std::pow((encoded + 0.055) / 1.055, 2.4);
|
104
104
|
}
|
105
|
-
|
105
|
+
|
106
106
|
// HWB conversion helpers
|
107
107
|
inline double hueToRgb(double m1, double m2, double h) {
|
108
108
|
h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
|
@@ -111,7 +111,7 @@ namespace Sass {
|
|
111
111
|
if (h * 3 < 2) return m1 + (m2 - m1) * (2.0 / 3.0 - h) * 6;
|
112
112
|
return m1;
|
113
113
|
}
|
114
|
-
|
114
|
+
|
115
115
|
// Lab conversion helpers
|
116
116
|
inline double labF(double t) {
|
117
117
|
if (t > LAB_EPSILON) {
|
@@ -119,7 +119,7 @@ namespace Sass {
|
|
119
119
|
}
|
120
120
|
return (LAB_KAPPA * t + 16) / 116;
|
121
121
|
}
|
122
|
-
|
122
|
+
|
123
123
|
inline double labFinv(double t) {
|
124
124
|
double cubed = t * t * t;
|
125
125
|
if (cubed > LAB_EPSILON) {
|
@@ -127,7 +127,7 @@ namespace Sass {
|
|
127
127
|
}
|
128
128
|
return (116 * t - 16) / LAB_KAPPA;
|
129
129
|
}
|
130
|
-
|
130
|
+
|
131
131
|
// LCH/Lab conversion
|
132
132
|
inline void labToLch(double L, double a, double b, double& l, double& c, double& h) {
|
133
133
|
l = L;
|
@@ -135,92 +135,92 @@ namespace Sass {
|
|
135
135
|
h = std::atan2(b, a) * 180.0 / M_PI;
|
136
136
|
if (h < 0) h += 360;
|
137
137
|
}
|
138
|
-
|
138
|
+
|
139
139
|
inline void lchToLab(double l, double c, double h, double& L, double& a, double& b) {
|
140
140
|
L = l;
|
141
141
|
double hRad = h * M_PI / 180.0;
|
142
142
|
a = c * std::cos(hRad);
|
143
143
|
b = c * std::sin(hRad);
|
144
144
|
}
|
145
|
-
|
145
|
+
|
146
146
|
} // namespace ColorSpaces
|
147
|
-
|
147
|
+
|
148
148
|
// New color classes for CSS Color Level 4
|
149
|
-
|
149
|
+
|
150
150
|
// HWB Color
|
151
151
|
struct HWB {
|
152
152
|
double h; // Hue (0-360)
|
153
153
|
double w; // Whiteness (0-100)
|
154
154
|
double b; // Blackness (0-100)
|
155
155
|
double a; // Alpha (0-1)
|
156
|
-
|
156
|
+
|
157
157
|
HWB(double hue = 0, double white = 0, double black = 0, double alpha = 1.0)
|
158
158
|
: h(hue), w(white), b(black), a(alpha) {}
|
159
|
-
|
159
|
+
|
160
160
|
Color_RGBA* toRGBA() const;
|
161
161
|
static HWB fromRGBA(const Color_RGBA* rgb);
|
162
162
|
};
|
163
|
-
|
163
|
+
|
164
164
|
// Lab Color
|
165
165
|
struct Lab {
|
166
166
|
double l; // Lightness (0-100)
|
167
167
|
double a; // a-axis (-125 to 125)
|
168
168
|
double b; // b-axis (-125 to 125)
|
169
169
|
double alpha; // Alpha (0-1)
|
170
|
-
|
170
|
+
|
171
171
|
Lab(double lightness = 0, double aAxis = 0, double bAxis = 0, double alphaVal = 1.0)
|
172
172
|
: l(lightness), a(aAxis), b(bAxis), alpha(alphaVal) {}
|
173
|
-
|
173
|
+
|
174
174
|
Color_RGBA* toRGBA() const;
|
175
175
|
static Lab fromRGBA(const Color_RGBA* rgb);
|
176
176
|
};
|
177
|
-
|
177
|
+
|
178
178
|
// LCH Color
|
179
179
|
struct LCH {
|
180
180
|
double l; // Lightness (0-100)
|
181
181
|
double c; // Chroma (0-150)
|
182
182
|
double h; // Hue (0-360)
|
183
183
|
double alpha; // Alpha (0-1)
|
184
|
-
|
184
|
+
|
185
185
|
LCH(double lightness = 0, double chroma = 0, double hue = 0, double alphaVal = 1.0)
|
186
186
|
: l(lightness), c(chroma), h(hue), alpha(alphaVal) {}
|
187
|
-
|
187
|
+
|
188
188
|
Color_RGBA* toRGBA() const;
|
189
189
|
static LCH fromRGBA(const Color_RGBA* rgb);
|
190
190
|
Lab toLab() const;
|
191
191
|
static LCH fromLab(const Lab& lab);
|
192
192
|
};
|
193
|
-
|
193
|
+
|
194
194
|
// OKLab Color
|
195
195
|
struct OKLab {
|
196
196
|
double l; // Lightness (0-1)
|
197
197
|
double a; // a-axis (-0.4 to 0.4)
|
198
198
|
double b; // b-axis (-0.4 to 0.4)
|
199
199
|
double alpha; // Alpha (0-1)
|
200
|
-
|
200
|
+
|
201
201
|
OKLab(double lightness = 0, double aAxis = 0, double bAxis = 0, double alphaVal = 1.0)
|
202
202
|
: l(lightness), a(aAxis), b(bAxis), alpha(alphaVal) {}
|
203
|
-
|
203
|
+
|
204
204
|
Color_RGBA* toRGBA() const;
|
205
205
|
static OKLab fromRGBA(const Color_RGBA* rgb);
|
206
206
|
};
|
207
|
-
|
207
|
+
|
208
208
|
// OKLCH Color
|
209
209
|
struct OKLCH {
|
210
210
|
double l; // Lightness (0-1)
|
211
211
|
double c; // Chroma (0-0.4)
|
212
212
|
double h; // Hue (0-360)
|
213
213
|
double alpha; // Alpha (0-1)
|
214
|
-
|
214
|
+
|
215
215
|
OKLCH(double lightness = 0, double chroma = 0, double hue = 0, double alphaVal = 1.0)
|
216
216
|
: l(lightness), c(chroma), h(hue), alpha(alphaVal) {}
|
217
|
-
|
217
|
+
|
218
218
|
Color_RGBA* toRGBA() const;
|
219
219
|
static OKLCH fromRGBA(const Color_RGBA* rgb);
|
220
220
|
OKLab toOKLab() const;
|
221
221
|
static OKLCH fromOKLab(const OKLab& oklab);
|
222
222
|
};
|
223
|
-
|
223
|
+
|
224
224
|
} // namespace Sass
|
225
225
|
|
226
226
|
#endif
|
@@ -103,6 +103,13 @@ namespace Sass {
|
|
103
103
|
extern const char progid_kwd[] = "progid";
|
104
104
|
extern const char expression_kwd[] = "expression";
|
105
105
|
extern const char calc_fn_kwd[] = "calc";
|
106
|
+
// CSS special function keywords
|
107
|
+
extern const char var_fn_kwd[] = "var";
|
108
|
+
extern const char env_fn_kwd[] = "env";
|
109
|
+
extern const char attr_fn_kwd[] = "attr";
|
110
|
+
extern const char clamp_fn_kwd[] = "clamp";
|
111
|
+
extern const char min_fn_kwd[] = "min";
|
112
|
+
extern const char max_fn_kwd[] = "max";
|
106
113
|
|
107
114
|
extern const char almost_any_value_class[] = "\"'#!;{}";
|
108
115
|
|
@@ -101,6 +101,13 @@ namespace Sass {
|
|
101
101
|
extern const char progid_kwd[];
|
102
102
|
extern const char expression_kwd[];
|
103
103
|
extern const char calc_fn_kwd[];
|
104
|
+
// CSS special function keywords (for CSS custom properties, etc.)
|
105
|
+
extern const char var_fn_kwd[];
|
106
|
+
extern const char env_fn_kwd[];
|
107
|
+
extern const char attr_fn_kwd[];
|
108
|
+
extern const char clamp_fn_kwd[];
|
109
|
+
extern const char min_fn_kwd[];
|
110
|
+
extern const char max_fn_kwd[];
|
104
111
|
|
105
112
|
// char classes for "regular expressions"
|
106
113
|
extern const char almost_any_value_class[];
|
@@ -14,12 +14,30 @@ namespace Sass {
|
|
14
14
|
|
15
15
|
namespace Functions {
|
16
16
|
|
17
|
+
// Check if argument is a "special number" according to CSS Color Level 4
|
18
|
+
// Special numbers include: calc(), var(), env(), attr(), clamp(), min(), max()
|
19
|
+
// These are CSS functions that may return a number and should be passed through as-is
|
17
20
|
bool string_argument(AST_Node_Obj obj) {
|
18
21
|
String_Constant* s = Cast<String_Constant>(obj);
|
19
22
|
if (s == nullptr) return false;
|
20
23
|
const sass::string& str = s->value();
|
24
|
+
|
25
|
+
// Check for CSS function prefixes (case-insensitive check would be better, but this works)
|
21
26
|
return starts_with(str, "calc(") ||
|
22
|
-
starts_with(str, "var(")
|
27
|
+
starts_with(str, "var(") ||
|
28
|
+
starts_with(str, "env(") ||
|
29
|
+
starts_with(str, "attr(") ||
|
30
|
+
starts_with(str, "clamp(") ||
|
31
|
+
starts_with(str, "min(") ||
|
32
|
+
starts_with(str, "max(") ||
|
33
|
+
// Case variations
|
34
|
+
starts_with(str, "CALC(") ||
|
35
|
+
starts_with(str, "VAR(") ||
|
36
|
+
starts_with(str, "ENV(") ||
|
37
|
+
starts_with(str, "ATTR(") ||
|
38
|
+
starts_with(str, "CLAMP(") ||
|
39
|
+
starts_with(str, "MIN(") ||
|
40
|
+
starts_with(str, "MAX(");
|
23
41
|
}
|
24
42
|
|
25
43
|
void hsla_alpha_percent_deprecation(const SourceSpan& pstate, const sass::string val)
|
@@ -633,11 +651,15 @@ namespace Sass {
|
|
633
651
|
Signature hwb_sig = "hwb($hue, $whiteness, $blackness, $alpha: 1)";
|
634
652
|
BUILT_IN(hwb)
|
635
653
|
{
|
654
|
+
bool has_alpha_arg = env.has("$alpha");
|
655
|
+
bool alpha_is_string = has_alpha_arg && string_argument(env["$alpha"]);
|
656
|
+
|
636
657
|
// Check for string arguments (CSS custom properties, calc, var, etc.)
|
637
658
|
if (
|
638
659
|
string_argument(env["$hue"]) ||
|
639
660
|
string_argument(env["$whiteness"]) ||
|
640
|
-
string_argument(env["$blackness"])
|
661
|
+
string_argument(env["$blackness"]) ||
|
662
|
+
alpha_is_string
|
641
663
|
) {
|
642
664
|
sass::string result = "hwb("
|
643
665
|
+ env["$hue"]->to_string()
|
@@ -646,8 +668,12 @@ namespace Sass {
|
|
646
668
|
+ " "
|
647
669
|
+ env["$blackness"]->to_string();
|
648
670
|
|
649
|
-
|
650
|
-
|
671
|
+
// Add alpha if present and not default 1
|
672
|
+
if (has_alpha_arg) {
|
673
|
+
Number* alpha_num = Cast<Number>(env["$alpha"]);
|
674
|
+
if (alpha_is_string || !alpha_num || alpha_num->value() != 1.0) {
|
675
|
+
result += " / " + env["$alpha"]->to_string();
|
676
|
+
}
|
651
677
|
}
|
652
678
|
result += ")";
|
653
679
|
|
@@ -657,7 +683,7 @@ namespace Sass {
|
|
657
683
|
double hue = ARGVAL("$hue");
|
658
684
|
double whiteness = DARG_U_PRCT("$whiteness");
|
659
685
|
double blackness = DARG_U_PRCT("$blackness");
|
660
|
-
double alpha =
|
686
|
+
double alpha = has_alpha_arg ? ALPHA_NUM("$alpha") : 1.0;
|
661
687
|
|
662
688
|
HWB hwb_color(hue, whiteness, blackness, alpha);
|
663
689
|
return hwb_color.toRGBA();
|
@@ -666,10 +692,14 @@ namespace Sass {
|
|
666
692
|
Signature lab_sig = "lab($lightness, $a, $b, $alpha: 1)";
|
667
693
|
BUILT_IN(lab)
|
668
694
|
{
|
695
|
+
bool has_alpha_arg = env.has("$alpha");
|
696
|
+
bool alpha_is_string = has_alpha_arg && string_argument(env["$alpha"]);
|
697
|
+
|
669
698
|
if (
|
670
699
|
string_argument(env["$lightness"]) ||
|
671
700
|
string_argument(env["$a"]) ||
|
672
|
-
string_argument(env["$b"])
|
701
|
+
string_argument(env["$b"]) ||
|
702
|
+
alpha_is_string
|
673
703
|
) {
|
674
704
|
sass::string result = "lab("
|
675
705
|
+ env["$lightness"]->to_string()
|
@@ -678,8 +708,12 @@ namespace Sass {
|
|
678
708
|
+ " "
|
679
709
|
+ env["$b"]->to_string();
|
680
710
|
|
681
|
-
|
682
|
-
|
711
|
+
// Add alpha if present and not default 1
|
712
|
+
if (has_alpha_arg) {
|
713
|
+
Number* alpha_num = Cast<Number>(env["$alpha"]);
|
714
|
+
if (alpha_is_string || !alpha_num || alpha_num->value() != 1.0) {
|
715
|
+
result += " / " + env["$alpha"]->to_string();
|
716
|
+
}
|
683
717
|
}
|
684
718
|
result += ")";
|
685
719
|
|
@@ -689,7 +723,7 @@ namespace Sass {
|
|
689
723
|
double lightness = DARG_U_PRCT("$lightness");
|
690
724
|
double a = ARGVAL("$a");
|
691
725
|
double b = ARGVAL("$b");
|
692
|
-
double alpha =
|
726
|
+
double alpha = has_alpha_arg ? ALPHA_NUM("$alpha") : 1.0;
|
693
727
|
|
694
728
|
Lab lab_color(lightness, a, b, alpha);
|
695
729
|
return lab_color.toRGBA();
|
@@ -698,10 +732,14 @@ namespace Sass {
|
|
698
732
|
Signature lch_sig = "lch($lightness, $chroma, $hue, $alpha: 1)";
|
699
733
|
BUILT_IN(lch)
|
700
734
|
{
|
735
|
+
bool has_alpha_arg = env.has("$alpha");
|
736
|
+
bool alpha_is_string = has_alpha_arg && string_argument(env["$alpha"]);
|
737
|
+
|
701
738
|
if (
|
702
739
|
string_argument(env["$lightness"]) ||
|
703
740
|
string_argument(env["$chroma"]) ||
|
704
|
-
string_argument(env["$hue"])
|
741
|
+
string_argument(env["$hue"]) ||
|
742
|
+
alpha_is_string
|
705
743
|
) {
|
706
744
|
sass::string result = "lch("
|
707
745
|
+ env["$lightness"]->to_string()
|
@@ -710,8 +748,12 @@ namespace Sass {
|
|
710
748
|
+ " "
|
711
749
|
+ env["$hue"]->to_string();
|
712
750
|
|
713
|
-
|
714
|
-
|
751
|
+
// Add alpha if present and not default 1
|
752
|
+
if (has_alpha_arg) {
|
753
|
+
Number* alpha_num = Cast<Number>(env["$alpha"]);
|
754
|
+
if (alpha_is_string || !alpha_num || alpha_num->value() != 1.0) {
|
755
|
+
result += " / " + env["$alpha"]->to_string();
|
756
|
+
}
|
715
757
|
}
|
716
758
|
result += ")";
|
717
759
|
|
@@ -721,7 +763,7 @@ namespace Sass {
|
|
721
763
|
double lightness = DARG_U_PRCT("$lightness");
|
722
764
|
double chroma = ARGVAL("$chroma");
|
723
765
|
double hue = ARGVAL("$hue");
|
724
|
-
double alpha =
|
766
|
+
double alpha = has_alpha_arg ? ALPHA_NUM("$alpha") : 1.0;
|
725
767
|
|
726
768
|
LCH lch_color(lightness, chroma, hue, alpha);
|
727
769
|
return lch_color.toRGBA();
|
@@ -730,10 +772,14 @@ namespace Sass {
|
|
730
772
|
Signature oklab_sig = "oklab($lightness, $a, $b, $alpha: 1)";
|
731
773
|
BUILT_IN(oklab)
|
732
774
|
{
|
775
|
+
bool has_alpha_arg = env.has("$alpha");
|
776
|
+
bool alpha_is_string = has_alpha_arg && string_argument(env["$alpha"]);
|
777
|
+
|
733
778
|
if (
|
734
779
|
string_argument(env["$lightness"]) ||
|
735
780
|
string_argument(env["$a"]) ||
|
736
|
-
string_argument(env["$b"])
|
781
|
+
string_argument(env["$b"]) ||
|
782
|
+
alpha_is_string
|
737
783
|
) {
|
738
784
|
sass::string result = "oklab("
|
739
785
|
+ env["$lightness"]->to_string()
|
@@ -742,8 +788,12 @@ namespace Sass {
|
|
742
788
|
+ " "
|
743
789
|
+ env["$b"]->to_string();
|
744
790
|
|
745
|
-
|
746
|
-
|
791
|
+
// Add alpha if present and not default 1
|
792
|
+
if (has_alpha_arg) {
|
793
|
+
Number* alpha_num = Cast<Number>(env["$alpha"]);
|
794
|
+
if (alpha_is_string || !alpha_num || alpha_num->value() != 1.0) {
|
795
|
+
result += " / " + env["$alpha"]->to_string();
|
796
|
+
}
|
747
797
|
}
|
748
798
|
result += ")";
|
749
799
|
|
@@ -754,7 +804,7 @@ namespace Sass {
|
|
754
804
|
double lightness = DARG_U_FACT("$lightness");
|
755
805
|
double a = ARGVAL("$a");
|
756
806
|
double b = ARGVAL("$b");
|
757
|
-
double alpha =
|
807
|
+
double alpha = has_alpha_arg ? ALPHA_NUM("$alpha") : 1.0;
|
758
808
|
|
759
809
|
OKLab oklab_color(lightness, a, b, alpha);
|
760
810
|
return oklab_color.toRGBA();
|
@@ -763,10 +813,14 @@ namespace Sass {
|
|
763
813
|
Signature oklch_sig = "oklch($lightness, $chroma, $hue, $alpha: 1)";
|
764
814
|
BUILT_IN(oklch)
|
765
815
|
{
|
816
|
+
bool has_alpha_arg = env.has("$alpha");
|
817
|
+
bool alpha_is_string = has_alpha_arg && string_argument(env["$alpha"]);
|
818
|
+
|
766
819
|
if (
|
767
820
|
string_argument(env["$lightness"]) ||
|
768
821
|
string_argument(env["$chroma"]) ||
|
769
|
-
string_argument(env["$hue"])
|
822
|
+
string_argument(env["$hue"]) ||
|
823
|
+
alpha_is_string
|
770
824
|
) {
|
771
825
|
sass::string result = "oklch("
|
772
826
|
+ env["$lightness"]->to_string()
|
@@ -775,8 +829,12 @@ namespace Sass {
|
|
775
829
|
+ " "
|
776
830
|
+ env["$hue"]->to_string();
|
777
831
|
|
778
|
-
|
779
|
-
|
832
|
+
// Add alpha if present and not default 1
|
833
|
+
if (has_alpha_arg) {
|
834
|
+
Number* alpha_num = Cast<Number>(env["$alpha"]);
|
835
|
+
if (alpha_is_string || !alpha_num || alpha_num->value() != 1.0) {
|
836
|
+
result += " / " + env["$alpha"]->to_string();
|
837
|
+
}
|
780
838
|
}
|
781
839
|
result += ")";
|
782
840
|
|
@@ -787,7 +845,7 @@ namespace Sass {
|
|
787
845
|
double lightness = DARG_U_FACT("$lightness");
|
788
846
|
double chroma = ARGVAL("$chroma");
|
789
847
|
double hue = ARGVAL("$hue");
|
790
|
-
double alpha =
|
848
|
+
double alpha = has_alpha_arg ? ALPHA_NUM("$alpha") : 1.0;
|
791
849
|
|
792
850
|
OKLCH oklch_color(lightness, chroma, hue, alpha);
|
793
851
|
return oklch_color.toRGBA();
|
@@ -803,28 +861,41 @@ namespace Sass {
|
|
803
861
|
}
|
804
862
|
|
805
863
|
sass::string space = space_str->value();
|
864
|
+
|
865
|
+
bool has_alpha_arg = env.has("$alpha");
|
866
|
+
bool alpha_is_string = has_alpha_arg && string_argument(env["$alpha"]);
|
867
|
+
|
868
|
+
// Check if any channel contains special numbers (calc, var, etc.)
|
869
|
+
bool has_special_number = string_argument(env["$channel1"]) ||
|
870
|
+
string_argument(env["$channel2"]) ||
|
871
|
+
string_argument(env["$channel3"]) ||
|
872
|
+
alpha_is_string;
|
806
873
|
|
807
874
|
// For now, support the most common color spaces
|
808
875
|
// Full implementation would support: srgb, srgb-linear, display-p3, a98-rgb, prophoto-rgb, rec2020, xyz, xyz-d50, xyz-d65
|
809
876
|
|
810
|
-
if (space == "srgb" || space == "rgb") {
|
811
|
-
// sRGB is the same as legacy RGB
|
877
|
+
if ((space == "srgb" || space == "rgb") && !has_special_number) {
|
878
|
+
// sRGB is the same as legacy RGB - only compute if no special numbers
|
812
879
|
double r = ARGVAL("$channel1");
|
813
880
|
double g = ARGVAL("$channel2");
|
814
881
|
double b = ARGVAL("$channel3");
|
815
|
-
double alpha =
|
882
|
+
double alpha = has_alpha_arg ? ALPHA_NUM("$alpha") : 1.0;
|
816
883
|
|
817
884
|
return SASS_MEMORY_NEW(Color_RGBA, pstate, r * 255.0, g * 255.0, b * 255.0, alpha);
|
818
885
|
}
|
819
886
|
|
820
|
-
// For other color spaces, output as CSS string for browser support
|
887
|
+
// For other color spaces or when special numbers are present, output as CSS string for browser support
|
821
888
|
sass::string result = "color(" + space + " "
|
822
889
|
+ env["$channel1"]->to_string() + " "
|
823
890
|
+ env["$channel2"]->to_string() + " "
|
824
891
|
+ env["$channel3"]->to_string();
|
825
892
|
|
826
|
-
|
827
|
-
|
893
|
+
// Add alpha if present and not default 1
|
894
|
+
if (has_alpha_arg) {
|
895
|
+
Number* alpha_num = Cast<Number>(env["$alpha"]);
|
896
|
+
if (alpha_is_string || !alpha_num || alpha_num->value() != 1.0) {
|
897
|
+
result += " / " + env["$alpha"]->to_string();
|
898
|
+
}
|
828
899
|
}
|
829
900
|
result += ")";
|
830
901
|
|
data/ext/libsass/src/parser.cpp
CHANGED
@@ -1364,6 +1364,9 @@ namespace Sass {
|
|
1364
1364
|
else if (peek< sequence < calc_fn_call, exactly <'('> > >()) {
|
1365
1365
|
return parse_calc_function();
|
1366
1366
|
}
|
1367
|
+
else if (peek< sequence < css_special_fn_call, exactly <'('> > >()) {
|
1368
|
+
return parse_css_special_function();
|
1369
|
+
}
|
1367
1370
|
else if (lex < functional_schema >()) {
|
1368
1371
|
return parse_function_call_schema();
|
1369
1372
|
}
|
@@ -1579,6 +1582,16 @@ namespace Sass {
|
|
1579
1582
|
if (lex< kwd_null >())
|
1580
1583
|
{ return SASS_MEMORY_NEW(Null, pstate); }
|
1581
1584
|
|
1585
|
+
// Check for calc() function
|
1586
|
+
if (peek< sequence < calc_fn_call, exactly <'('> > >()) {
|
1587
|
+
return parse_css_special_function();
|
1588
|
+
}
|
1589
|
+
|
1590
|
+
// Check for CSS special functions (var, env, attr, clamp, min, max) before identifier
|
1591
|
+
if (peek< sequence < css_special_fn_call, exactly <'('> > >()) {
|
1592
|
+
return parse_css_special_function();
|
1593
|
+
}
|
1594
|
+
|
1582
1595
|
if (lex< identifier >()) {
|
1583
1596
|
return color_or_string(lexed);
|
1584
1597
|
}
|
@@ -2001,6 +2014,51 @@ namespace Sass {
|
|
2001
2014
|
return SASS_MEMORY_NEW(Function_Call, call_pos, name, args);
|
2002
2015
|
}
|
2003
2016
|
|
2017
|
+
// CSS special functions (var, env, attr, clamp, min, max) should be passed through as strings
|
2018
|
+
String_Constant_Obj Parser::parse_css_special_function()
|
2019
|
+
{
|
2020
|
+
lex< identifier >();
|
2021
|
+
sass::string name(lexed);
|
2022
|
+
SourceSpan call_pos = pstate;
|
2023
|
+
|
2024
|
+
if (!lex< exactly<'('> >()) {
|
2025
|
+
css_error("Invalid CSS", " after ", ": expected \"(\", was ");
|
2026
|
+
}
|
2027
|
+
|
2028
|
+
// Find the matching closing parenthesis
|
2029
|
+
const char* arg_beg = position;
|
2030
|
+
|
2031
|
+
// Skip over the entire function content including nested parentheses
|
2032
|
+
// This will position us right before the closing ')'
|
2033
|
+
const char* p = arg_beg;
|
2034
|
+
int depth = 1;
|
2035
|
+
bool in_squote = false;
|
2036
|
+
bool in_dquote = false;
|
2037
|
+
|
2038
|
+
while (depth > 0 && *p) {
|
2039
|
+
if (!in_squote && !in_dquote) {
|
2040
|
+
if (*p == '(') depth++;
|
2041
|
+
else if (*p == ')') depth--;
|
2042
|
+
else if (*p == '"') in_dquote = true;
|
2043
|
+
else if (*p == '\'') in_squote = true;
|
2044
|
+
} else {
|
2045
|
+
if (in_dquote && *p == '"' && *(p-1) != '\\') in_dquote = false;
|
2046
|
+
else if (in_squote && *p == '\'' && *(p-1) != '\\') in_squote = false;
|
2047
|
+
}
|
2048
|
+
if (depth > 0) p++;
|
2049
|
+
}
|
2050
|
+
|
2051
|
+
const char* arg_end = p;
|
2052
|
+
|
2053
|
+
// Build the complete function string: name(content)
|
2054
|
+
sass::string result = name + "(" + sass::string(arg_beg, arg_end) + ")";
|
2055
|
+
|
2056
|
+
// Move position past the closing ')'
|
2057
|
+
position = arg_end + 1;
|
2058
|
+
|
2059
|
+
return SASS_MEMORY_NEW(String_Constant, call_pos, result);
|
2060
|
+
}
|
2061
|
+
|
2004
2062
|
String_Obj Parser::parse_url_function_string()
|
2005
2063
|
{
|
2006
2064
|
sass::string prefix("");
|
@@ -2075,7 +2133,11 @@ namespace Sass {
|
|
2075
2133
|
Arguments_Obj args;
|
2076
2134
|
|
2077
2135
|
if (normalized_name == "rgb" || normalized_name == "rgba" ||
|
2078
|
-
normalized_name == "hsl" || normalized_name == "hsla"
|
2136
|
+
normalized_name == "hsl" || normalized_name == "hsla" ||
|
2137
|
+
normalized_name == "hwb" ||
|
2138
|
+
normalized_name == "lab" || normalized_name == "lch" ||
|
2139
|
+
normalized_name == "oklab" || normalized_name == "oklch" ||
|
2140
|
+
normalized_name == "color") {
|
2079
2141
|
args = parse_color_arguments();
|
2080
2142
|
} else {
|
2081
2143
|
args = parse_arguments();
|
data/ext/libsass/src/parser.hpp
CHANGED
@@ -279,6 +279,7 @@ namespace Sass {
|
|
279
279
|
ExpressionObj parse_factor();
|
280
280
|
ExpressionObj parse_value();
|
281
281
|
Function_Call_Obj parse_calc_function();
|
282
|
+
String_Constant_Obj parse_css_special_function();
|
282
283
|
Function_Call_Obj parse_function_call();
|
283
284
|
Function_Call_Obj parse_function_call_schema();
|
284
285
|
String_Obj parse_url_function_string();
|
@@ -1226,6 +1226,19 @@ namespace Sass {
|
|
1226
1226
|
>(src);
|
1227
1227
|
}
|
1228
1228
|
|
1229
|
+
// Match CSS special functions: var, env, attr, clamp, min, max
|
1230
|
+
// These functions should be passed through to CSS as-is
|
1231
|
+
const char* css_special_fn_call(const char* src) {
|
1232
|
+
return alternatives <
|
1233
|
+
sequence < exactly < var_fn_kwd >, word_boundary >,
|
1234
|
+
sequence < exactly < env_fn_kwd >, word_boundary >,
|
1235
|
+
sequence < exactly < attr_fn_kwd >, word_boundary >,
|
1236
|
+
sequence < exactly < clamp_fn_kwd >, word_boundary >,
|
1237
|
+
sequence < exactly < min_fn_kwd >, word_boundary >,
|
1238
|
+
sequence < exactly < max_fn_kwd >, word_boundary >
|
1239
|
+
>(src);
|
1240
|
+
}
|
1241
|
+
|
1229
1242
|
// Match Sass boolean keywords.
|
1230
1243
|
const char* kwd_true(const char* src) {
|
1231
1244
|
return word<true_kwd>(src);
|
@@ -345,6 +345,8 @@ namespace Sass {
|
|
345
345
|
// Match SCSS variable names.
|
346
346
|
const char* variable(const char* src);
|
347
347
|
const char* calc_fn_call(const char* src);
|
348
|
+
// Match CSS special functions (var, env, attr, clamp, min, max)
|
349
|
+
const char* css_special_fn_call(const char* src);
|
348
350
|
|
349
351
|
// IE stuff
|
350
352
|
const char* ie_progid(const char* src);
|
data/lib/sassc/version.rb
CHANGED