Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/css-color-parser/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changes to CSS Color Parser

### Unreleased (patch)

- Fix handling of `none` in some edge cases

### 4.1.9

_June 25, 2026_
Expand Down
2 changes: 1 addition & 1 deletion packages/css-color-parser/dist/index.mjs

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions packages/css-color-parser/src/color-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,25 +592,25 @@ function convertPowerlessComponentsToMissingComponents(a: Color, colorNotation:

switch (colorNotation) {
case ColorNotation.HSL:
if (!Number.isNaN(out[1]) && out[1] <= 0.001) {
if ((Number.isNaN(out[1]) ? 0 : out[1]) <= 0.001) {
out[0] = Number.NaN;
}

break;
case ColorNotation.HWB:
if (!Number.isNaN(out[1]) && !Number.isNaN(out[2]) && (Math.max(0, out[1]) + Math.max(0, out[2])) >= 99.999) {
if ((Math.max(0, (Number.isNaN(out[1]) ? 0 : out[1])) + Math.max(0, (Number.isNaN(out[2]) ? 0 : out[2]))) >= 99.999) {
out[0] = Number.NaN;
}

break;
case ColorNotation.LCH:
if (!Number.isNaN(out[1]) && out[1] <= 0.0015) {
if ((Number.isNaN(out[1]) ? 0 : out[1]) <= 0.0015) {
out[2] = Number.NaN;
}

break;
case ColorNotation.OKLCH:
if (!Number.isNaN(out[1]) && out[1] <= 0.000004) {
if ((Number.isNaN(out[1]) ? 0 : out[1]) <= 0.000004) {
out[2] = Number.NaN;
}

Expand All @@ -625,18 +625,18 @@ export function convertPowerlessComponentsToZeroValuesForDisplay(a: Color, color

switch (colorNotation) {
case ColorNotation.HSL:
if (reducePrecision(out[2]) <= 0 || reducePrecision(out[2]) >= 100) {
if ((Number.isNaN(out[1]) ? 0 : out[1]) <= 0.001) {
out[0] = Number.NaN;
out[1] = Number.NaN;
}

if (!Number.isNaN(out[1]) && out[1] <= 0.001) {
if (reducePrecision(out[2]) <= 0 || reducePrecision(out[2]) >= 100) {
out[0] = Number.NaN;
out[1] = Number.NaN;
}

break;
case ColorNotation.HWB:
if (!Number.isNaN(out[1]) && !Number.isNaN(out[2]) && (Math.max(0, out[1]) + Math.max(0, out[2])) >= 99.999) {
if ((Math.max(0, (Number.isNaN(out[1]) ? 0 : out[1])) + Math.max(0, (Number.isNaN(out[2]) ? 0 : out[2]))) >= 99.999) {
out[0] = Number.NaN;
}
break;
Expand All @@ -647,7 +647,7 @@ export function convertPowerlessComponentsToZeroValuesForDisplay(a: Color, color
}
break;
case ColorNotation.LCH:
if (!Number.isNaN(out[1]) && out[1] <= 0.0015) {
if ((Number.isNaN(out[1]) ? 0 : out[1]) <= 0.0015) {
out[2] = Number.NaN;
}

Expand All @@ -663,7 +663,7 @@ export function convertPowerlessComponentsToZeroValuesForDisplay(a: Color, color
}
break;
case ColorNotation.OKLCH:
if (!Number.isNaN(out[1]) && out[1] <= 0.000004) {
if ((Number.isNaN(out[1]) ? 0 : out[1]) <= 0.000004) {
out[2] = Number.NaN;
}

Expand Down
5 changes: 1 addition & 4 deletions packages/css-color-parser/src/functions/color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,7 @@ export function color(colorFunctionNode: FunctionNode, colorParser: ColorParser)
colorData.colorNotation = colorSpaceNameToColorNotation(colorSpace);

if (relativeToColor) {
if (relativeToColor.colorNotation !== colorData.colorNotation) {
relativeToColor = colorDataTo(relativeToColor, colorData.colorNotation);
}

relativeToColor = colorDataTo(relativeToColor, colorData.colorNotation);
relativeColorChannels = normalizeRelativeColorDataChannels(relativeToColor);
relativeColorChannelsWithoutNone = noneToZeroInRelativeColorDataChannels(relativeColorChannels);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,7 @@ export function threeChannelSpaceSeparated(

colorData.syntaxFlags.add(SyntaxFlag.RelativeColorSyntax);

if (relativeToColor.colorNotation !== colorNotation) {
relativeToColor = colorDataTo(relativeToColor, colorNotation);
}

relativeToColor = colorDataTo(relativeToColor, colorNotation);
relativeColorChannels = normalizeRelativeColorDataChannels(relativeToColor);
relativeColorChannelsWithoutNone = noneToZeroInRelativeColorDataChannels(relativeColorChannels);

Expand Down
2 changes: 1 addition & 1 deletion packages/css-color-parser/test/basic/basic.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ assert.deepStrictEqual(
color(parse('lch(from hwb(50deg none none) l c h)')),
{
colorNotation: 'lch',
channels: [NaN, NaN, 87.26522367839932],
channels: [NaN, NaN, NaN],
alpha: 1,
syntaxFlags: new Set(['relative-color-syntax', 'has-number-values']),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ const tests = [
['color-mix(in oklch, rgb(255, 255, 255), rgb(180, 6, 95))', 'oklch(0.75031 0.10016 359.858)'],
['color-mix(in lch, oklch(75% 0% 60deg), oklch(75% 50% 0deg))', 'oklch(0.74979 0.09824 0.10588)'],
['color-mix(in oklch, oklch(100% 0% none), oklch(50% 50% 0deg))', 'oklch(0.75 0.1 0)'],
['color-mix(in oklch, oklch(100% none 60deg), oklch(50% 50% 0deg))', 'oklch(0.75 0.2 30)'],
['color-mix(in oklch, oklch(100% none 60deg), oklch(50% 50% 0deg))', 'oklch(0.75 0.2 0)'],

// Analogous sets
['color-mix(in oklch, rgb(none none none), oklch(0.5 0.2 50))', 'oklch(0.5 0.2 50)'],
['color-mix(in oklch, hwb(100deg none none), oklch(0.5 0.2 50deg))', 'oklch(0.5 0.2 94.8876)'],
['color-mix(in oklch, hwb(100deg none none), oklch(0.5 0.2 50deg))', 'oklch(0.5 0.2 50)'],
['color-mix(in oklch, lab(100 none none), oklch(0.5 0.2 50deg))', 'oklch(0.75 0.2 50)'],
];

Expand Down
14 changes: 13 additions & 1 deletion packages/css-color-parser/test/basic/color-mix-function.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ const tests = [
['color-mix(in oklch, green 40%, oklch(0.747 0.196 322.2))', 'rgb(0, 148, 253)'],
['color-mix(in oklch, green 40%, hsl(292deg 85.71% 72.55%))', 'rgb(0, 148, 253)'],

['color-mix(in display-p3-linear, green 40%, color(srgb 0.8978862558205767 0.4885001647805462 0.9594359763905097))', 'rgb(182, 126, 195)'],
['color-mix(in display-p3-linear, green 40%, color(srgb-linear 0.7832360124544266 0.2035510416163499 0.9101924728483531))', 'rgb(182, 126, 195)'],
['color-mix(in display-p3-linear, green 40%, color(a98-rgb 0.8035122804301492 0.484896415622613 0.9440692746539695))', 'rgb(182, 126, 195)'],
['color-mix(in display-p3-linear, green 40%, color(prophoto-rgb 0.7596595159204217 0.4934889951894072 0.8985832663171222))', 'rgb(182, 126, 195)'],
['color-mix(in display-p3-linear, green 40%, color(display-p3 0.843565234 0.509345345 0.9342344435))', 'rgb(182, 126, 195)'],
['color-mix(in display-p3-linear, green 40%, color(rec2020 0.807076644727751 0.5627572708703388 0.9326528689276063))', 'rgb(182, 126, 195)'],
['color-mix(in display-p3-linear, green 40%, color(xyz-d50 0.5501693084815327 0.37536346388820246 0.6806345611398199))', 'rgb(182, 126, 195)'],
['color-mix(in display-p3-linear, green 40%, color(xyz-d65 0.5600582450343325 0.37782875858447507 0.904570025128693))', 'rgb(182, 126, 195)'],
['color-mix(in display-p3-linear, green 40%, color(xyz 0.5600582450343325 0.37782875858447507 0.904570025128693))', 'rgb(182, 126, 195)'],
['color-mix(in display-p3-linear, green 40%, oklch(0.747 0.196 322.2))', 'rgb(182, 126, 195)'],
['color-mix(in display-p3-linear, green 40%, hsl(292deg 85.71% 72.55%))', 'rgb(182, 126, 195)'],

['color-mix(in srgb, color(xyz 1 none 0) 30%, rgb(none 255 128))', 'rgb(255, 255, 255)'],

['color-mix(in oklab, #09232c, white 50%)', 'rgb(123, 137, 142)'],
Expand Down Expand Up @@ -104,7 +116,7 @@ const tests = [

['color-mix(in hsl, color-mix(in hsl longer hue, hsl(50deg 0% 50%), hsl(50deg 0% 50%)), hsl(180deg 100% 50%))', canonicalize('hsl(180deg 50% 50%)')],

['color-mix(in hsl, hsl(30deg 40% 80% / 25%) 0%, hsl(90deg none none / none))', canonicalize('hsl(90deg 40% 80% / 25%)')],
['color-mix(in hsl, hsl(30deg 40% 80% / 25%) 0%, hsl(90deg none none / none))', canonicalize('hsl(30deg 40% 80% / 25%)')],
['color-mix(in hwb, hwb(30deg 30% 40% / 25%) 0%, hwb(90deg none none / 0.5))', canonicalize('hwb(90deg 30% 40% / 0.5)')],
['color-mix(in hsl, hsl(from hsl(none 50% 50%) h s l), hsl(from hsl(120deg 50% 50%) h s l))', canonicalize('hsl(120deg 50% 50%)')],
['color-mix(in hsl, hsl(from hsl(0deg 50% 50%) none s l), hsl(from hsl(120deg 50% 50%) h s l))', canonicalize('hsl(120deg 50% 50%)')],
Expand Down
Loading
Loading