Skip to content

Commit e9c9705

Browse files
authored
css-color-parser: fix handling of none in some edge cases (#1859)
1 parent 75781af commit e9c9705

23 files changed

Lines changed: 2546 additions & 1257 deletions

packages/css-color-parser/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changes to CSS Color Parser
22

3+
### Unreleased (patch)
4+
5+
- Fix handling of `none` in some edge cases
6+
37
### 4.1.9
48

59
_June 25, 2026_

packages/css-color-parser/dist/index.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

packages/css-color-parser/src/color-data.ts

Lines changed: 350 additions & 205 deletions
Large diffs are not rendered by default.

packages/css-color-parser/src/functions/color-mix.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { Color } from '@csstools/color-helpers';
55
import { ColorNotation } from '../color-notation';
66
import { isTokenIdent, isTokenNumeric, isTokenPercentage } from '@csstools/css-tokenizer';
77
import { calcFromComponentValues } from '@csstools/css-calc';
8-
import { colorDataTo, SyntaxFlag } from '../color-data';
8+
import { colorDataToForInterpolation, SyntaxFlag } from '../color-data';
99
import { isFunctionNode, isTokenNode, isWhiteSpaceOrCommentNode } from '@csstools/css-parser-algorithms';
1010
import { toLowerCaseAZ } from '../util/to-lower-case-a-z';
1111
import { mathFunctionNames } from '@csstools/css-calc';
@@ -279,7 +279,7 @@ function colorMixRectangular(colorSpace: string, items: Array<ColorMixEntry> | f
279279

280280
// 3. If items is length 1, set color to the color of that sole item, converted to the specified interpolation <color-space>.
281281
if (normalizedItems.length === 1) {
282-
const color = colorDataTo(normalizedItems[0].color, outputColorNotation);
282+
const color = colorDataToForInterpolation(normalizedItems[0].color, outputColorNotation);
283283
color.colorNotation = outputColorNotation;
284284
color.syntaxFlags.add(SyntaxFlag.ColorMixVariadic);
285285
color.syntaxFlags.add(SyntaxFlag.ColorMix);
@@ -369,8 +369,8 @@ function colorMixRectangularPair(colorNotation: ColorNotation, a_color: ColorDat
369369
a_alpha = Number.isNaN(a_alpha) ? b_alpha : a_alpha;
370370
b_alpha = Number.isNaN(b_alpha) ? a_alpha : b_alpha;
371371

372-
const a_channels = colorDataTo(a_color, colorNotation).channels;
373-
const b_channels = colorDataTo(b_color, colorNotation).channels;
372+
const a_channels = colorDataToForInterpolation(a_color, colorNotation).channels;
373+
const b_channels = colorDataToForInterpolation(b_color, colorNotation).channels;
374374

375375
a_channels[0] = fillInMissingComponent(a_channels[0], b_channels[0]);
376376
b_channels[0] = fillInMissingComponent(b_channels[0], a_channels[0]);
@@ -448,7 +448,7 @@ function colorMixPolar(colorSpace: string, hueInterpolationMethod: string, items
448448

449449
// 3. If items is length 1, set color to the color of that sole item, converted to the specified interpolation <color-space>.
450450
if (normalizedItems.length === 1) {
451-
const color = colorDataTo(normalizedItems[0].color, outputColorNotation);
451+
const color = colorDataToForInterpolation(normalizedItems[0].color, outputColorNotation);
452452
color.colorNotation = outputColorNotation;
453453
color.syntaxFlags.add(SyntaxFlag.ColorMixVariadic);
454454
color.syntaxFlags.add(SyntaxFlag.ColorMix);
@@ -547,8 +547,8 @@ function colorMixPolarPair(colorNotation: ColorNotation, hueInterpolationMethod:
547547
a_alpha = Number.isNaN(a_alpha) ? b_alpha : a_alpha;
548548
b_alpha = Number.isNaN(b_alpha) ? a_alpha : b_alpha;
549549

550-
const a_channels = colorDataTo(a_color, colorNotation).channels;
551-
const b_channels = colorDataTo(b_color, colorNotation).channels;
550+
const a_channels = colorDataToForInterpolation(a_color, colorNotation).channels;
551+
const b_channels = colorDataToForInterpolation(b_color, colorNotation).channels;
552552

553553
switch (colorNotation) {
554554
case ColorNotation.HSL:

packages/css-color-parser/src/functions/color-normalize-channel-values.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ export function normalize_Color_ChannelValues(token: CSSToken, index: number, co
2626
colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues);
2727
}
2828

29-
let value = normalize(token[4].value, 100, -2_147_483_647, 2_147_483_647);
29+
let value;
3030
if (index === 3) {
3131
value = normalize(token[4].value, 100, 0, 1);
32+
} else {
33+
value = normalize(token[4].value, 100, -2_147_483_647, 2_147_483_647);
3234
}
3335

3436
return [
@@ -48,9 +50,11 @@ export function normalize_Color_ChannelValues(token: CSSToken, index: number, co
4850
colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues);
4951
}
5052

51-
let value = normalize(token[4].value, 1, -2_147_483_647, 2_147_483_647);
53+
let value;
5254
if (index === 3) {
5355
value = normalize(token[4].value, 1, 0, 1);
56+
} else {
57+
value = normalize(token[4].value, 1, -2_147_483_647, 2_147_483_647);
5458
}
5559

5660
return [

packages/css-color-parser/src/functions/color.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ColorData} from '../color-data';
2-
import { SyntaxFlag, colorDataTo, noneToZeroInRelativeColorDataChannels, normalizeRelativeColorDataChannels } from '../color-data';
2+
import { SyntaxFlag, colorDataToForRelativeColorSyntax, noneToZeroInRelativeColorDataChannels, normalizeRelativeColorDataChannels } from '../color-data';
33
import type { ColorParser } from '../color-parser';
44
import { ColorNotation } from '../color-notation';
55
import type { ComponentValue, FunctionNode} from '@csstools/css-parser-algorithms';
@@ -106,10 +106,7 @@ export function color(colorFunctionNode: FunctionNode, colorParser: ColorParser)
106106
colorData.colorNotation = colorSpaceNameToColorNotation(colorSpace);
107107

108108
if (relativeToColor) {
109-
if (relativeToColor.colorNotation !== colorData.colorNotation) {
110-
relativeToColor = colorDataTo(relativeToColor, colorData.colorNotation);
111-
}
112-
109+
relativeToColor = colorDataToForRelativeColorSyntax(relativeToColor, colorData.colorNotation);
113110
relativeColorChannels = normalizeRelativeColorDataChannels(relativeToColor);
114111
relativeColorChannelsWithoutNone = noneToZeroInRelativeColorDataChannels(relativeColorChannels);
115112
}

packages/css-color-parser/src/functions/hsl-normalize-channel-values.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ export function normalize_legacy_HSL_ChannelValues(token: CSSToken, index: numbe
2727
colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues);
2828
}
2929

30-
let value = normalize(token[4].value, 1, 0, 100);
30+
let value;
3131
if (index === 3) {
3232
value = normalize(token[4].value, 100, 0, 1);
33+
} else {
34+
value = normalize(token[4].value, 1, 0, 100);
3335
}
3436

3537
return [
@@ -49,9 +51,11 @@ export function normalize_legacy_HSL_ChannelValues(token: CSSToken, index: numbe
4951
return false;
5052
}
5153

52-
let value = normalize(token[4].value, 1, 0, 100);
54+
let value;
5355
if (index === 3) {
5456
value = normalize(token[4].value, 1, 0, 1);
57+
} else {
58+
value = normalize(token[4].value, 1, 0, 100);
5559
}
5660

5761
return [
@@ -105,11 +109,13 @@ export function normalize_modern_HSL_ChannelValues(token: CSSToken, index: numbe
105109
colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues);
106110
}
107111

108-
let value = token[4].value;
112+
let value;
109113
if (index === 3) {
110114
value = normalize(token[4].value, 100, 0, 1);
111115
} else if (index === 1) {
112116
value = normalize(token[4].value, 1, 0, 2_147_483_647);
117+
} else {
118+
value = normalize(token[4].value, 1, -2_147_483_647, 2_147_483_647);
113119
}
114120

115121
return [
@@ -129,11 +135,13 @@ export function normalize_modern_HSL_ChannelValues(token: CSSToken, index: numbe
129135
colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues);
130136
}
131137

132-
let value = token[4].value;
138+
let value;
133139
if (index === 3) {
134140
value = normalize(token[4].value, 1, 0, 1);
135141
} else if (index === 1) {
136142
value = normalize(token[4].value, 1, 0, 2_147_483_647);
143+
} else {
144+
value = normalize(token[4].value, 1, -2_147_483_647, 2_147_483_647);
137145
}
138146

139147
return [

packages/css-color-parser/src/functions/hwb-normalize-channel-values.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,11 @@ export function normalize_HWB_ChannelValues(token: CSSToken, index: number, colo
4242
colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues);
4343
}
4444

45-
let value = token[4].value;
45+
let value;
4646
if (index === 3) {
4747
value = normalize(token[4].value, 100, 0, 1);
48+
} else {
49+
value = normalize(token[4].value, 1, -2_147_483_647, 2_147_483_647);
4850
}
4951

5052
return [
@@ -64,9 +66,11 @@ export function normalize_HWB_ChannelValues(token: CSSToken, index: number, colo
6466
colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues);
6567
}
6668

67-
let value = token[4].value;
69+
let value;
6870
if (index === 3) {
6971
value = normalize(token[4].value, 1, 0, 1);
72+
} else {
73+
value = normalize(token[4].value, 1, -2_147_483_647, 2_147_483_647);
7074
}
7175

7276
return [

packages/css-color-parser/src/functions/lab-normalize-channel-values.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ export function normalize_Lab_ChannelValues(token: CSSToken, index: number, colo
2626
colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues);
2727
}
2828

29-
let value = normalize(token[4].value, 1, 0, 100);
29+
let value;
3030
if (index === 1 || index === 2) {
3131
value = normalize(token[4].value, 0.8, -2_147_483_647, 2_147_483_647);
3232
} else if (index === 3) {
3333
value = normalize(token[4].value, 100, 0, 1);
34+
} else {
35+
value = normalize(token[4].value, 1, 0, 100);
3436
}
3537

3638
return [
@@ -50,11 +52,13 @@ export function normalize_Lab_ChannelValues(token: CSSToken, index: number, colo
5052
colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues);
5153
}
5254

53-
let value = normalize(token[4].value, 1, 0, 100);
55+
let value;
5456
if (index === 1 || index === 2) {
5557
value = normalize(token[4].value, 1, -2_147_483_647, 2_147_483_647);
5658
} else if (index === 3) {
5759
value = normalize(token[4].value, 1, 0, 1);
60+
} else {
61+
value = normalize(token[4].value, 1, 0, 100);
5862
}
5963

6064
return [

packages/css-color-parser/src/functions/lch-normalize-channel-values.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ export function normalize_LCH_ChannelValues(token: CSSToken, index: number, colo
4040
colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues);
4141
}
4242

43-
let value = normalize(token[4].value, 1, 0, 100);
43+
let value;
4444
if (index === 1) {
4545
value = normalize(token[4].value, (100 / 150), 0, 2_147_483_647);
4646
} else if (index === 3) {
4747
value = normalize(token[4].value, 100, 0, 1);
48+
} else {
49+
value = normalize(token[4].value, 1, 0, 100);
4850
}
4951

5052
return [
@@ -64,11 +66,13 @@ export function normalize_LCH_ChannelValues(token: CSSToken, index: number, colo
6466
colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues);
6567
}
6668

67-
let value = normalize(token[4].value, 1, 0, 100);
69+
let value;
6870
if (index === 1) {
6971
value = normalize(token[4].value, 1, 0, 2_147_483_647);
7072
} else if (index === 3) {
7173
value = normalize(token[4].value, 1, 0, 1);
74+
} else {
75+
value = normalize(token[4].value, 1, 0, 100);
7276
}
7377

7478
return [

0 commit comments

Comments
 (0)