Skip to content

Commit 9c210b6

Browse files
authored
css-color-4 : percentage & number unit color components (csstools#266)
* css-color-4 : percentage unit color components * finish lab * more unit support in color components * cleanup * update change log * finish * tabs
1 parent d07a7b1 commit 9c210b6

23 files changed

Lines changed: 326 additions & 122 deletions

plugins/postcss-color-function/CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# Changes to PostCSS Color Function
22

3+
### Unreleased (minor)
4+
5+
- Allow percentage units in XYZ color spaces.
6+
7+
```css
8+
.percentages {
9+
color-1: color(xyz-d50 64.331% 19.245% 16.771%);
10+
color-2: color(xyz-d65 64.331% 19.245% 16.771%);
11+
color-3: color(xyz 64.331% 19.245% 16.771%);
12+
13+
/* becomes */
14+
15+
color-1: rgb(245,0,135);
16+
color-2: rgb(253,0,127);
17+
color-3: rgb(253,0,127);
18+
}
19+
```
20+
321
### 1.0.3 (March 8, 2022)
422

523
- Fix gamut mapping giving overly unsaturated colors.

plugins/postcss-color-function/src/on-css-function.ts

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,7 @@ function colorFunctionContents(nodes): Color|null {
236236
}
237237
}
238238

239-
if (!out.colorSpace.startsWith('xyz') && isNumericNodePercentageOrNumber(nodes[i])) {
240-
// non-xyz DOES support percentages
239+
if (isNumericNodePercentageOrNumber(nodes[i])) {
241240
const unitAndValue = valueParser.unit(nodes[i].value) as Dimension;
242241
if (unitAndValue.unit === '%') {
243242
// transform the channel from a Percentage to (0-1) Number
@@ -250,19 +249,6 @@ function colorFunctionContents(nodes): Color|null {
250249
value: unitAndValue,
251250
node: nodes[i],
252251
});
253-
254-
} else if (out.colorSpace.startsWith('xyz') && isNumericNodePercentageOrNumber(nodes[i])) {
255-
// xyz DOES NOT support percentages
256-
const unitAndValue = valueParser.unit(nodes[i].value) as Dimension;
257-
if (unitAndValue.unit !== '') {
258-
return null;
259-
}
260-
261-
out.parameters.push({
262-
value: unitAndValue,
263-
node: nodes[i],
264-
});
265-
266252
} else {
267253
return null;
268254
}

plugins/postcss-color-function/test/basic.expect.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@
6464
}
6565

6666
.test-percentage-xyz {
67-
color-1: color(xyz-d50 64.331% 0.19245 0.16771);
68-
color-2: color(xyz-d65 0.64331 19.245% 0.16771);
69-
color-3: color(xyz 0.64331 0.19245 16.771%);
67+
color-1: rgb(252,0,135);
68+
color-2: rgb(255,0,126);
69+
color-3: rgb(255,0,126);
7070
}
7171

7272
.test-author-provided-fallback {

plugins/postcss-color-function/test/basic.preserve-true.expect.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,11 @@
9292
}
9393

9494
.test-percentage-xyz {
95+
color-1: rgb(252,0,135);
9596
color-1: color(xyz-d50 64.331% 0.19245 0.16771);
97+
color-2: rgb(255,0,126);
9698
color-2: color(xyz-d65 0.64331 19.245% 0.16771);
99+
color-3: rgb(255,0,126);
97100
color-3: color(xyz 0.64331 0.19245 16.771%);
98101
}
99102

plugins/postcss-lab-function/CHANGELOG.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
11
# Changes to PostCSS Lab Function
22

3+
### Unreleased (minor)
4+
5+
- Allow percentage and number units in more color components.
6+
7+
```css
8+
.percentages {
9+
color-1: lab(40% 35% 30%);
10+
color-2: lch(40% 50% 39);
11+
12+
/* becomes */
13+
14+
color-1: rgb(163, 57, 35);
15+
color-1: color(display-p3 0.59266 0.25309 0.17075);
16+
color-2: rgb(181, 30, 19);
17+
color-2: color(display-p3 0.65205 0.18193 0.12753);
18+
}
19+
20+
.numbers {
21+
color-1: lab(40 35 30);
22+
color-2: lch(40 50 39);
23+
24+
/* becomes */
25+
26+
color-1: rgb(152, 68, 47);
27+
color-1: color(display-p3 0.55453 0.28432 0.20788);
28+
color-2: rgb(157, 63, 45);
29+
color-2: color(display-p3 0.57072 0.27138 0.20109);
30+
}
31+
```
32+
333
### 4.1.2 (March 8, 2022)
434

535
- Fix gamut mapping giving overly unsaturated colors.

plugins/postcss-lab-function/src/convert-lab-to-display-p3.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ export function labToDisplayP3(labRaw: color): [color, boolean] {
1414
const labA = Math.min(
1515
Math.max(
1616
labARaw,
17-
-127,
17+
-160,
1818
),
19-
128,
19+
160,
2020
);
2121

2222
const labB = Math.min(
2323
Math.max(
2424
labBRaw,
25-
-127,
25+
-160,
2626
),
27-
128,
27+
160,
2828
);
2929

3030
const lab = [labL, labA, labB];

plugins/postcss-lab-function/src/convert-lab-to-srgb.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ export function labToSRgb(labRaw: color): color {
1414
const labA = Math.min(
1515
Math.max(
1616
labARaw,
17-
-127,
17+
-160,
1818
),
19-
128,
19+
160,
2020
);
2121

2222
const labB = Math.min(
2323
Math.max(
2424
labBRaw,
25-
-127,
25+
-160,
2626
),
27-
128,
27+
160,
2828
);
2929

3030
const lab = [labL, labA, labB];

plugins/postcss-lab-function/src/on-css-function.ts

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ export function onCSSFunctionSRgb(node: FunctionNode) {
2424
return;
2525
}
2626

27-
if (relevantNodes.length > 3 && (!nodes.slash || !nodes.alpha)) {
28-
return;
29-
}
30-
3127
// rename the Color function to `rgb`
3228
node.value = 'rgb';
3329

@@ -191,23 +187,6 @@ function isNumericNode(node: Node): node is WordNode {
191187
return !!unitAndValue.number;
192188
}
193189

194-
function isNumericNodeNumber(node): node is WordNode {
195-
if (!node || node.type !== 'word') {
196-
return false;
197-
}
198-
199-
if (!canParseAsUnit(node)) {
200-
return false;
201-
}
202-
203-
const unitAndValue = valueParser.unit(node.value);
204-
if (!unitAndValue) {
205-
return false;
206-
}
207-
208-
return !!unitAndValue.number && unitAndValue.unit === '';
209-
}
210-
211190
function isNumericNodeHueLike(node: Node): node is WordNode {
212191
if (!node || node.type !== 'word') {
213192
return false;
@@ -231,23 +210,6 @@ function isNumericNodeHueLike(node: Node): node is WordNode {
231210
);
232211
}
233212

234-
function isNumericNodePercentage(node: Node): node is WordNode {
235-
if (!node || node.type !== 'word') {
236-
return false;
237-
}
238-
239-
if (!canParseAsUnit(node)) {
240-
return false;
241-
}
242-
243-
const unitAndValue = valueParser.unit(node.value);
244-
if (!unitAndValue) {
245-
return false;
246-
}
247-
248-
return unitAndValue.unit === '%';
249-
}
250-
251213
function isNumericNodePercentageOrNumber(node: Node): node is WordNode {
252214
if (!node || node.type !== 'word') {
253215
return false;
@@ -289,11 +251,11 @@ type Lch = {
289251
}
290252

291253
function lchFunctionContents(nodes): Lch|null {
292-
if (!isNumericNodePercentage(nodes[0])) {
254+
if (!isNumericNodePercentageOrNumber(nodes[0])) {
293255
return null;
294256
}
295257

296-
if (!isNumericNodeNumber(nodes[1])) {
258+
if (!isNumericNodePercentageOrNumber(nodes[1])) {
297259
return null;
298260
}
299261

@@ -323,6 +285,21 @@ function lchFunctionContents(nodes): Lch|null {
323285
out.alpha = nodes[4];
324286
}
325287

288+
if (nodes.length > 3 && (!out.slash || !out.alpha)) {
289+
return null;
290+
}
291+
292+
// 0% = 0.0, 100% = 100.0
293+
if (out.l.unit === '%') {
294+
out.l.unit = '';
295+
}
296+
297+
// 0% = 0, 100% = 150
298+
if (out.c.unit === '%') {
299+
out.c.unit = '';
300+
out.c.number = ((parseFloat(out.c.number) / 100) * 150).toFixed(10);
301+
}
302+
326303
return out;
327304
}
328305

@@ -338,15 +315,15 @@ type Lab = {
338315
}
339316

340317
function labFunctionContents(nodes): Lab|null {
341-
if (!isNumericNodePercentage(nodes[0])) {
318+
if (!isNumericNodePercentageOrNumber(nodes[0])) {
342319
return null;
343320
}
344321

345-
if (!isNumericNodeNumber(nodes[1])) {
322+
if (!isNumericNodePercentageOrNumber(nodes[1])) {
346323
return null;
347324
}
348325

349-
if (!isNumericNodeNumber(nodes[2])) {
326+
if (!isNumericNodePercentageOrNumber(nodes[2])) {
350327
return null;
351328
}
352329

@@ -367,6 +344,27 @@ function labFunctionContents(nodes): Lab|null {
367344
out.alpha = nodes[4];
368345
}
369346

347+
if (nodes.length > 3 && (!out.slash || !out.alpha)) {
348+
return null;
349+
}
350+
351+
// 0% = 0.0, 100% = 100.0
352+
if (out.l.unit === '%') {
353+
out.l.unit = '';
354+
}
355+
356+
// -100% = -125, 100% = 125
357+
if (out.a.unit === '%') {
358+
out.a.unit = '';
359+
out.a.number = ((parseFloat(out.a.number) / 100) * 125).toFixed(10);
360+
}
361+
362+
// -100% = -125, 100% = 125
363+
if (out.b.unit === '%') {
364+
out.b.unit = '';
365+
out.b.number = ((parseFloat(out.b.number) / 100) * 125).toFixed(10);
366+
}
367+
370368
return out;
371369
}
372370

plugins/postcss-lab-function/test/basic.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,17 @@
2828
color-15: lch(60% 50 50grad);
2929
color-16: lch(60% 50 0.785398rad);
3030
color-17: lch(60% 50 0.785398unknown);
31+
color-18: lch(60% 50 405);
32+
}
33+
34+
.test-percentages {
35+
color-1: lab(40% 35% 30%);
36+
color-2: lch(40% 50% 39);
37+
}
38+
39+
.test-numbers {
40+
color-1: lab(40 35 30);
41+
color-2: lch(40 50 39);
3142
}
3243

3344
.test-author-provided-fallback {

plugins/postcss-lab-function/test/basic.display-p3-false.expect.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,17 @@
2828
color-15: rgb(212, 118, 84);
2929
color-16: rgb(212, 118, 84);
3030
color-17: lch(60% 50 0.785398unknown);
31+
color-18: rgb(212, 118, 84);
32+
}
33+
34+
.test-percentages {
35+
color-1: rgb(163, 57, 35);
36+
color-2: rgb(181, 30, 19);
37+
}
38+
39+
.test-numbers {
40+
color-1: rgb(152, 68, 47);
41+
color-2: rgb(157, 63, 45);
3142
}
3243

3344
.test-author-provided-fallback {

0 commit comments

Comments
 (0)