From 458e8d8a61c6024a99bba0a19a1025819d602058 Mon Sep 17 00:00:00 2001 From: Romain Menke Date: Tue, 29 Aug 2023 12:09:58 +0200 Subject: [PATCH] css-color-parser : allow color channels to be normalized individually --- .../color-normalize-channel-values.d.ts | 4 +- .../hsl-normalize-channel-values.d.ts | 5 +- .../hwb-normalize-channel-values.d.ts | 3 +- .../lab-normalize-channel-values.d.ts | 3 +- .../lch-normalize-channel-values.d.ts | 3 +- .../functions/normalize-channel-values.d.ts | 3 +- .../oklab-normalize-channel-values.d.ts | 3 +- .../oklch-normalize-channel-values.d.ts | 3 +- .../rgb-normalize-channel-values.d.ts | 5 +- packages/css-color-parser/dist/index.cjs | 2 +- packages/css-color-parser/dist/index.mjs | 2 +- .../color-normalize-channel-values.ts | 111 ++++---- .../css-color-parser/src/functions/color.ts | 52 ++-- .../functions/hsl-normalize-channel-values.ts | 252 ++++++++---------- .../functions/hwb-normalize-channel-values.ts | 133 +++++---- .../functions/lab-normalize-channel-values.ts | 118 ++++---- .../functions/lch-normalize-channel-values.ts | 137 +++++----- .../src/functions/normalize-channel-values.ts | 3 +- .../oklab-normalize-channel-values.ts | 118 ++++---- .../oklch-normalize-channel-values.ts | 137 +++++----- .../functions/rgb-normalize-channel-values.ts | 205 ++++++-------- .../css-color-parser/src/functions/rgb.ts | 7 + .../functions/three-channel-legacy-syntax.ts | 47 ++-- .../three-channel-space-separated.ts | 52 ++-- .../test/wpt/color-mix-out-of-gamut.mjs | 35 +++ packages/css-color-parser/test/wpt/index.mjs | 1 + 26 files changed, 701 insertions(+), 743 deletions(-) create mode 100644 packages/css-color-parser/test/wpt/color-mix-out-of-gamut.mjs diff --git a/packages/css-color-parser/dist/functions/color-normalize-channel-values.d.ts b/packages/css-color-parser/dist/functions/color-normalize-channel-values.d.ts index bee5b4e37..51b6624d4 100644 --- a/packages/css-color-parser/dist/functions/color-normalize-channel-values.d.ts +++ b/packages/css-color-parser/dist/functions/color-normalize-channel-values.d.ts @@ -1,3 +1,3 @@ import type { ColorData } from '../color-data'; -import { CSSToken, TokenNumber } from '@csstools/css-tokenizer'; -export declare function normalize_Color_ChannelValues(tokens: Array, colorData: ColorData): Array | false; +import { CSSToken } from '@csstools/css-tokenizer'; +export declare function normalize_Color_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false; diff --git a/packages/css-color-parser/dist/functions/hsl-normalize-channel-values.d.ts b/packages/css-color-parser/dist/functions/hsl-normalize-channel-values.d.ts index d961bcc1b..068bcae7e 100644 --- a/packages/css-color-parser/dist/functions/hsl-normalize-channel-values.d.ts +++ b/packages/css-color-parser/dist/functions/hsl-normalize-channel-values.d.ts @@ -1,5 +1,4 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken } from '@csstools/css-tokenizer'; -export declare function normalize_legacy_HSL_ChannelValues(tokens: Array, colorData: ColorData): Array | false; -export declare function normalize_modern_HSL_ChannelValues(tokens: Array, colorData: ColorData): Array | false; +export declare function normalize_legacy_HSL_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false; +export declare function normalize_modern_HSL_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false; diff --git a/packages/css-color-parser/dist/functions/hwb-normalize-channel-values.d.ts b/packages/css-color-parser/dist/functions/hwb-normalize-channel-values.d.ts index 83dd448b0..81da6aacb 100644 --- a/packages/css-color-parser/dist/functions/hwb-normalize-channel-values.d.ts +++ b/packages/css-color-parser/dist/functions/hwb-normalize-channel-values.d.ts @@ -1,4 +1,3 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken } from '@csstools/css-tokenizer'; -export declare function normalize_HWB_ChannelValues(tokens: Array, colorData: ColorData): Array | false; +export declare function normalize_HWB_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false; diff --git a/packages/css-color-parser/dist/functions/lab-normalize-channel-values.d.ts b/packages/css-color-parser/dist/functions/lab-normalize-channel-values.d.ts index e279128e0..73587504c 100644 --- a/packages/css-color-parser/dist/functions/lab-normalize-channel-values.d.ts +++ b/packages/css-color-parser/dist/functions/lab-normalize-channel-values.d.ts @@ -1,4 +1,3 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken } from '@csstools/css-tokenizer'; -export declare function normalize_Lab_ChannelValues(tokens: Array, colorData: ColorData): Array | false; +export declare function normalize_Lab_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false; diff --git a/packages/css-color-parser/dist/functions/lch-normalize-channel-values.d.ts b/packages/css-color-parser/dist/functions/lch-normalize-channel-values.d.ts index fbc071756..a2227e446 100644 --- a/packages/css-color-parser/dist/functions/lch-normalize-channel-values.d.ts +++ b/packages/css-color-parser/dist/functions/lch-normalize-channel-values.d.ts @@ -1,4 +1,3 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken } from '@csstools/css-tokenizer'; -export declare function normalize_LCH_ChannelValues(tokens: Array, colorData: ColorData): Array | false; +export declare function normalize_LCH_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false; diff --git a/packages/css-color-parser/dist/functions/normalize-channel-values.d.ts b/packages/css-color-parser/dist/functions/normalize-channel-values.d.ts index ff309d6a6..c32172fdf 100644 --- a/packages/css-color-parser/dist/functions/normalize-channel-values.d.ts +++ b/packages/css-color-parser/dist/functions/normalize-channel-values.d.ts @@ -1,4 +1,3 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken } from '@csstools/css-tokenizer'; -export type normalizeChannelValuesFn = (tokens: Array, colorData: ColorData) => Array | false; +export type normalizeChannelValuesFn = (token: CSSToken, index: number, colorData: ColorData) => CSSToken | false; diff --git a/packages/css-color-parser/dist/functions/oklab-normalize-channel-values.d.ts b/packages/css-color-parser/dist/functions/oklab-normalize-channel-values.d.ts index a9c55b2b7..97b827928 100644 --- a/packages/css-color-parser/dist/functions/oklab-normalize-channel-values.d.ts +++ b/packages/css-color-parser/dist/functions/oklab-normalize-channel-values.d.ts @@ -1,4 +1,3 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken } from '@csstools/css-tokenizer'; -export declare function normalize_OKLab_ChannelValues(tokens: Array, colorData: ColorData): Array | false; +export declare function normalize_OKLab_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false; diff --git a/packages/css-color-parser/dist/functions/oklch-normalize-channel-values.d.ts b/packages/css-color-parser/dist/functions/oklch-normalize-channel-values.d.ts index c50f38eda..afd514b38 100644 --- a/packages/css-color-parser/dist/functions/oklch-normalize-channel-values.d.ts +++ b/packages/css-color-parser/dist/functions/oklch-normalize-channel-values.d.ts @@ -1,4 +1,3 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken } from '@csstools/css-tokenizer'; -export declare function normalize_OKLCH_ChannelValues(tokens: Array, colorData: ColorData): Array | false; +export declare function normalize_OKLCH_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false; diff --git a/packages/css-color-parser/dist/functions/rgb-normalize-channel-values.d.ts b/packages/css-color-parser/dist/functions/rgb-normalize-channel-values.d.ts index 8e0176423..eb3e89bcf 100644 --- a/packages/css-color-parser/dist/functions/rgb-normalize-channel-values.d.ts +++ b/packages/css-color-parser/dist/functions/rgb-normalize-channel-values.d.ts @@ -1,5 +1,4 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken } from '@csstools/css-tokenizer'; -export declare function normalize_legacy_sRGB_ChannelValues(tokens: Array, colorData: ColorData): Array | false; -export declare function normalize_modern_sRGB_ChannelValues(tokens: Array, colorData: ColorData): Array | false; +export declare function normalize_legacy_sRGB_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false; +export declare function normalize_modern_sRGB_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false; diff --git a/packages/css-color-parser/dist/index.cjs b/packages/css-color-parser/dist/index.cjs index 3b7876936..c2df993cc 100644 --- a/packages/css-color-parser/dist/index.cjs +++ b/packages/css-color-parser/dist/index.cjs @@ -1 +1 @@ -"use strict";var e,o,a=require("@csstools/css-tokenizer"),n=require("@csstools/color-helpers"),t=require("@csstools/css-parser-algorithms"),r=require("@csstools/css-calc");function colorData_to_XYZ_D50(e){switch(e.colorNotation){case exports.ColorNotation.HEX:case exports.ColorNotation.RGB:case exports.ColorNotation.sRGB:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.sRGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.Linear_sRGB:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.lin_sRGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.Display_P3:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.P3_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.Rec2020:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.rec_2020_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.A98_RGB:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.a98_RGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.ProPhoto_RGB:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.ProPhoto_RGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.HSL:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.HSL_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.HWB:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.HWB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.Lab:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.Lab_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.OKLab:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.OKLab_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.LCH:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.LCH_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.OKLCH:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.OKLCH_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.XYZ_D50:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.XYZ_D50_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.XYZ_D65:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.XYZ_D65_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};default:throw new Error("Unsupported color notation")}}exports.ColorNotation=void 0,(e=exports.ColorNotation||(exports.ColorNotation={})).A98_RGB="a98-rgb",e.Display_P3="display-p3",e.HEX="hex",e.HSL="hsl",e.HWB="hwb",e.LCH="lch",e.Lab="lab",e.Linear_sRGB="srgb-linear",e.OKLCH="oklch",e.OKLab="oklab",e.ProPhoto_RGB="prophoto-rgb",e.RGB="rgb",e.sRGB="srgb",e.Rec2020="rec2020",e.XYZ_D50="xyz-d50",e.XYZ_D65="xyz-d65",exports.SyntaxFlag=void 0,(o=exports.SyntaxFlag||(exports.SyntaxFlag={})).ColorKeyword="color-keyword",o.HasAlpha="has-alpha",o.HasDimensionValues="has-dimension-values",o.HasNoneKeywords="has-none-keywords",o.HasNumberValues="has-number-values",o.HasPercentageAlpha="has-percentage-alpha",o.HasPercentageValues="has-percentage-values",o.HasVariableAlpha="has-variable-alpha",o.Hex="hex",o.LegacyHSL="legacy-hsl",o.LegacyRGB="legacy-rgb",o.NamedColor="named-color",o.RelativeColorSyntax="relative-color-syntax",o.ColorMix="color-mix";const s=new Set([exports.ColorNotation.A98_RGB,exports.ColorNotation.Display_P3,exports.ColorNotation.HEX,exports.ColorNotation.Linear_sRGB,exports.ColorNotation.ProPhoto_RGB,exports.ColorNotation.RGB,exports.ColorNotation.sRGB,exports.ColorNotation.Rec2020,exports.ColorNotation.XYZ_D50,exports.ColorNotation.XYZ_D65]);function colorDataTo(e,o){const a={...e};if(e.colorNotation!==o){const e=colorData_to_XYZ_D50(a);switch(o){case exports.ColorNotation.HEX:case exports.ColorNotation.RGB:a.colorNotation=exports.ColorNotation.RGB,a.channels=n.xyz.XYZ_D50_to_sRGB(e.channels);break;case exports.ColorNotation.sRGB:a.colorNotation=exports.ColorNotation.sRGB,a.channels=n.xyz.XYZ_D50_to_sRGB(e.channels);break;case exports.ColorNotation.Linear_sRGB:a.colorNotation=exports.ColorNotation.Linear_sRGB,a.channels=n.xyz.XYZ_D50_to_lin_sRGB(e.channels);break;case exports.ColorNotation.Display_P3:a.colorNotation=exports.ColorNotation.Display_P3,a.channels=n.xyz.XYZ_D50_to_P3(e.channels);break;case exports.ColorNotation.Rec2020:a.colorNotation=exports.ColorNotation.Rec2020,a.channels=n.xyz.XYZ_D50_to_rec_2020(e.channels);break;case exports.ColorNotation.ProPhoto_RGB:a.colorNotation=exports.ColorNotation.ProPhoto_RGB,a.channels=n.xyz.XYZ_D50_to_ProPhoto(e.channels);break;case exports.ColorNotation.A98_RGB:a.colorNotation=exports.ColorNotation.A98_RGB,a.channels=n.xyz.XYZ_D50_to_a98_RGB(e.channels);break;case exports.ColorNotation.HSL:a.colorNotation=exports.ColorNotation.HSL,a.channels=n.xyz.XYZ_D50_to_HSL(e.channels);break;case exports.ColorNotation.HWB:a.colorNotation=exports.ColorNotation.HWB,a.channels=n.xyz.XYZ_D50_to_HWB(e.channels);break;case exports.ColorNotation.Lab:a.colorNotation=exports.ColorNotation.Lab,a.channels=n.xyz.XYZ_D50_to_Lab(e.channels);break;case exports.ColorNotation.LCH:a.colorNotation=exports.ColorNotation.LCH,a.channels=n.xyz.XYZ_D50_to_LCH(e.channels);break;case exports.ColorNotation.OKLCH:a.colorNotation=exports.ColorNotation.OKLCH,a.channels=n.xyz.XYZ_D50_to_OKLCH(e.channels);break;case exports.ColorNotation.OKLab:a.colorNotation=exports.ColorNotation.OKLab,a.channels=n.xyz.XYZ_D50_to_OKLab(e.channels);break;case exports.ColorNotation.XYZ_D50:a.colorNotation=exports.ColorNotation.XYZ_D50,a.channels=n.xyz.XYZ_D50_to_XYZ_D50(e.channels);break;case exports.ColorNotation.XYZ_D65:a.colorNotation=exports.ColorNotation.XYZ_D65,a.channels=n.xyz.XYZ_D50_to_XYZ_D65(e.channels);break;default:throw new Error("Unsupported color notation")}}else a.channels=e.channels.map((e=>Number.isNaN(e)?0:e));if(o===e.colorNotation)a.channels=carryForwardMissingComponents(e.channels,[0,1,2],a.channels,[0,1,2]);else if(s.has(o)&&s.has(e.colorNotation))a.channels=carryForwardMissingComponents(e.channels,[0,1,2],a.channels,[0,1,2]);else switch(o){case exports.ColorNotation.HSL:switch(e.colorNotation){case exports.ColorNotation.HWB:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[0]);break;case exports.ColorNotation.Lab:case exports.ColorNotation.OKLab:a.channels=carryForwardMissingComponents(e.channels,[2],a.channels,[0]);break;case exports.ColorNotation.LCH:case exports.ColorNotation.OKLCH:a.channels=carryForwardMissingComponents(e.channels,[0,1,2],a.channels,[2,1,0])}break;case exports.ColorNotation.HWB:switch(e.colorNotation){case exports.ColorNotation.HSL:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[0]);break;case exports.ColorNotation.LCH:case exports.ColorNotation.OKLCH:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[2])}break;case exports.ColorNotation.Lab:case exports.ColorNotation.OKLab:switch(e.colorNotation){case exports.ColorNotation.HSL:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[2]);break;case exports.ColorNotation.Lab:case exports.ColorNotation.OKLab:a.channels=carryForwardMissingComponents(e.channels,[0,1,2],a.channels,[0,1,2]);break;case exports.ColorNotation.LCH:case exports.ColorNotation.OKLCH:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[0])}break;case exports.ColorNotation.LCH:case exports.ColorNotation.OKLCH:switch(e.colorNotation){case exports.ColorNotation.HSL:a.channels=carryForwardMissingComponents(e.channels,[0,1,2],a.channels,[2,1,0]);break;case exports.ColorNotation.HWB:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[2]);break;case exports.ColorNotation.Lab:case exports.ColorNotation.OKLab:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[0]);break;case exports.ColorNotation.LCH:case exports.ColorNotation.OKLCH:a.channels=carryForwardMissingComponents(e.channels,[0,1,2],a.channels,[0,1,2])}}return a.channels=convertPowerlessComponentsToMissingComponents(a.channels,o),a}function convertPowerlessComponentsToMissingComponents(e,o){const a=[...e];switch(o){case exports.ColorNotation.HSL:reducePrecision(a[1],4)<=0&&(a[0]=NaN);break;case exports.ColorNotation.HWB:Math.max(0,reducePrecision(a[1],4))+Math.max(0,reducePrecision(a[2],4))>=100&&(a[0]=NaN);break;case exports.ColorNotation.LCH:reducePrecision(a[1],4)<=0&&(a[2]=NaN);break;case exports.ColorNotation.OKLCH:reducePrecision(a[1],6)<=0&&(a[2]=NaN)}return a}function convertPowerlessComponentsToZeroValuesForDisplay(e,o){const a=[...e];switch(o){case exports.ColorNotation.HSL:(reducePrecision(a[2])<=0||reducePrecision(a[2])>=100)&&(a[0]=NaN,a[1]=NaN),reducePrecision(a[1])<=0&&(a[0]=NaN);break;case exports.ColorNotation.HWB:Math.max(0,reducePrecision(a[1]))+Math.max(0,reducePrecision(a[2]))>=100&&(a[0]=NaN);break;case exports.ColorNotation.Lab:(reducePrecision(a[0])<=0||reducePrecision(a[0])>=100)&&(a[1]=NaN,a[2]=NaN);break;case exports.ColorNotation.LCH:reducePrecision(a[1])<=0&&(a[2]=NaN),(reducePrecision(a[0])<=0||reducePrecision(a[0])>=100)&&(a[1]=NaN,a[2]=NaN);break;case exports.ColorNotation.OKLab:(reducePrecision(a[0])<=0||reducePrecision(a[0])>=1)&&(a[1]=NaN,a[2]=NaN);break;case exports.ColorNotation.OKLCH:reducePrecision(a[1])<=0&&(a[2]=NaN),(reducePrecision(a[0])<=0||reducePrecision(a[0])>=1)&&(a[1]=NaN,a[2]=NaN)}return a}function carryForwardMissingComponents(e,o,a,n){const t=[...a];for(const a of o)Number.isNaN(e[o[a]])&&(t[n[a]]=NaN);return t}function normalizeRelativeColorDataChannels(e){const o=new Map;switch(e.colorNotation){case exports.ColorNotation.RGB:case exports.ColorNotation.HEX:o.set("r",dummyNumberToken(255*e.channels[0])),o.set("g",dummyNumberToken(255*e.channels[1])),o.set("b",dummyNumberToken(255*e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha));break;case exports.ColorNotation.HSL:o.set("h",dummyNumberToken(e.channels[0])),o.set("s",dummyNumberToken(e.channels[1])),o.set("l",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha));break;case exports.ColorNotation.HWB:o.set("h",dummyNumberToken(e.channels[0])),o.set("w",dummyNumberToken(e.channels[1])),o.set("b",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha));break;case exports.ColorNotation.Lab:case exports.ColorNotation.OKLab:o.set("l",dummyNumberToken(e.channels[0])),o.set("a",dummyNumberToken(e.channels[1])),o.set("b",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha));break;case exports.ColorNotation.LCH:case exports.ColorNotation.OKLCH:o.set("l",dummyNumberToken(e.channels[0])),o.set("c",dummyNumberToken(e.channels[1])),o.set("h",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha));break;case exports.ColorNotation.sRGB:case exports.ColorNotation.A98_RGB:case exports.ColorNotation.Display_P3:case exports.ColorNotation.Rec2020:case exports.ColorNotation.Linear_sRGB:case exports.ColorNotation.ProPhoto_RGB:o.set("r",dummyNumberToken(e.channels[0])),o.set("g",dummyNumberToken(e.channels[1])),o.set("b",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha));break;case exports.ColorNotation.XYZ_D50:case exports.ColorNotation.XYZ_D65:o.set("x",dummyNumberToken(e.channels[0])),o.set("y",dummyNumberToken(e.channels[1])),o.set("z",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha))}return o}function noneToZeroInRelativeColorDataChannels(e){const o=new Map;for(const[a,n]of e)Number.isNaN(n[4].value)?o.set(a,dummyNumberToken(0)):o.set(a,n);return o}function dummyNumberToken(e){return[a.TokenType.Number,e.toString(),-1,-1,{value:e,type:a.NumberType.Number}]}function reducePrecision(e,o=7){if(Number.isNaN(e))return 0;const a=Math.pow(10,o);return Math.round(e*a)/a}function normalize(e,o,a,n){return Math.min(Math.max(e/o,a),n)}const l=/[A-Z]/g;function toLowerCaseAZ(e){return e.replace(l,(e=>String.fromCharCode(e.charCodeAt(0)+32)))}function normalize_Color_ChannelValues(e,o){const n=[];for(let t=0;t=0){i=u.value[4].value;continue}}return!1}if(!l)return!1;n.push({color:l,percentage:i}),l=!1,i=!1}}if(l&&n.push({color:l,percentage:i}),2!==n.length)return!1;let u=n[0].percentage,c=n[1].percentage;return(!1===u||!(u<0||u>100))&&((!1===c||!(c<0||c>100))&&(!1===u&&!1===c?(u=50,c=50):!1!==u&&!1===c?c=100-u:!1===u&&!1!==c&&(u=100-c),(0!==u||0!==c)&&(!1!==u&&!1!==c&&(u+c>100&&(u=u/(u+c)*100,c=c/(u+c)*100),u+c<100&&(s=(u+c)/100,u=u/(u+c)*100,c=c/(u+c)*100),{a:{color:n[0].color,percentage:u},b:{color:n[1].color,percentage:c},alphaMultiplier:s}))))}function colorMixRectangular(e,o){if(!o)return!1;const a=o.a.color,n=o.b.color,t=o.a.percentage/100;let r=a.channels,s=n.channels,l=exports.ColorNotation.RGB,i=a.alpha;if("number"!=typeof i)return!1;let u=n.alpha;if("number"!=typeof u)return!1;switch(i=Number.isNaN(i)?u:i,u=Number.isNaN(u)?i:u,e){case"srgb":l=exports.ColorNotation.RGB;break;case"srgb-linear":l=exports.ColorNotation.Linear_sRGB;break;case"lab":l=exports.ColorNotation.Lab;break;case"oklab":l=exports.ColorNotation.OKLab;break;case"xyz-d50":l=exports.ColorNotation.XYZ_D50;break;case"xyz":case"xyz-d65":l=exports.ColorNotation.XYZ_D65}r=colorDataTo(a,l).channels,s=colorDataTo(n,l).channels,r[0]=premultiply(r[0],i),r[1]=premultiply(r[1],i),r[2]=premultiply(r[2],i),s[0]=premultiply(s[0],u),s[1]=premultiply(s[1],u),s[2]=premultiply(s[2],u);const c=interpolate(i,u,t);return{colorNotation:l,channels:[un_premultiply(interpolate(r[0],s[0],t),c),un_premultiply(interpolate(r[1],s[1],t),c),un_premultiply(interpolate(r[2],s[2],t),c)],alpha:c*o.alphaMultiplier,syntaxFlags:new Set([exports.SyntaxFlag.ColorMix])}}function colorMixPolar(e,o,a){if(!a)return!1;const n=a.a.color,t=a.b.color,r=a.a.percentage/100;let s=n.channels,l=t.channels,i=0,u=0,c=0,p=0,N=0,m=0,h=exports.ColorNotation.RGB,y=n.alpha;if("number"!=typeof y)return!1;let x=t.alpha;if("number"!=typeof x)return!1;switch(y=Number.isNaN(y)?x:y,x=Number.isNaN(x)?y:x,e){case"hsl":h=exports.ColorNotation.HSL;break;case"hwb":h=exports.ColorNotation.HWB;break;case"lch":h=exports.ColorNotation.LCH;break;case"oklch":h=exports.ColorNotation.OKLCH}switch(s=colorDataTo(n,h).channels,l=colorDataTo(t,h).channels,e){case"hsl":case"hwb":i=s[0],u=l[0],c=s[1],p=l[1],N=s[2],m=l[2];break;case"lch":case"oklch":c=s[0],p=l[0],N=s[1],m=l[1],i=s[2],u=l[2]}if(!Number.isNaN(i)&&!Number.isNaN(u)){const e=u-i;switch(o){case"shorter":e>180?i+=360:e<-180&&(u+=360);break;case"longer":-1800?i+=360:u+=360);break;case"increasing":e<0&&(u+=360);break;case"decreasing":e>0&&(i+=360);break;default:throw new Error("Unknown hue interpolation method")}}c=premultiply(c,y),N=premultiply(N,y),p=premultiply(p,x),m=premultiply(m,x);let b=[0,0,0];const T=interpolate(y,x,r);switch(e){case"hsl":case"hwb":b=[interpolate(i,u,r),un_premultiply(interpolate(c,p,r),T),un_premultiply(interpolate(N,m,r),T)];break;case"lch":case"oklch":b=[un_premultiply(interpolate(c,p,r),T),un_premultiply(interpolate(N,m,r),T),interpolate(i,u,r)]}return{colorNotation:h,channels:b,alpha:T*a.alphaMultiplier,syntaxFlags:new Set([exports.SyntaxFlag.ColorMix])}}function interpolate(e,o,a){return Number.isNaN(e)?o:Number.isNaN(o)?e:e*a+o*(1-a)}function premultiply(e,o){return Number.isNaN(o)?e:Number.isNaN(e)?NaN:e*o}function un_premultiply(e,o){return 0===o||Number.isNaN(o)?e:Number.isNaN(e)?NaN:e/o}function hex(e){const o=toLowerCaseAZ(e[4].value);if(o.match(/[^a-f0-9]/))return!1;const a={colorNotation:exports.ColorNotation.HEX,channels:[0,0,0],alpha:1,syntaxFlags:new Set([exports.SyntaxFlag.Hex])},n=o.length;if(3===n){const e=o[0],n=o[1],t=o[2];return a.channels=[parseInt(e+e,16)/255,parseInt(n+n,16)/255,parseInt(t+t,16)/255],a}if(6===n){const e=o[0]+o[1],n=o[2]+o[3],t=o[4]+o[5];return a.channels=[parseInt(e,16)/255,parseInt(n,16)/255,parseInt(t,16)/255],a}if(4===n){const e=o[0],n=o[1],t=o[2],r=o[3];return a.channels=[parseInt(e+e,16)/255,parseInt(n+n,16)/255,parseInt(t+t,16)/255],a.alpha=parseInt(r+r,16)/255,a.syntaxFlags.add(exports.SyntaxFlag.HasAlpha),a}if(8===n){const e=o[0]+o[1],n=o[2]+o[3],t=o[4]+o[5],r=o[6]+o[7];return a.channels=[parseInt(e,16)/255,parseInt(n,16)/255,parseInt(t,16)/255],a.alpha=parseInt(r,16)/255,a.syntaxFlags.add(exports.SyntaxFlag.HasAlpha),a}return!1}function normalizeHue(e){if(e[0]===a.TokenType.Number)return e[4].value=e[4].value%360,e[1]=e[4].value.toString(),e;if(e[0]===a.TokenType.Dimension){let o=e[4].value;switch(toLowerCaseAZ(e[4].unit)){case"deg":break;case"rad":o=180*e[4].value/Math.PI;break;case"grad":o=.9*e[4].value;break;case"turn":o=360*e[4].value;break;default:return!1}return o%=360,[a.TokenType.Number,o.toString(),e[2],e[3],{value:o,type:a.NumberType.Number}]}return!1}function normalize_legacy_HSL_ChannelValues(e,o){const n=[];for(let t=0;t.999999&&(a=[1,0,0]),n.calculations.mapGamut(a,(e=>(e=n.conversions.OKLCH_to_OKLab(e),e=n.conversions.OKLab_to_XYZ(e),e=n.conversions.XYZ_to_lin_sRGB(e),n.conversions.gam_sRGB(e))),(e=>(e=n.conversions.lin_sRGB(e),e=n.conversions.lin_sRGB_to_XYZ(e),e=n.conversions.XYZ_to_OKLab(e),n.conversions.OKLab_to_OKLCH(e))))}function threeChannelSpaceSeparated(e,o,s,l,i){const u=toLowerCaseAZ(e.getName()),c=[],p=[],N=[],m=[];let h,y,x=!1;const b={colorNotation:s,channels:[0,0,0],alpha:1,syntaxFlags:new Set(l)};let T=c;for(let o=0;ot.isTokenNode(e)&&e.value[0]===a.TokenType.Comma))){const o=hslCommaSeparated(e);if(!1!==o)return o}{const a=hslSpaceSeparated(e,o);if(!1!==a)return a}return!1}function hslCommaSeparated(e){return threeChannelLegacySyntax(e,normalize_legacy_HSL_ChannelValues,exports.ColorNotation.HSL,[exports.SyntaxFlag.LegacyHSL])}function hslSpaceSeparated(e,o){return threeChannelSpaceSeparated(e,normalize_modern_HSL_ChannelValues,exports.ColorNotation.HSL,[],o)}function normalize_HWB_ChannelValues(e,o){const n=[];for(let t=0;tt.isTokenNode(e)&&e.value[0]===a.TokenType.Comma))){const o=rgbCommaSeparated(e);if(!1!==o)return o}else{const a=rgbSpaceSeparated(e,o);if(!1!==a)return a}return!1}function rgbCommaSeparated(e){return threeChannelLegacySyntax(e,normalize_legacy_sRGB_ChannelValues,exports.ColorNotation.RGB,[exports.SyntaxFlag.LegacyRGB])}function rgbSpaceSeparated(e,o){return threeChannelSpaceSeparated(e,normalize_modern_sRGB_ChannelValues,exports.ColorNotation.RGB,[],o)}function toPrecision(e,o=7){e=+e,o=+o;const a=(Math.floor(e)+"").length;if(o>a)return+e.toFixed(o-a);{const n=10**(a-o);return Math.round(e/n)*n}}function XYZ_D50_to_P3_Gamut(e){const o=n.xyz.XYZ_D50_to_P3(e);if(n.utils.inGamut(o))return n.utils.clip(o);let a=e.slice();return a=n.conversions.D50_to_D65(a),a=n.conversions.XYZ_to_OKLab(a),a=n.conversions.OKLab_to_OKLCH(a),a[0]<1e-6&&(a=[0,0,0]),a[0]>.999999&&(a=[1,0,0]),n.calculations.mapGamut(a,(e=>(e=n.conversions.OKLCH_to_OKLab(e),e=n.conversions.OKLab_to_XYZ(e),e=n.conversions.XYZ_to_lin_P3(e),n.conversions.gam_P3(e))),(e=>(e=n.conversions.lin_P3(e),e=n.conversions.lin_P3_to_XYZ(e),e=n.conversions.XYZ_to_OKLab(e),n.conversions.OKLab_to_OKLCH(e))))}function serializeWithAlpha(e,o,n,r){const s=[a.TokenType.CloseParen,")",-1,-1,void 0];if("number"==typeof e.alpha){const l=Math.min(1,Math.max(0,toPrecision(Number.isNaN(e.alpha)?0:e.alpha)));return 1===toPrecision(l,4)?new t.FunctionNode(o,s,r):new t.FunctionNode(o,s,[...r,new t.WhitespaceNode([n]),new t.TokenNode([a.TokenType.Delim,"/",-1,-1,{value:"/"}]),new t.WhitespaceNode([n]),new t.TokenNode([a.TokenType.Number,toPrecision(l,4).toString(),-1,-1,{value:e.alpha,type:a.NumberType.Integer}])])}return new t.FunctionNode(o,s,[...r,new t.WhitespaceNode([n]),new t.TokenNode([a.TokenType.Delim,"/",-1,-1,{value:"/"}]),new t.WhitespaceNode([n]),e.alpha])}exports.color=function color(e){if(t.isFunctionNode(e)){switch(toLowerCaseAZ(e.getName())){case"rgb":case"rgba":return rgb(e,color);case"hsl":case"hsla":return hsl(e,color);case"hwb":return o=color,threeChannelSpaceSeparated(e,normalize_HWB_ChannelValues,exports.ColorNotation.HWB,[],o);case"lab":return lab(e,color);case"lch":return lch(e,color);case"oklab":return oklab(e,color);case"oklch":return oklch(e,color);case"color":return color$1(e,color);case"color-mix":return colorMix(e,color)}}var o;if(t.isTokenNode(e)){if(e.value[0]===a.TokenType.Hash)return hex(e.value);if(e.value[0]===a.TokenType.Ident){const o=namedColor(e.value[4].value);return!1!==o?o:"transparent"===toLowerCaseAZ(e.value[4].value)&&{colorNotation:exports.ColorNotation.RGB,channels:[0,0,0],alpha:0,syntaxFlags:new Set([exports.SyntaxFlag.ColorKeyword])}}}return!1},exports.colorDataFitsRGB_Gamut=function colorDataFitsRGB_Gamut(e){const o=JSON.parse(JSON.stringify(e));return o.channels=convertPowerlessComponentsToZeroValuesForDisplay(o.channels,o.colorNotation),!colorDataTo(o,exports.ColorNotation.RGB).channels.find((e=>e<-1e-5||e>1.00001))},exports.colorDataTo=colorDataTo,exports.serializeOKLCH=function serializeOKLCH(e){e.channels=convertPowerlessComponentsToZeroValuesForDisplay(e.channels,e.colorNotation);let o=e.channels.map((e=>Number.isNaN(e)?0:e));e.colorNotation!==exports.ColorNotation.OKLCH&&(o=n.xyz.XYZ_D50_to_OKLCH(colorData_to_XYZ_D50(e).channels));const r=toPrecision(o[0],6),s=toPrecision(o[1],6),l=toPrecision(o[2],6),i=[a.TokenType.Function,"oklch(",-1,-1,{value:"oklch"}],u=[a.TokenType.Whitespace," ",-1,-1,void 0];return serializeWithAlpha(e,i,u,[new t.TokenNode([a.TokenType.Number,r.toString(),-1,-1,{value:o[0],type:a.NumberType.Number}]),new t.WhitespaceNode([u]),new t.TokenNode([a.TokenType.Number,s.toString(),-1,-1,{value:o[1],type:a.NumberType.Number}]),new t.WhitespaceNode([u]),new t.TokenNode([a.TokenType.Number,l.toString(),-1,-1,{value:o[2],type:a.NumberType.Number}])])},exports.serializeP3=function serializeP3(e,o=!0){e.channels=convertPowerlessComponentsToZeroValuesForDisplay(e.channels,e.colorNotation);let r=e.channels.map((e=>Number.isNaN(e)?0:e));e.colorNotation!==exports.ColorNotation.Display_P3&&(r=o?XYZ_D50_to_P3_Gamut(colorData_to_XYZ_D50(e).channels):n.xyz.XYZ_D50_to_P3(colorData_to_XYZ_D50(e).channels));const s=toPrecision(r[0],6),l=toPrecision(r[1],6),i=toPrecision(r[2],6),u=[a.TokenType.Function,"color(",-1,-1,{value:"color"}],c=[a.TokenType.Whitespace," ",-1,-1,void 0];return serializeWithAlpha(e,u,c,[new t.TokenNode([a.TokenType.Ident,"display-p3",-1,-1,{value:"display-p3"}]),new t.WhitespaceNode([c]),new t.TokenNode([a.TokenType.Number,s.toString(),-1,-1,{value:r[0],type:a.NumberType.Number}]),new t.WhitespaceNode([c]),new t.TokenNode([a.TokenType.Number,l.toString(),-1,-1,{value:r[1],type:a.NumberType.Number}]),new t.WhitespaceNode([c]),new t.TokenNode([a.TokenType.Number,i.toString(),-1,-1,{value:r[2],type:a.NumberType.Number}])])},exports.serializeRGB=function serializeRGB(e,o=!0){e.channels=convertPowerlessComponentsToZeroValuesForDisplay(e.channels,e.colorNotation);let r=e.channels.map((e=>Number.isNaN(e)?0:e));e.colorNotation===exports.ColorNotation.HWB?r=n.conversions.HWB_to_sRGB(r):e.colorNotation===exports.ColorNotation.HSL?r=n.conversions.HSL_to_sRGB(r):e.colorNotation!==exports.ColorNotation.RGB&&e.colorNotation!==exports.ColorNotation.HEX&&(r=o?XYZ_D50_to_sRGB_Gamut(colorData_to_XYZ_D50(e).channels):n.xyz.XYZ_D50_to_sRGB(colorData_to_XYZ_D50(e).channels));const s=Math.min(255,Math.max(0,Math.round(255*toPrecision(r[0])))),l=Math.min(255,Math.max(0,Math.round(255*toPrecision(r[1])))),i=Math.min(255,Math.max(0,Math.round(255*toPrecision(r[2])))),u=[a.TokenType.CloseParen,")",-1,-1,void 0],c=[a.TokenType.Whitespace," ",-1,-1,void 0],p=[a.TokenType.Comma,",",-1,-1,void 0],N=[new t.TokenNode([a.TokenType.Number,s.toString(),-1,-1,{value:r[0],type:a.NumberType.Integer}]),new t.TokenNode(p),new t.WhitespaceNode([c]),new t.TokenNode([a.TokenType.Number,l.toString(),-1,-1,{value:r[1],type:a.NumberType.Integer}]),new t.TokenNode(p),new t.WhitespaceNode([c]),new t.TokenNode([a.TokenType.Number,i.toString(),-1,-1,{value:r[2],type:a.NumberType.Integer}])];if("number"==typeof e.alpha){const o=Math.min(1,Math.max(0,toPrecision(Number.isNaN(e.alpha)?0:e.alpha)));return 1===toPrecision(o,4)?new t.FunctionNode([a.TokenType.Function,"rgb(",-1,-1,{value:"rgb"}],u,N):new t.FunctionNode([a.TokenType.Function,"rgba(",-1,-1,{value:"rgba"}],u,[...N,new t.TokenNode(p),new t.WhitespaceNode([c]),new t.TokenNode([a.TokenType.Number,toPrecision(o,4).toString(),-1,-1,{value:e.alpha,type:a.NumberType.Number}])])}return new t.FunctionNode([a.TokenType.Function,"rgba(",-1,-1,{value:"rgba"}],u,[...N,new t.TokenNode(p),new t.WhitespaceNode([c]),e.alpha])}; +"use strict";var e,o,a=require("@csstools/css-tokenizer"),n=require("@csstools/color-helpers"),t=require("@csstools/css-parser-algorithms"),r=require("@csstools/css-calc");function colorData_to_XYZ_D50(e){switch(e.colorNotation){case exports.ColorNotation.HEX:case exports.ColorNotation.RGB:case exports.ColorNotation.sRGB:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.sRGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.Linear_sRGB:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.lin_sRGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.Display_P3:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.P3_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.Rec2020:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.rec_2020_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.A98_RGB:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.a98_RGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.ProPhoto_RGB:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.ProPhoto_RGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.HSL:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.HSL_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.HWB:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.HWB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.Lab:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.Lab_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.OKLab:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.OKLab_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.LCH:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.LCH_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.OKLCH:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.OKLCH_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.XYZ_D50:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.XYZ_D50_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case exports.ColorNotation.XYZ_D65:return{...e,colorNotation:exports.ColorNotation.XYZ_D50,channels:n.xyz.XYZ_D65_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};default:throw new Error("Unsupported color notation")}}exports.ColorNotation=void 0,(e=exports.ColorNotation||(exports.ColorNotation={})).A98_RGB="a98-rgb",e.Display_P3="display-p3",e.HEX="hex",e.HSL="hsl",e.HWB="hwb",e.LCH="lch",e.Lab="lab",e.Linear_sRGB="srgb-linear",e.OKLCH="oklch",e.OKLab="oklab",e.ProPhoto_RGB="prophoto-rgb",e.RGB="rgb",e.sRGB="srgb",e.Rec2020="rec2020",e.XYZ_D50="xyz-d50",e.XYZ_D65="xyz-d65",exports.SyntaxFlag=void 0,(o=exports.SyntaxFlag||(exports.SyntaxFlag={})).ColorKeyword="color-keyword",o.HasAlpha="has-alpha",o.HasDimensionValues="has-dimension-values",o.HasNoneKeywords="has-none-keywords",o.HasNumberValues="has-number-values",o.HasPercentageAlpha="has-percentage-alpha",o.HasPercentageValues="has-percentage-values",o.HasVariableAlpha="has-variable-alpha",o.Hex="hex",o.LegacyHSL="legacy-hsl",o.LegacyRGB="legacy-rgb",o.NamedColor="named-color",o.RelativeColorSyntax="relative-color-syntax",o.ColorMix="color-mix";const s=new Set([exports.ColorNotation.A98_RGB,exports.ColorNotation.Display_P3,exports.ColorNotation.HEX,exports.ColorNotation.Linear_sRGB,exports.ColorNotation.ProPhoto_RGB,exports.ColorNotation.RGB,exports.ColorNotation.sRGB,exports.ColorNotation.Rec2020,exports.ColorNotation.XYZ_D50,exports.ColorNotation.XYZ_D65]);function colorDataTo(e,o){const a={...e};if(e.colorNotation!==o){const e=colorData_to_XYZ_D50(a);switch(o){case exports.ColorNotation.HEX:case exports.ColorNotation.RGB:a.colorNotation=exports.ColorNotation.RGB,a.channels=n.xyz.XYZ_D50_to_sRGB(e.channels);break;case exports.ColorNotation.sRGB:a.colorNotation=exports.ColorNotation.sRGB,a.channels=n.xyz.XYZ_D50_to_sRGB(e.channels);break;case exports.ColorNotation.Linear_sRGB:a.colorNotation=exports.ColorNotation.Linear_sRGB,a.channels=n.xyz.XYZ_D50_to_lin_sRGB(e.channels);break;case exports.ColorNotation.Display_P3:a.colorNotation=exports.ColorNotation.Display_P3,a.channels=n.xyz.XYZ_D50_to_P3(e.channels);break;case exports.ColorNotation.Rec2020:a.colorNotation=exports.ColorNotation.Rec2020,a.channels=n.xyz.XYZ_D50_to_rec_2020(e.channels);break;case exports.ColorNotation.ProPhoto_RGB:a.colorNotation=exports.ColorNotation.ProPhoto_RGB,a.channels=n.xyz.XYZ_D50_to_ProPhoto(e.channels);break;case exports.ColorNotation.A98_RGB:a.colorNotation=exports.ColorNotation.A98_RGB,a.channels=n.xyz.XYZ_D50_to_a98_RGB(e.channels);break;case exports.ColorNotation.HSL:a.colorNotation=exports.ColorNotation.HSL,a.channels=n.xyz.XYZ_D50_to_HSL(e.channels);break;case exports.ColorNotation.HWB:a.colorNotation=exports.ColorNotation.HWB,a.channels=n.xyz.XYZ_D50_to_HWB(e.channels);break;case exports.ColorNotation.Lab:a.colorNotation=exports.ColorNotation.Lab,a.channels=n.xyz.XYZ_D50_to_Lab(e.channels);break;case exports.ColorNotation.LCH:a.colorNotation=exports.ColorNotation.LCH,a.channels=n.xyz.XYZ_D50_to_LCH(e.channels);break;case exports.ColorNotation.OKLCH:a.colorNotation=exports.ColorNotation.OKLCH,a.channels=n.xyz.XYZ_D50_to_OKLCH(e.channels);break;case exports.ColorNotation.OKLab:a.colorNotation=exports.ColorNotation.OKLab,a.channels=n.xyz.XYZ_D50_to_OKLab(e.channels);break;case exports.ColorNotation.XYZ_D50:a.colorNotation=exports.ColorNotation.XYZ_D50,a.channels=n.xyz.XYZ_D50_to_XYZ_D50(e.channels);break;case exports.ColorNotation.XYZ_D65:a.colorNotation=exports.ColorNotation.XYZ_D65,a.channels=n.xyz.XYZ_D50_to_XYZ_D65(e.channels);break;default:throw new Error("Unsupported color notation")}}else a.channels=e.channels.map((e=>Number.isNaN(e)?0:e));if(o===e.colorNotation)a.channels=carryForwardMissingComponents(e.channels,[0,1,2],a.channels,[0,1,2]);else if(s.has(o)&&s.has(e.colorNotation))a.channels=carryForwardMissingComponents(e.channels,[0,1,2],a.channels,[0,1,2]);else switch(o){case exports.ColorNotation.HSL:switch(e.colorNotation){case exports.ColorNotation.HWB:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[0]);break;case exports.ColorNotation.Lab:case exports.ColorNotation.OKLab:a.channels=carryForwardMissingComponents(e.channels,[2],a.channels,[0]);break;case exports.ColorNotation.LCH:case exports.ColorNotation.OKLCH:a.channels=carryForwardMissingComponents(e.channels,[0,1,2],a.channels,[2,1,0])}break;case exports.ColorNotation.HWB:switch(e.colorNotation){case exports.ColorNotation.HSL:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[0]);break;case exports.ColorNotation.LCH:case exports.ColorNotation.OKLCH:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[2])}break;case exports.ColorNotation.Lab:case exports.ColorNotation.OKLab:switch(e.colorNotation){case exports.ColorNotation.HSL:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[2]);break;case exports.ColorNotation.Lab:case exports.ColorNotation.OKLab:a.channels=carryForwardMissingComponents(e.channels,[0,1,2],a.channels,[0,1,2]);break;case exports.ColorNotation.LCH:case exports.ColorNotation.OKLCH:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[0])}break;case exports.ColorNotation.LCH:case exports.ColorNotation.OKLCH:switch(e.colorNotation){case exports.ColorNotation.HSL:a.channels=carryForwardMissingComponents(e.channels,[0,1,2],a.channels,[2,1,0]);break;case exports.ColorNotation.HWB:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[2]);break;case exports.ColorNotation.Lab:case exports.ColorNotation.OKLab:a.channels=carryForwardMissingComponents(e.channels,[0],a.channels,[0]);break;case exports.ColorNotation.LCH:case exports.ColorNotation.OKLCH:a.channels=carryForwardMissingComponents(e.channels,[0,1,2],a.channels,[0,1,2])}}return a.channels=convertPowerlessComponentsToMissingComponents(a.channels,o),a}function convertPowerlessComponentsToMissingComponents(e,o){const a=[...e];switch(o){case exports.ColorNotation.HSL:reducePrecision(a[1],4)<=0&&(a[0]=NaN);break;case exports.ColorNotation.HWB:Math.max(0,reducePrecision(a[1],4))+Math.max(0,reducePrecision(a[2],4))>=100&&(a[0]=NaN);break;case exports.ColorNotation.LCH:reducePrecision(a[1],4)<=0&&(a[2]=NaN);break;case exports.ColorNotation.OKLCH:reducePrecision(a[1],6)<=0&&(a[2]=NaN)}return a}function convertPowerlessComponentsToZeroValuesForDisplay(e,o){const a=[...e];switch(o){case exports.ColorNotation.HSL:(reducePrecision(a[2])<=0||reducePrecision(a[2])>=100)&&(a[0]=NaN,a[1]=NaN),reducePrecision(a[1])<=0&&(a[0]=NaN);break;case exports.ColorNotation.HWB:Math.max(0,reducePrecision(a[1]))+Math.max(0,reducePrecision(a[2]))>=100&&(a[0]=NaN);break;case exports.ColorNotation.Lab:(reducePrecision(a[0])<=0||reducePrecision(a[0])>=100)&&(a[1]=NaN,a[2]=NaN);break;case exports.ColorNotation.LCH:reducePrecision(a[1])<=0&&(a[2]=NaN),(reducePrecision(a[0])<=0||reducePrecision(a[0])>=100)&&(a[1]=NaN,a[2]=NaN);break;case exports.ColorNotation.OKLab:(reducePrecision(a[0])<=0||reducePrecision(a[0])>=1)&&(a[1]=NaN,a[2]=NaN);break;case exports.ColorNotation.OKLCH:reducePrecision(a[1])<=0&&(a[2]=NaN),(reducePrecision(a[0])<=0||reducePrecision(a[0])>=1)&&(a[1]=NaN,a[2]=NaN)}return a}function carryForwardMissingComponents(e,o,a,n){const t=[...a];for(const a of o)Number.isNaN(e[o[a]])&&(t[n[a]]=NaN);return t}function normalizeRelativeColorDataChannels(e){const o=new Map;switch(e.colorNotation){case exports.ColorNotation.RGB:case exports.ColorNotation.HEX:o.set("r",dummyNumberToken(255*e.channels[0])),o.set("g",dummyNumberToken(255*e.channels[1])),o.set("b",dummyNumberToken(255*e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha));break;case exports.ColorNotation.HSL:o.set("h",dummyNumberToken(e.channels[0])),o.set("s",dummyNumberToken(e.channels[1])),o.set("l",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha));break;case exports.ColorNotation.HWB:o.set("h",dummyNumberToken(e.channels[0])),o.set("w",dummyNumberToken(e.channels[1])),o.set("b",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha));break;case exports.ColorNotation.Lab:case exports.ColorNotation.OKLab:o.set("l",dummyNumberToken(e.channels[0])),o.set("a",dummyNumberToken(e.channels[1])),o.set("b",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha));break;case exports.ColorNotation.LCH:case exports.ColorNotation.OKLCH:o.set("l",dummyNumberToken(e.channels[0])),o.set("c",dummyNumberToken(e.channels[1])),o.set("h",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha));break;case exports.ColorNotation.sRGB:case exports.ColorNotation.A98_RGB:case exports.ColorNotation.Display_P3:case exports.ColorNotation.Rec2020:case exports.ColorNotation.Linear_sRGB:case exports.ColorNotation.ProPhoto_RGB:o.set("r",dummyNumberToken(e.channels[0])),o.set("g",dummyNumberToken(e.channels[1])),o.set("b",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha));break;case exports.ColorNotation.XYZ_D50:case exports.ColorNotation.XYZ_D65:o.set("x",dummyNumberToken(e.channels[0])),o.set("y",dummyNumberToken(e.channels[1])),o.set("z",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&o.set("alpha",dummyNumberToken(e.alpha))}return o}function noneToZeroInRelativeColorDataChannels(e){const o=new Map;for(const[a,n]of e)Number.isNaN(n[4].value)?o.set(a,dummyNumberToken(0)):o.set(a,n);return o}function dummyNumberToken(e){return[a.TokenType.Number,e.toString(),-1,-1,{value:e,type:a.NumberType.Number}]}function reducePrecision(e,o=7){if(Number.isNaN(e))return 0;const a=Math.pow(10,o);return Math.round(e*a)/a}function normalize(e,o,a,n){return Math.min(Math.max(e/o,a),n)}const l=/[A-Z]/g;function toLowerCaseAZ(e){return e.replace(l,(e=>String.fromCharCode(e.charCodeAt(0)+32)))}function normalize_Color_ChannelValues(e,o,n){if(e[0]===a.TokenType.Ident&&"none"===toLowerCaseAZ(e[4].value))return n.syntaxFlags.add(exports.SyntaxFlag.HasNoneKeywords),[a.TokenType.Number,"none",e[2],e[3],{value:NaN,type:a.NumberType.Number}];if(e[0]===a.TokenType.Percentage){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageValues);let t=normalize(e[4].value,100,-1/0,1/0);return 3===o&&(t=normalize(e[4].value,100,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}if(e[0]===a.TokenType.Number){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasNumberValues);let t=normalize(e[4].value,1,-1/0,1/0);return 3===o&&(t=normalize(e[4].value,1,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}return!1}const i=new Set(["srgb","srgb-linear","display-p3","a98-rgb","prophoto-rgb","rec2020","xyz","xyz-d50","xyz-d65"]);function color$1(e,o){const n=[],s=[],l=[],u=[];let c,p,N=!1,m=!1;const h={colorNotation:exports.ColorNotation.sRGB,channels:[0,0,0],alpha:1,syntaxFlags:new Set([])};let y=n;for(let x=0;x=0){i=u.value[4].value;continue}}return!1}if(!l)return!1;n.push({color:l,percentage:i}),l=!1,i=!1}}if(l&&n.push({color:l,percentage:i}),2!==n.length)return!1;let u=n[0].percentage,c=n[1].percentage;return(!1===u||!(u<0||u>100))&&((!1===c||!(c<0||c>100))&&(!1===u&&!1===c?(u=50,c=50):!1!==u&&!1===c?c=100-u:!1===u&&!1!==c&&(u=100-c),(0!==u||0!==c)&&(!1!==u&&!1!==c&&(u+c>100&&(u=u/(u+c)*100,c=c/(u+c)*100),u+c<100&&(s=(u+c)/100,u=u/(u+c)*100,c=c/(u+c)*100),{a:{color:n[0].color,percentage:u},b:{color:n[1].color,percentage:c},alphaMultiplier:s}))))}function colorMixRectangular(e,o){if(!o)return!1;const a=o.a.color,n=o.b.color,t=o.a.percentage/100;let r=a.channels,s=n.channels,l=exports.ColorNotation.RGB,i=a.alpha;if("number"!=typeof i)return!1;let u=n.alpha;if("number"!=typeof u)return!1;switch(i=Number.isNaN(i)?u:i,u=Number.isNaN(u)?i:u,e){case"srgb":l=exports.ColorNotation.RGB;break;case"srgb-linear":l=exports.ColorNotation.Linear_sRGB;break;case"lab":l=exports.ColorNotation.Lab;break;case"oklab":l=exports.ColorNotation.OKLab;break;case"xyz-d50":l=exports.ColorNotation.XYZ_D50;break;case"xyz":case"xyz-d65":l=exports.ColorNotation.XYZ_D65}r=colorDataTo(a,l).channels,s=colorDataTo(n,l).channels,r[0]=premultiply(r[0],i),r[1]=premultiply(r[1],i),r[2]=premultiply(r[2],i),s[0]=premultiply(s[0],u),s[1]=premultiply(s[1],u),s[2]=premultiply(s[2],u);const c=interpolate(i,u,t);return{colorNotation:l,channels:[un_premultiply(interpolate(r[0],s[0],t),c),un_premultiply(interpolate(r[1],s[1],t),c),un_premultiply(interpolate(r[2],s[2],t),c)],alpha:c*o.alphaMultiplier,syntaxFlags:new Set([exports.SyntaxFlag.ColorMix])}}function colorMixPolar(e,o,a){if(!a)return!1;const n=a.a.color,t=a.b.color,r=a.a.percentage/100;let s=n.channels,l=t.channels,i=0,u=0,c=0,p=0,N=0,m=0,h=exports.ColorNotation.RGB,y=n.alpha;if("number"!=typeof y)return!1;let x=t.alpha;if("number"!=typeof x)return!1;switch(y=Number.isNaN(y)?x:y,x=Number.isNaN(x)?y:x,e){case"hsl":h=exports.ColorNotation.HSL;break;case"hwb":h=exports.ColorNotation.HWB;break;case"lch":h=exports.ColorNotation.LCH;break;case"oklch":h=exports.ColorNotation.OKLCH}switch(s=colorDataTo(n,h).channels,l=colorDataTo(t,h).channels,e){case"hsl":case"hwb":i=s[0],u=l[0],c=s[1],p=l[1],N=s[2],m=l[2];break;case"lch":case"oklch":c=s[0],p=l[0],N=s[1],m=l[1],i=s[2],u=l[2]}if(!Number.isNaN(i)&&!Number.isNaN(u)){const e=u-i;switch(o){case"shorter":e>180?i+=360:e<-180&&(u+=360);break;case"longer":-1800?i+=360:u+=360);break;case"increasing":e<0&&(u+=360);break;case"decreasing":e>0&&(i+=360);break;default:throw new Error("Unknown hue interpolation method")}}c=premultiply(c,y),N=premultiply(N,y),p=premultiply(p,x),m=premultiply(m,x);let b=[0,0,0];const T=interpolate(y,x,r);switch(e){case"hsl":case"hwb":b=[interpolate(i,u,r),un_premultiply(interpolate(c,p,r),T),un_premultiply(interpolate(N,m,r),T)];break;case"lch":case"oklch":b=[un_premultiply(interpolate(c,p,r),T),un_premultiply(interpolate(N,m,r),T),interpolate(i,u,r)]}return{colorNotation:h,channels:b,alpha:T*a.alphaMultiplier,syntaxFlags:new Set([exports.SyntaxFlag.ColorMix])}}function interpolate(e,o,a){return Number.isNaN(e)?o:Number.isNaN(o)?e:e*a+o*(1-a)}function premultiply(e,o){return Number.isNaN(o)?e:Number.isNaN(e)?NaN:e*o}function un_premultiply(e,o){return 0===o||Number.isNaN(o)?e:Number.isNaN(e)?NaN:e/o}function hex(e){const o=toLowerCaseAZ(e[4].value);if(o.match(/[^a-f0-9]/))return!1;const a={colorNotation:exports.ColorNotation.HEX,channels:[0,0,0],alpha:1,syntaxFlags:new Set([exports.SyntaxFlag.Hex])},n=o.length;if(3===n){const e=o[0],n=o[1],t=o[2];return a.channels=[parseInt(e+e,16)/255,parseInt(n+n,16)/255,parseInt(t+t,16)/255],a}if(6===n){const e=o[0]+o[1],n=o[2]+o[3],t=o[4]+o[5];return a.channels=[parseInt(e,16)/255,parseInt(n,16)/255,parseInt(t,16)/255],a}if(4===n){const e=o[0],n=o[1],t=o[2],r=o[3];return a.channels=[parseInt(e+e,16)/255,parseInt(n+n,16)/255,parseInt(t+t,16)/255],a.alpha=parseInt(r+r,16)/255,a.syntaxFlags.add(exports.SyntaxFlag.HasAlpha),a}if(8===n){const e=o[0]+o[1],n=o[2]+o[3],t=o[4]+o[5],r=o[6]+o[7];return a.channels=[parseInt(e,16)/255,parseInt(n,16)/255,parseInt(t,16)/255],a.alpha=parseInt(r,16)/255,a.syntaxFlags.add(exports.SyntaxFlag.HasAlpha),a}return!1}function normalizeHue(e){if(e[0]===a.TokenType.Number)return e[4].value=e[4].value%360,e[1]=e[4].value.toString(),e;if(e[0]===a.TokenType.Dimension){let o=e[4].value;switch(toLowerCaseAZ(e[4].unit)){case"deg":break;case"rad":o=180*e[4].value/Math.PI;break;case"grad":o=.9*e[4].value;break;case"turn":o=360*e[4].value;break;default:return!1}return o%=360,[a.TokenType.Number,o.toString(),e[2],e[3],{value:o,type:a.NumberType.Number}]}return!1}function normalize_legacy_HSL_ChannelValues(e,o,n){if(0===o){const o=normalizeHue(e);return!1!==o&&(e[0]===a.TokenType.Dimension&&n.syntaxFlags.add(exports.SyntaxFlag.HasDimensionValues),o)}if(e[0]===a.TokenType.Percentage){3===o?n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageAlpha):n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageValues);let t=normalize(e[4].value,1,0,100);return 3===o&&(t=normalize(e[4].value,100,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}if(e[0]===a.TokenType.Number){if(3!==o)return!1;let n=normalize(e[4].value,1,0,100);return 3===o&&(n=normalize(e[4].value,1,0,1)),[a.TokenType.Number,n.toString(),e[2],e[3],{value:n,type:a.NumberType.Number}]}return!1}function normalize_modern_HSL_ChannelValues(e,o,n){if(e[0]===a.TokenType.Ident&&"none"===toLowerCaseAZ(e[4].value))return n.syntaxFlags.add(exports.SyntaxFlag.HasNoneKeywords),[a.TokenType.Number,"none",e[2],e[3],{value:NaN,type:a.NumberType.Number}];if(0===o){const o=normalizeHue(e);return!1!==o&&(e[0]===a.TokenType.Dimension&&n.syntaxFlags.add(exports.SyntaxFlag.HasDimensionValues),o)}if(e[0]===a.TokenType.Percentage){3===o?n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageAlpha):n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageValues);let t=normalize(e[4].value,1,0,100);return 3===o&&(t=normalize(e[4].value,100,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}if(e[0]===a.TokenType.Number){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasNumberValues);let t=normalize(e[4].value,1,0,100);return 3===o&&(t=normalize(e[4].value,1,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}return!1}function threeChannelLegacySyntax(e,o,n,s){const l=[],i=[],u=[],c=[],p={colorNotation:n,channels:[0,0,0],alpha:1,syntaxFlags:new Set(s)};let N=l;for(let o=0;o.999999&&(a=[1,0,0]),n.calculations.mapGamut(a,(e=>(e=n.conversions.OKLCH_to_OKLab(e),e=n.conversions.OKLab_to_XYZ(e),e=n.conversions.XYZ_to_lin_sRGB(e),n.conversions.gam_sRGB(e))),(e=>(e=n.conversions.lin_sRGB(e),e=n.conversions.lin_sRGB_to_XYZ(e),e=n.conversions.XYZ_to_OKLab(e),n.conversions.OKLab_to_OKLCH(e))))}function threeChannelSpaceSeparated(e,o,s,l,i){const u=toLowerCaseAZ(e.getName()),c=[],p=[],N=[],m=[];let h,y,x=!1;const b={colorNotation:s,channels:[0,0,0],alpha:1,syntaxFlags:new Set(l)};let T=c;for(let o=0;ot.isTokenNode(e)&&e.value[0]===a.TokenType.Comma))){const o=hslCommaSeparated(e);if(!1!==o)return o}{const a=hslSpaceSeparated(e,o);if(!1!==a)return a}return!1}function hslCommaSeparated(e){return threeChannelLegacySyntax(e,normalize_legacy_HSL_ChannelValues,exports.ColorNotation.HSL,[exports.SyntaxFlag.LegacyHSL])}function hslSpaceSeparated(e,o){return threeChannelSpaceSeparated(e,normalize_modern_HSL_ChannelValues,exports.ColorNotation.HSL,[],o)}function normalize_HWB_ChannelValues(e,o,n){if(e[0]===a.TokenType.Ident&&"none"===toLowerCaseAZ(e[4].value))return n.syntaxFlags.add(exports.SyntaxFlag.HasNoneKeywords),[a.TokenType.Number,"none",e[2],e[3],{value:NaN,type:a.NumberType.Number}];if(0===o){const o=normalizeHue(e);return!1!==o&&(e[0]===a.TokenType.Dimension&&n.syntaxFlags.add(exports.SyntaxFlag.HasDimensionValues),o)}if(e[0]===a.TokenType.Percentage){3===o?n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageAlpha):n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageValues);let t=normalize(e[4].value,1,0,100);return 3===o&&(t=normalize(e[4].value,100,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}if(e[0]===a.TokenType.Number){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasNumberValues);let t=normalize(e[4].value,1,0,100);return 3===o&&(t=normalize(e[4].value,1,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}return!1}function normalize_Lab_ChannelValues(e,o,n){if(e[0]===a.TokenType.Ident&&"none"===toLowerCaseAZ(e[4].value))return n.syntaxFlags.add(exports.SyntaxFlag.HasNoneKeywords),[a.TokenType.Number,"none",e[2],e[3],{value:NaN,type:a.NumberType.Number}];if(e[0]===a.TokenType.Percentage){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageValues);let t=normalize(e[4].value,1,0,100);return 1===o||2===o?t=normalize(e[4].value,.8,-1/0,1/0):3===o&&(t=normalize(e[4].value,100,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}if(e[0]===a.TokenType.Number){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasNumberValues);let t=normalize(e[4].value,1,0,100);return 1===o||2===o?t=normalize(e[4].value,1,-1/0,1/0):3===o&&(t=normalize(e[4].value,1,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}return!1}function lab(e,o){return threeChannelSpaceSeparated(e,normalize_Lab_ChannelValues,exports.ColorNotation.Lab,[],o)}function normalize_LCH_ChannelValues(e,o,n){if(e[0]===a.TokenType.Ident&&"none"===toLowerCaseAZ(e[4].value))return n.syntaxFlags.add(exports.SyntaxFlag.HasNoneKeywords),[a.TokenType.Number,"none",e[2],e[3],{value:NaN,type:a.NumberType.Number}];if(2===o){const o=normalizeHue(e);return!1!==o&&(e[0]===a.TokenType.Dimension&&n.syntaxFlags.add(exports.SyntaxFlag.HasDimensionValues),o)}if(e[0]===a.TokenType.Percentage){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageValues);let t=normalize(e[4].value,1,0,100);return 1===o?t=normalize(e[4].value,100/150,0,1/0):3===o&&(t=normalize(e[4].value,100,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}if(e[0]===a.TokenType.Number){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasNumberValues);let t=normalize(e[4].value,1,0,100);return 1===o?t=normalize(e[4].value,1,0,1/0):3===o&&(t=normalize(e[4].value,1,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}return!1}function lch(e,o){return threeChannelSpaceSeparated(e,normalize_LCH_ChannelValues,exports.ColorNotation.LCH,[],o)}const N=new Map;for(const[e,o]of Object.entries(n.namedColors))N.set(e,o);function namedColor(e){const o=N.get(toLowerCaseAZ(e));return!!o&&{colorNotation:exports.ColorNotation.RGB,channels:[o[0]/255,o[1]/255,o[2]/255],alpha:1,syntaxFlags:new Set([exports.SyntaxFlag.ColorKeyword,exports.SyntaxFlag.NamedColor])}}function normalize_OKLab_ChannelValues(e,o,n){if(e[0]===a.TokenType.Ident&&"none"===toLowerCaseAZ(e[4].value))return n.syntaxFlags.add(exports.SyntaxFlag.HasNoneKeywords),[a.TokenType.Number,"none",e[2],e[3],{value:NaN,type:a.NumberType.Number}];if(e[0]===a.TokenType.Percentage){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageValues);let t=normalize(e[4].value,100,0,1);return 1===o||2===o?t=normalize(e[4].value,250,-1/0,1/0):3===o&&(t=normalize(e[4].value,100,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}if(e[0]===a.TokenType.Number){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasNumberValues);let t=normalize(e[4].value,1,0,1);return 1===o||2===o?t=normalize(e[4].value,1,-1/0,1/0):3===o&&(t=normalize(e[4].value,1,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}return!1}function oklab(e,o){return threeChannelSpaceSeparated(e,normalize_OKLab_ChannelValues,exports.ColorNotation.OKLab,[],o)}function normalize_OKLCH_ChannelValues(e,o,n){if(e[0]===a.TokenType.Ident&&"none"===toLowerCaseAZ(e[4].value))return n.syntaxFlags.add(exports.SyntaxFlag.HasNoneKeywords),[a.TokenType.Number,"none",e[2],e[3],{value:NaN,type:a.NumberType.Number}];if(2===o){const o=normalizeHue(e);return!1!==o&&(e[0]===a.TokenType.Dimension&&n.syntaxFlags.add(exports.SyntaxFlag.HasDimensionValues),o)}if(e[0]===a.TokenType.Percentage){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageValues);let t=normalize(e[4].value,100,0,1);return 1===o?t=normalize(e[4].value,250,0,1/0):3===o&&(t=normalize(e[4].value,100,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}if(e[0]===a.TokenType.Number){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasNumberValues);let t=normalize(e[4].value,1,0,1);return 1===o?t=normalize(e[4].value,1,0,1/0):3===o&&(t=normalize(e[4].value,1,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}return!1}function oklch(e,o){return threeChannelSpaceSeparated(e,normalize_OKLCH_ChannelValues,exports.ColorNotation.OKLCH,[],o)}function normalize_legacy_sRGB_ChannelValues(e,o,n){if(e[0]===a.TokenType.Percentage){3===o?n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageAlpha):n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageValues);const t=normalize(e[4].value,100,0,1);return[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}if(e[0]===a.TokenType.Number){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasNumberValues);let t=normalize(e[4].value,255,0,1);return 3===o&&(t=normalize(e[4].value,1,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}return!1}function normalize_modern_sRGB_ChannelValues(e,o,n){if(e[0]===a.TokenType.Ident&&"none"===toLowerCaseAZ(e[4].value))return n.syntaxFlags.add(exports.SyntaxFlag.HasNoneKeywords),[a.TokenType.Number,"none",e[2],e[3],{value:NaN,type:a.NumberType.Number}];if(e[0]===a.TokenType.Percentage){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasPercentageValues);const t=normalize(e[4].value,100,0,1);return[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}if(e[0]===a.TokenType.Number){3!==o&&n.syntaxFlags.add(exports.SyntaxFlag.HasNumberValues);let t=normalize(e[4].value,255,0,1);return 3===o&&(t=normalize(e[4].value,1,0,1)),[a.TokenType.Number,t.toString(),e[2],e[3],{value:t,type:a.NumberType.Number}]}return!1}function rgb(e,o){if(e.value.some((e=>t.isTokenNode(e)&&e.value[0]===a.TokenType.Comma))){const o=rgbCommaSeparated(e);if(!1!==o)return(!o.syntaxFlags.has(exports.SyntaxFlag.HasNumberValues)||!o.syntaxFlags.has(exports.SyntaxFlag.HasPercentageValues))&&o}else{const a=rgbSpaceSeparated(e,o);if(!1!==a)return a}return!1}function rgbCommaSeparated(e){return threeChannelLegacySyntax(e,normalize_legacy_sRGB_ChannelValues,exports.ColorNotation.RGB,[exports.SyntaxFlag.LegacyRGB])}function rgbSpaceSeparated(e,o){return threeChannelSpaceSeparated(e,normalize_modern_sRGB_ChannelValues,exports.ColorNotation.RGB,[],o)}function toPrecision(e,o=7){e=+e,o=+o;const a=(Math.floor(e)+"").length;if(o>a)return+e.toFixed(o-a);{const n=10**(a-o);return Math.round(e/n)*n}}function XYZ_D50_to_P3_Gamut(e){const o=n.xyz.XYZ_D50_to_P3(e);if(n.utils.inGamut(o))return n.utils.clip(o);let a=e.slice();return a=n.conversions.D50_to_D65(a),a=n.conversions.XYZ_to_OKLab(a),a=n.conversions.OKLab_to_OKLCH(a),a[0]<1e-6&&(a=[0,0,0]),a[0]>.999999&&(a=[1,0,0]),n.calculations.mapGamut(a,(e=>(e=n.conversions.OKLCH_to_OKLab(e),e=n.conversions.OKLab_to_XYZ(e),e=n.conversions.XYZ_to_lin_P3(e),n.conversions.gam_P3(e))),(e=>(e=n.conversions.lin_P3(e),e=n.conversions.lin_P3_to_XYZ(e),e=n.conversions.XYZ_to_OKLab(e),n.conversions.OKLab_to_OKLCH(e))))}function serializeWithAlpha(e,o,n,r){const s=[a.TokenType.CloseParen,")",-1,-1,void 0];if("number"==typeof e.alpha){const l=Math.min(1,Math.max(0,toPrecision(Number.isNaN(e.alpha)?0:e.alpha)));return 1===toPrecision(l,4)?new t.FunctionNode(o,s,r):new t.FunctionNode(o,s,[...r,new t.WhitespaceNode([n]),new t.TokenNode([a.TokenType.Delim,"/",-1,-1,{value:"/"}]),new t.WhitespaceNode([n]),new t.TokenNode([a.TokenType.Number,toPrecision(l,4).toString(),-1,-1,{value:e.alpha,type:a.NumberType.Integer}])])}return new t.FunctionNode(o,s,[...r,new t.WhitespaceNode([n]),new t.TokenNode([a.TokenType.Delim,"/",-1,-1,{value:"/"}]),new t.WhitespaceNode([n]),e.alpha])}exports.color=function color(e){if(t.isFunctionNode(e)){switch(toLowerCaseAZ(e.getName())){case"rgb":case"rgba":return rgb(e,color);case"hsl":case"hsla":return hsl(e,color);case"hwb":return o=color,threeChannelSpaceSeparated(e,normalize_HWB_ChannelValues,exports.ColorNotation.HWB,[],o);case"lab":return lab(e,color);case"lch":return lch(e,color);case"oklab":return oklab(e,color);case"oklch":return oklch(e,color);case"color":return color$1(e,color);case"color-mix":return colorMix(e,color)}}var o;if(t.isTokenNode(e)){if(e.value[0]===a.TokenType.Hash)return hex(e.value);if(e.value[0]===a.TokenType.Ident){const o=namedColor(e.value[4].value);return!1!==o?o:"transparent"===toLowerCaseAZ(e.value[4].value)&&{colorNotation:exports.ColorNotation.RGB,channels:[0,0,0],alpha:0,syntaxFlags:new Set([exports.SyntaxFlag.ColorKeyword])}}}return!1},exports.colorDataFitsRGB_Gamut=function colorDataFitsRGB_Gamut(e){const o=JSON.parse(JSON.stringify(e));return o.channels=convertPowerlessComponentsToZeroValuesForDisplay(o.channels,o.colorNotation),!colorDataTo(o,exports.ColorNotation.RGB).channels.find((e=>e<-1e-5||e>1.00001))},exports.colorDataTo=colorDataTo,exports.serializeOKLCH=function serializeOKLCH(e){e.channels=convertPowerlessComponentsToZeroValuesForDisplay(e.channels,e.colorNotation);let o=e.channels.map((e=>Number.isNaN(e)?0:e));e.colorNotation!==exports.ColorNotation.OKLCH&&(o=n.xyz.XYZ_D50_to_OKLCH(colorData_to_XYZ_D50(e).channels));const r=toPrecision(o[0],6),s=toPrecision(o[1],6),l=toPrecision(o[2],6),i=[a.TokenType.Function,"oklch(",-1,-1,{value:"oklch"}],u=[a.TokenType.Whitespace," ",-1,-1,void 0];return serializeWithAlpha(e,i,u,[new t.TokenNode([a.TokenType.Number,r.toString(),-1,-1,{value:o[0],type:a.NumberType.Number}]),new t.WhitespaceNode([u]),new t.TokenNode([a.TokenType.Number,s.toString(),-1,-1,{value:o[1],type:a.NumberType.Number}]),new t.WhitespaceNode([u]),new t.TokenNode([a.TokenType.Number,l.toString(),-1,-1,{value:o[2],type:a.NumberType.Number}])])},exports.serializeP3=function serializeP3(e,o=!0){e.channels=convertPowerlessComponentsToZeroValuesForDisplay(e.channels,e.colorNotation);let r=e.channels.map((e=>Number.isNaN(e)?0:e));e.colorNotation!==exports.ColorNotation.Display_P3&&(r=o?XYZ_D50_to_P3_Gamut(colorData_to_XYZ_D50(e).channels):n.xyz.XYZ_D50_to_P3(colorData_to_XYZ_D50(e).channels));const s=toPrecision(r[0],6),l=toPrecision(r[1],6),i=toPrecision(r[2],6),u=[a.TokenType.Function,"color(",-1,-1,{value:"color"}],c=[a.TokenType.Whitespace," ",-1,-1,void 0];return serializeWithAlpha(e,u,c,[new t.TokenNode([a.TokenType.Ident,"display-p3",-1,-1,{value:"display-p3"}]),new t.WhitespaceNode([c]),new t.TokenNode([a.TokenType.Number,s.toString(),-1,-1,{value:r[0],type:a.NumberType.Number}]),new t.WhitespaceNode([c]),new t.TokenNode([a.TokenType.Number,l.toString(),-1,-1,{value:r[1],type:a.NumberType.Number}]),new t.WhitespaceNode([c]),new t.TokenNode([a.TokenType.Number,i.toString(),-1,-1,{value:r[2],type:a.NumberType.Number}])])},exports.serializeRGB=function serializeRGB(e,o=!0){e.channels=convertPowerlessComponentsToZeroValuesForDisplay(e.channels,e.colorNotation);let r=e.channels.map((e=>Number.isNaN(e)?0:e));e.colorNotation===exports.ColorNotation.HWB?r=n.conversions.HWB_to_sRGB(r):e.colorNotation===exports.ColorNotation.HSL?r=n.conversions.HSL_to_sRGB(r):e.colorNotation!==exports.ColorNotation.RGB&&e.colorNotation!==exports.ColorNotation.HEX&&(r=o?XYZ_D50_to_sRGB_Gamut(colorData_to_XYZ_D50(e).channels):n.xyz.XYZ_D50_to_sRGB(colorData_to_XYZ_D50(e).channels));const s=Math.min(255,Math.max(0,Math.round(255*toPrecision(r[0])))),l=Math.min(255,Math.max(0,Math.round(255*toPrecision(r[1])))),i=Math.min(255,Math.max(0,Math.round(255*toPrecision(r[2])))),u=[a.TokenType.CloseParen,")",-1,-1,void 0],c=[a.TokenType.Whitespace," ",-1,-1,void 0],p=[a.TokenType.Comma,",",-1,-1,void 0],N=[new t.TokenNode([a.TokenType.Number,s.toString(),-1,-1,{value:r[0],type:a.NumberType.Integer}]),new t.TokenNode(p),new t.WhitespaceNode([c]),new t.TokenNode([a.TokenType.Number,l.toString(),-1,-1,{value:r[1],type:a.NumberType.Integer}]),new t.TokenNode(p),new t.WhitespaceNode([c]),new t.TokenNode([a.TokenType.Number,i.toString(),-1,-1,{value:r[2],type:a.NumberType.Integer}])];if("number"==typeof e.alpha){const o=Math.min(1,Math.max(0,toPrecision(Number.isNaN(e.alpha)?0:e.alpha)));return 1===toPrecision(o,4)?new t.FunctionNode([a.TokenType.Function,"rgb(",-1,-1,{value:"rgb"}],u,N):new t.FunctionNode([a.TokenType.Function,"rgba(",-1,-1,{value:"rgba"}],u,[...N,new t.TokenNode(p),new t.WhitespaceNode([c]),new t.TokenNode([a.TokenType.Number,toPrecision(o,4).toString(),-1,-1,{value:e.alpha,type:a.NumberType.Number}])])}return new t.FunctionNode([a.TokenType.Function,"rgba(",-1,-1,{value:"rgba"}],u,[...N,new t.TokenNode(p),new t.WhitespaceNode([c]),e.alpha])}; diff --git a/packages/css-color-parser/dist/index.mjs b/packages/css-color-parser/dist/index.mjs index 43860b380..edc688fd7 100644 --- a/packages/css-color-parser/dist/index.mjs +++ b/packages/css-color-parser/dist/index.mjs @@ -1 +1 @@ -import{TokenType as e,NumberType as a}from"@csstools/css-tokenizer";import{xyz as n,utils as r,conversions as o,calculations as t,namedColors as l}from"@csstools/color-helpers";import{isWhitespaceNode as s,isCommentNode as u,isTokenNode as c,isFunctionNode as i,TokenNode as h,FunctionNode as m,WhitespaceNode as N}from"@csstools/css-parser-algorithms";import{mathFunctionNames as p,calcFromComponentValues as b}from"@csstools/css-calc";var _,g;function colorData_to_XYZ_D50(e){switch(e.colorNotation){case _.HEX:case _.RGB:case _.sRGB:return{...e,colorNotation:_.XYZ_D50,channels:n.sRGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.Linear_sRGB:return{...e,colorNotation:_.XYZ_D50,channels:n.lin_sRGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.Display_P3:return{...e,colorNotation:_.XYZ_D50,channels:n.P3_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.Rec2020:return{...e,colorNotation:_.XYZ_D50,channels:n.rec_2020_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.A98_RGB:return{...e,colorNotation:_.XYZ_D50,channels:n.a98_RGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.ProPhoto_RGB:return{...e,colorNotation:_.XYZ_D50,channels:n.ProPhoto_RGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.HSL:return{...e,colorNotation:_.XYZ_D50,channels:n.HSL_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.HWB:return{...e,colorNotation:_.XYZ_D50,channels:n.HWB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.Lab:return{...e,colorNotation:_.XYZ_D50,channels:n.Lab_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.OKLab:return{...e,colorNotation:_.XYZ_D50,channels:n.OKLab_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.LCH:return{...e,colorNotation:_.XYZ_D50,channels:n.LCH_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.OKLCH:return{...e,colorNotation:_.XYZ_D50,channels:n.OKLCH_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.XYZ_D50:return{...e,colorNotation:_.XYZ_D50,channels:n.XYZ_D50_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.XYZ_D65:return{...e,colorNotation:_.XYZ_D50,channels:n.XYZ_D65_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};default:throw new Error("Unsupported color notation")}}!function(e){e.A98_RGB="a98-rgb",e.Display_P3="display-p3",e.HEX="hex",e.HSL="hsl",e.HWB="hwb",e.LCH="lch",e.Lab="lab",e.Linear_sRGB="srgb-linear",e.OKLCH="oklch",e.OKLab="oklab",e.ProPhoto_RGB="prophoto-rgb",e.RGB="rgb",e.sRGB="srgb",e.Rec2020="rec2020",e.XYZ_D50="xyz-d50",e.XYZ_D65="xyz-d65"}(_||(_={})),function(e){e.ColorKeyword="color-keyword",e.HasAlpha="has-alpha",e.HasDimensionValues="has-dimension-values",e.HasNoneKeywords="has-none-keywords",e.HasNumberValues="has-number-values",e.HasPercentageAlpha="has-percentage-alpha",e.HasPercentageValues="has-percentage-values",e.HasVariableAlpha="has-variable-alpha",e.Hex="hex",e.LegacyHSL="legacy-hsl",e.LegacyRGB="legacy-rgb",e.NamedColor="named-color",e.RelativeColorSyntax="relative-color-syntax",e.ColorMix="color-mix"}(g||(g={}));const v=new Set([_.A98_RGB,_.Display_P3,_.HEX,_.Linear_sRGB,_.ProPhoto_RGB,_.RGB,_.sRGB,_.Rec2020,_.XYZ_D50,_.XYZ_D65]);function colorDataTo(e,a){const r={...e};if(e.colorNotation!==a){const e=colorData_to_XYZ_D50(r);switch(a){case _.HEX:case _.RGB:r.colorNotation=_.RGB,r.channels=n.XYZ_D50_to_sRGB(e.channels);break;case _.sRGB:r.colorNotation=_.sRGB,r.channels=n.XYZ_D50_to_sRGB(e.channels);break;case _.Linear_sRGB:r.colorNotation=_.Linear_sRGB,r.channels=n.XYZ_D50_to_lin_sRGB(e.channels);break;case _.Display_P3:r.colorNotation=_.Display_P3,r.channels=n.XYZ_D50_to_P3(e.channels);break;case _.Rec2020:r.colorNotation=_.Rec2020,r.channels=n.XYZ_D50_to_rec_2020(e.channels);break;case _.ProPhoto_RGB:r.colorNotation=_.ProPhoto_RGB,r.channels=n.XYZ_D50_to_ProPhoto(e.channels);break;case _.A98_RGB:r.colorNotation=_.A98_RGB,r.channels=n.XYZ_D50_to_a98_RGB(e.channels);break;case _.HSL:r.colorNotation=_.HSL,r.channels=n.XYZ_D50_to_HSL(e.channels);break;case _.HWB:r.colorNotation=_.HWB,r.channels=n.XYZ_D50_to_HWB(e.channels);break;case _.Lab:r.colorNotation=_.Lab,r.channels=n.XYZ_D50_to_Lab(e.channels);break;case _.LCH:r.colorNotation=_.LCH,r.channels=n.XYZ_D50_to_LCH(e.channels);break;case _.OKLCH:r.colorNotation=_.OKLCH,r.channels=n.XYZ_D50_to_OKLCH(e.channels);break;case _.OKLab:r.colorNotation=_.OKLab,r.channels=n.XYZ_D50_to_OKLab(e.channels);break;case _.XYZ_D50:r.colorNotation=_.XYZ_D50,r.channels=n.XYZ_D50_to_XYZ_D50(e.channels);break;case _.XYZ_D65:r.colorNotation=_.XYZ_D65,r.channels=n.XYZ_D50_to_XYZ_D65(e.channels);break;default:throw new Error("Unsupported color notation")}}else r.channels=e.channels.map((e=>Number.isNaN(e)?0:e));if(a===e.colorNotation)r.channels=carryForwardMissingComponents(e.channels,[0,1,2],r.channels,[0,1,2]);else if(v.has(a)&&v.has(e.colorNotation))r.channels=carryForwardMissingComponents(e.channels,[0,1,2],r.channels,[0,1,2]);else switch(a){case _.HSL:switch(e.colorNotation){case _.HWB:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[0]);break;case _.Lab:case _.OKLab:r.channels=carryForwardMissingComponents(e.channels,[2],r.channels,[0]);break;case _.LCH:case _.OKLCH:r.channels=carryForwardMissingComponents(e.channels,[0,1,2],r.channels,[2,1,0])}break;case _.HWB:switch(e.colorNotation){case _.HSL:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[0]);break;case _.LCH:case _.OKLCH:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[2])}break;case _.Lab:case _.OKLab:switch(e.colorNotation){case _.HSL:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[2]);break;case _.Lab:case _.OKLab:r.channels=carryForwardMissingComponents(e.channels,[0,1,2],r.channels,[0,1,2]);break;case _.LCH:case _.OKLCH:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[0])}break;case _.LCH:case _.OKLCH:switch(e.colorNotation){case _.HSL:r.channels=carryForwardMissingComponents(e.channels,[0,1,2],r.channels,[2,1,0]);break;case _.HWB:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[2]);break;case _.Lab:case _.OKLab:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[0]);break;case _.LCH:case _.OKLCH:r.channels=carryForwardMissingComponents(e.channels,[0,1,2],r.channels,[0,1,2])}}return r.channels=convertPowerlessComponentsToMissingComponents(r.channels,a),r}function convertPowerlessComponentsToMissingComponents(e,a){const n=[...e];switch(a){case _.HSL:reducePrecision(n[1],4)<=0&&(n[0]=NaN);break;case _.HWB:Math.max(0,reducePrecision(n[1],4))+Math.max(0,reducePrecision(n[2],4))>=100&&(n[0]=NaN);break;case _.LCH:reducePrecision(n[1],4)<=0&&(n[2]=NaN);break;case _.OKLCH:reducePrecision(n[1],6)<=0&&(n[2]=NaN)}return n}function convertPowerlessComponentsToZeroValuesForDisplay(e,a){const n=[...e];switch(a){case _.HSL:(reducePrecision(n[2])<=0||reducePrecision(n[2])>=100)&&(n[0]=NaN,n[1]=NaN),reducePrecision(n[1])<=0&&(n[0]=NaN);break;case _.HWB:Math.max(0,reducePrecision(n[1]))+Math.max(0,reducePrecision(n[2]))>=100&&(n[0]=NaN);break;case _.Lab:(reducePrecision(n[0])<=0||reducePrecision(n[0])>=100)&&(n[1]=NaN,n[2]=NaN);break;case _.LCH:reducePrecision(n[1])<=0&&(n[2]=NaN),(reducePrecision(n[0])<=0||reducePrecision(n[0])>=100)&&(n[1]=NaN,n[2]=NaN);break;case _.OKLab:(reducePrecision(n[0])<=0||reducePrecision(n[0])>=1)&&(n[1]=NaN,n[2]=NaN);break;case _.OKLCH:reducePrecision(n[1])<=0&&(n[2]=NaN),(reducePrecision(n[0])<=0||reducePrecision(n[0])>=1)&&(n[1]=NaN,n[2]=NaN)}return n}function carryForwardMissingComponents(e,a,n,r){const o=[...n];for(const n of a)Number.isNaN(e[a[n]])&&(o[r[n]]=NaN);return o}function normalizeRelativeColorDataChannels(e){const a=new Map;switch(e.colorNotation){case _.RGB:case _.HEX:a.set("r",dummyNumberToken(255*e.channels[0])),a.set("g",dummyNumberToken(255*e.channels[1])),a.set("b",dummyNumberToken(255*e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha));break;case _.HSL:a.set("h",dummyNumberToken(e.channels[0])),a.set("s",dummyNumberToken(e.channels[1])),a.set("l",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha));break;case _.HWB:a.set("h",dummyNumberToken(e.channels[0])),a.set("w",dummyNumberToken(e.channels[1])),a.set("b",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha));break;case _.Lab:case _.OKLab:a.set("l",dummyNumberToken(e.channels[0])),a.set("a",dummyNumberToken(e.channels[1])),a.set("b",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha));break;case _.LCH:case _.OKLCH:a.set("l",dummyNumberToken(e.channels[0])),a.set("c",dummyNumberToken(e.channels[1])),a.set("h",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha));break;case _.sRGB:case _.A98_RGB:case _.Display_P3:case _.Rec2020:case _.Linear_sRGB:case _.ProPhoto_RGB:a.set("r",dummyNumberToken(e.channels[0])),a.set("g",dummyNumberToken(e.channels[1])),a.set("b",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha));break;case _.XYZ_D50:case _.XYZ_D65:a.set("x",dummyNumberToken(e.channels[0])),a.set("y",dummyNumberToken(e.channels[1])),a.set("z",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha))}return a}function noneToZeroInRelativeColorDataChannels(e){const a=new Map;for(const[n,r]of e)Number.isNaN(r[4].value)?a.set(n,dummyNumberToken(0)):a.set(n,r);return a}function dummyNumberToken(n){return[e.Number,n.toString(),-1,-1,{value:n,type:a.Number}]}function reducePrecision(e,a=7){if(Number.isNaN(e))return 0;const n=Math.pow(10,a);return Math.round(e*n)/n}function colorDataFitsRGB_Gamut(e){const a=JSON.parse(JSON.stringify(e));a.channels=convertPowerlessComponentsToZeroValuesForDisplay(a.channels,a.colorNotation);return!colorDataTo(a,_.RGB).channels.find((e=>e<-1e-5||e>1.00001))}function normalize(e,a,n,r){return Math.min(Math.max(e/a,n),r)}const d=/[A-Z]/g;function toLowerCaseAZ(e){return e.replace(d,(e=>String.fromCharCode(e.charCodeAt(0)+32)))}function normalize_Color_ChannelValues(n,r){const o=[];for(let t=0;t=0){l=h.value[4].value;continue}}return!1}if(!t)return!1;r.push({color:t,percentage:l}),t=!1,l=!1}}if(t&&r.push({color:t,percentage:l}),2!==r.length)return!1;let h=r[0].percentage,m=r[1].percentage;return(!1===h||!(h<0||h>100))&&((!1===m||!(m<0||m>100))&&(!1===h&&!1===m?(h=50,m=50):!1!==h&&!1===m?m=100-h:!1===h&&!1!==m&&(h=100-m),(0!==h||0!==m)&&(!1!==h&&!1!==m&&(h+m>100&&(h=h/(h+m)*100,m=m/(h+m)*100),h+m<100&&(o=(h+m)/100,h=h/(h+m)*100,m=m/(h+m)*100),{a:{color:r[0].color,percentage:h},b:{color:r[1].color,percentage:m},alphaMultiplier:o}))))}function colorMixRectangular(e,a){if(!a)return!1;const n=a.a.color,r=a.b.color,o=a.a.percentage/100;let t=n.channels,l=r.channels,s=_.RGB,u=n.alpha;if("number"!=typeof u)return!1;let c=r.alpha;if("number"!=typeof c)return!1;switch(u=Number.isNaN(u)?c:u,c=Number.isNaN(c)?u:c,e){case"srgb":s=_.RGB;break;case"srgb-linear":s=_.Linear_sRGB;break;case"lab":s=_.Lab;break;case"oklab":s=_.OKLab;break;case"xyz-d50":s=_.XYZ_D50;break;case"xyz":case"xyz-d65":s=_.XYZ_D65}t=colorDataTo(n,s).channels,l=colorDataTo(r,s).channels,t[0]=premultiply(t[0],u),t[1]=premultiply(t[1],u),t[2]=premultiply(t[2],u),l[0]=premultiply(l[0],c),l[1]=premultiply(l[1],c),l[2]=premultiply(l[2],c);const i=interpolate(u,c,o);return{colorNotation:s,channels:[un_premultiply(interpolate(t[0],l[0],o),i),un_premultiply(interpolate(t[1],l[1],o),i),un_premultiply(interpolate(t[2],l[2],o),i)],alpha:i*a.alphaMultiplier,syntaxFlags:new Set([g.ColorMix])}}function colorMixPolar(e,a,n){if(!n)return!1;const r=n.a.color,o=n.b.color,t=n.a.percentage/100;let l=r.channels,s=o.channels,u=0,c=0,i=0,h=0,m=0,N=0,p=_.RGB,b=r.alpha;if("number"!=typeof b)return!1;let v=o.alpha;if("number"!=typeof v)return!1;switch(b=Number.isNaN(b)?v:b,v=Number.isNaN(v)?b:v,e){case"hsl":p=_.HSL;break;case"hwb":p=_.HWB;break;case"lch":p=_.LCH;break;case"oklch":p=_.OKLCH}switch(l=colorDataTo(r,p).channels,s=colorDataTo(o,p).channels,e){case"hsl":case"hwb":u=l[0],c=s[0],i=l[1],h=s[1],m=l[2],N=s[2];break;case"lch":case"oklch":i=l[0],h=s[0],m=l[1],N=s[1],u=l[2],c=s[2]}if(!Number.isNaN(u)&&!Number.isNaN(c)){const e=c-u;switch(a){case"shorter":e>180?u+=360:e<-180&&(c+=360);break;case"longer":-1800?u+=360:c+=360);break;case"increasing":e<0&&(c+=360);break;case"decreasing":e>0&&(u+=360);break;default:throw new Error("Unknown hue interpolation method")}}i=premultiply(i,b),m=premultiply(m,b),h=premultiply(h,v),N=premultiply(N,v);let d=[0,0,0];const f=interpolate(b,v,t);switch(e){case"hsl":case"hwb":d=[interpolate(u,c,t),un_premultiply(interpolate(i,h,t),f),un_premultiply(interpolate(m,N,t),f)];break;case"lch":case"oklch":d=[un_premultiply(interpolate(i,h,t),f),un_premultiply(interpolate(m,N,t),f),interpolate(u,c,t)]}return{colorNotation:p,channels:d,alpha:f*n.alphaMultiplier,syntaxFlags:new Set([g.ColorMix])}}function interpolate(e,a,n){return Number.isNaN(e)?a:Number.isNaN(a)?e:e*n+a*(1-n)}function premultiply(e,a){return Number.isNaN(a)?e:Number.isNaN(e)?NaN:e*a}function un_premultiply(e,a){return 0===a||Number.isNaN(a)?e:Number.isNaN(e)?NaN:e/a}function hex(e){const a=toLowerCaseAZ(e[4].value);if(a.match(/[^a-f0-9]/))return!1;const n={colorNotation:_.HEX,channels:[0,0,0],alpha:1,syntaxFlags:new Set([g.Hex])},r=a.length;if(3===r){const e=a[0],r=a[1],o=a[2];return n.channels=[parseInt(e+e,16)/255,parseInt(r+r,16)/255,parseInt(o+o,16)/255],n}if(6===r){const e=a[0]+a[1],r=a[2]+a[3],o=a[4]+a[5];return n.channels=[parseInt(e,16)/255,parseInt(r,16)/255,parseInt(o,16)/255],n}if(4===r){const e=a[0],r=a[1],o=a[2],t=a[3];return n.channels=[parseInt(e+e,16)/255,parseInt(r+r,16)/255,parseInt(o+o,16)/255],n.alpha=parseInt(t+t,16)/255,n.syntaxFlags.add(g.HasAlpha),n}if(8===r){const e=a[0]+a[1],r=a[2]+a[3],o=a[4]+a[5],t=a[6]+a[7];return n.channels=[parseInt(e,16)/255,parseInt(r,16)/255,parseInt(o,16)/255],n.alpha=parseInt(t,16)/255,n.syntaxFlags.add(g.HasAlpha),n}return!1}function normalizeHue(n){if(n[0]===e.Number)return n[4].value=n[4].value%360,n[1]=n[4].value.toString(),n;if(n[0]===e.Dimension){let r=n[4].value;switch(toLowerCaseAZ(n[4].unit)){case"deg":break;case"rad":r=180*n[4].value/Math.PI;break;case"grad":r=.9*n[4].value;break;case"turn":r=360*n[4].value;break;default:return!1}return r%=360,[e.Number,r.toString(),n[2],n[3],{value:r,type:a.Number}]}return!1}function normalize_legacy_HSL_ChannelValues(n,r){const o=[];for(let t=0;t.999999&&(l=[1,0,0]),t.mapGamut(l,(e=>(e=o.OKLCH_to_OKLab(e),e=o.OKLab_to_XYZ(e),e=o.XYZ_to_lin_sRGB(e),o.gam_sRGB(e))),(e=>(e=o.lin_sRGB(e),e=o.lin_sRGB_to_XYZ(e),e=o.XYZ_to_OKLab(e),o.OKLab_to_OKLCH(e))))}function threeChannelSpaceSeparated(a,n,r,t,l){const m=toLowerCaseAZ(a.getName()),N=[],v=[],d=[],f=[];let y,C,L=!1;const H={colorNotation:r,channels:[0,0,0],alpha:1,syntaxFlags:new Set(t)};let w=N;for(let n=0;nc(a)&&a.value[0]===e.Comma))){const e=hslCommaSeparated(a);if(!1!==e)return e}{const e=hslSpaceSeparated(a,n);if(!1!==e)return e}return!1}function hslCommaSeparated(e){return threeChannelLegacySyntax(e,normalize_legacy_HSL_ChannelValues,_.HSL,[g.LegacyHSL])}function hslSpaceSeparated(e,a){return threeChannelSpaceSeparated(e,normalize_modern_HSL_ChannelValues,_.HSL,[],a)}function normalize_HWB_ChannelValues(n,r){const o=[];for(let t=0;tc(a)&&a.value[0]===e.Comma))){const e=rgbCommaSeparated(a);if(!1!==e)return e}else{const e=rgbSpaceSeparated(a,n);if(!1!==e)return e}return!1}function rgbCommaSeparated(e){return threeChannelLegacySyntax(e,normalize_legacy_sRGB_ChannelValues,_.RGB,[g.LegacyRGB])}function rgbSpaceSeparated(e,a){return threeChannelSpaceSeparated(e,normalize_modern_sRGB_ChannelValues,_.RGB,[],a)}function toPrecision(e,a=7){e=+e,a=+a;const n=(Math.floor(e)+"").length;if(a>n)return+e.toFixed(a-n);{const r=10**(n-a);return Math.round(e/r)*r}}function XYZ_D50_to_P3_Gamut(e){const a=n.XYZ_D50_to_P3(e);if(r.inGamut(a))return r.clip(a);let l=e.slice();return l=o.D50_to_D65(l),l=o.XYZ_to_OKLab(l),l=o.OKLab_to_OKLCH(l),l[0]<1e-6&&(l=[0,0,0]),l[0]>.999999&&(l=[1,0,0]),t.mapGamut(l,(e=>(e=o.OKLCH_to_OKLab(e),e=o.OKLab_to_XYZ(e),e=o.XYZ_to_lin_P3(e),o.gam_P3(e))),(e=>(e=o.lin_P3(e),e=o.lin_P3_to_XYZ(e),e=o.XYZ_to_OKLab(e),o.OKLab_to_OKLCH(e))))}function serializeWithAlpha(n,r,o,t){const l=[e.CloseParen,")",-1,-1,void 0];if("number"==typeof n.alpha){const s=Math.min(1,Math.max(0,toPrecision(Number.isNaN(n.alpha)?0:n.alpha)));return 1===toPrecision(s,4)?new m(r,l,t):new m(r,l,[...t,new N([o]),new h([e.Delim,"/",-1,-1,{value:"/"}]),new N([o]),new h([e.Number,toPrecision(s,4).toString(),-1,-1,{value:n.alpha,type:a.Integer}])])}return new m(r,l,[...t,new N([o]),new h([e.Delim,"/",-1,-1,{value:"/"}]),new N([o]),n.alpha])}function serializeP3(r,o=!0){r.channels=convertPowerlessComponentsToZeroValuesForDisplay(r.channels,r.colorNotation);let t=r.channels.map((e=>Number.isNaN(e)?0:e));r.colorNotation!==_.Display_P3&&(t=o?XYZ_D50_to_P3_Gamut(colorData_to_XYZ_D50(r).channels):n.XYZ_D50_to_P3(colorData_to_XYZ_D50(r).channels));const l=toPrecision(t[0],6),s=toPrecision(t[1],6),u=toPrecision(t[2],6),c=[e.Function,"color(",-1,-1,{value:"color"}],i=[e.Whitespace," ",-1,-1,void 0];return serializeWithAlpha(r,c,i,[new h([e.Ident,"display-p3",-1,-1,{value:"display-p3"}]),new N([i]),new h([e.Number,l.toString(),-1,-1,{value:t[0],type:a.Number}]),new N([i]),new h([e.Number,s.toString(),-1,-1,{value:t[1],type:a.Number}]),new N([i]),new h([e.Number,u.toString(),-1,-1,{value:t[2],type:a.Number}])])}function serializeRGB(r,t=!0){r.channels=convertPowerlessComponentsToZeroValuesForDisplay(r.channels,r.colorNotation);let l=r.channels.map((e=>Number.isNaN(e)?0:e));r.colorNotation===_.HWB?l=o.HWB_to_sRGB(l):r.colorNotation===_.HSL?l=o.HSL_to_sRGB(l):r.colorNotation!==_.RGB&&r.colorNotation!==_.HEX&&(l=t?XYZ_D50_to_sRGB_Gamut(colorData_to_XYZ_D50(r).channels):n.XYZ_D50_to_sRGB(colorData_to_XYZ_D50(r).channels));const s=Math.min(255,Math.max(0,Math.round(255*toPrecision(l[0])))),u=Math.min(255,Math.max(0,Math.round(255*toPrecision(l[1])))),c=Math.min(255,Math.max(0,Math.round(255*toPrecision(l[2])))),i=[e.CloseParen,")",-1,-1,void 0],p=[e.Whitespace," ",-1,-1,void 0],b=[e.Comma,",",-1,-1,void 0],g=[new h([e.Number,s.toString(),-1,-1,{value:l[0],type:a.Integer}]),new h(b),new N([p]),new h([e.Number,u.toString(),-1,-1,{value:l[1],type:a.Integer}]),new h(b),new N([p]),new h([e.Number,c.toString(),-1,-1,{value:l[2],type:a.Integer}])];if("number"==typeof r.alpha){const n=Math.min(1,Math.max(0,toPrecision(Number.isNaN(r.alpha)?0:r.alpha)));return 1===toPrecision(n,4)?new m([e.Function,"rgb(",-1,-1,{value:"rgb"}],i,g):new m([e.Function,"rgba(",-1,-1,{value:"rgba"}],i,[...g,new h(b),new N([p]),new h([e.Number,toPrecision(n,4).toString(),-1,-1,{value:r.alpha,type:a.Number}])])}return new m([e.Function,"rgba(",-1,-1,{value:"rgba"}],i,[...g,new h(b),new N([p]),r.alpha])}function serializeOKLCH(r){r.channels=convertPowerlessComponentsToZeroValuesForDisplay(r.channels,r.colorNotation);let o=r.channels.map((e=>Number.isNaN(e)?0:e));r.colorNotation!==_.OKLCH&&(o=n.XYZ_D50_to_OKLCH(colorData_to_XYZ_D50(r).channels));const t=toPrecision(o[0],6),l=toPrecision(o[1],6),s=toPrecision(o[2],6),u=[e.Function,"oklch(",-1,-1,{value:"oklch"}],c=[e.Whitespace," ",-1,-1,void 0];return serializeWithAlpha(r,u,c,[new h([e.Number,t.toString(),-1,-1,{value:o[0],type:a.Number}]),new N([c]),new h([e.Number,l.toString(),-1,-1,{value:o[1],type:a.Number}]),new N([c]),new h([e.Number,s.toString(),-1,-1,{value:o[2],type:a.Number}])])}function color(a){if(i(a)){switch(toLowerCaseAZ(a.getName())){case"rgb":case"rgba":return rgb(a,color);case"hsl":case"hsla":return hsl(a,color);case"hwb":return n=color,threeChannelSpaceSeparated(a,normalize_HWB_ChannelValues,_.HWB,[],n);case"lab":return lab(a,color);case"lch":return lch(a,color);case"oklab":return oklab(a,color);case"oklch":return oklch(a,color);case"color":return color$1(a,color);case"color-mix":return colorMix(a,color)}}var n;if(c(a)){if(a.value[0]===e.Hash)return hex(a.value);if(a.value[0]===e.Ident){const e=namedColor(a.value[4].value);return!1!==e?e:"transparent"===toLowerCaseAZ(a.value[4].value)&&{colorNotation:_.RGB,channels:[0,0,0],alpha:0,syntaxFlags:new Set([g.ColorKeyword])}}}return!1}export{_ as ColorNotation,g as SyntaxFlag,color,colorDataFitsRGB_Gamut,colorDataTo,serializeOKLCH,serializeP3,serializeRGB}; +import{TokenType as e,NumberType as a}from"@csstools/css-tokenizer";import{xyz as n,utils as r,conversions as o,calculations as t,namedColors as l}from"@csstools/color-helpers";import{isWhitespaceNode as s,isCommentNode as u,isTokenNode as c,isFunctionNode as i,TokenNode as m,FunctionNode as h,WhitespaceNode as N}from"@csstools/css-parser-algorithms";import{mathFunctionNames as b,calcFromComponentValues as p}from"@csstools/css-calc";var _,g;function colorData_to_XYZ_D50(e){switch(e.colorNotation){case _.HEX:case _.RGB:case _.sRGB:return{...e,colorNotation:_.XYZ_D50,channels:n.sRGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.Linear_sRGB:return{...e,colorNotation:_.XYZ_D50,channels:n.lin_sRGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.Display_P3:return{...e,colorNotation:_.XYZ_D50,channels:n.P3_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.Rec2020:return{...e,colorNotation:_.XYZ_D50,channels:n.rec_2020_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.A98_RGB:return{...e,colorNotation:_.XYZ_D50,channels:n.a98_RGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.ProPhoto_RGB:return{...e,colorNotation:_.XYZ_D50,channels:n.ProPhoto_RGB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.HSL:return{...e,colorNotation:_.XYZ_D50,channels:n.HSL_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.HWB:return{...e,colorNotation:_.XYZ_D50,channels:n.HWB_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.Lab:return{...e,colorNotation:_.XYZ_D50,channels:n.Lab_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.OKLab:return{...e,colorNotation:_.XYZ_D50,channels:n.OKLab_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.LCH:return{...e,colorNotation:_.XYZ_D50,channels:n.LCH_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.OKLCH:return{...e,colorNotation:_.XYZ_D50,channels:n.OKLCH_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.XYZ_D50:return{...e,colorNotation:_.XYZ_D50,channels:n.XYZ_D50_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};case _.XYZ_D65:return{...e,colorNotation:_.XYZ_D50,channels:n.XYZ_D65_to_XYZ_D50(e.channels.map((e=>Number.isNaN(e)?0:e)))};default:throw new Error("Unsupported color notation")}}!function(e){e.A98_RGB="a98-rgb",e.Display_P3="display-p3",e.HEX="hex",e.HSL="hsl",e.HWB="hwb",e.LCH="lch",e.Lab="lab",e.Linear_sRGB="srgb-linear",e.OKLCH="oklch",e.OKLab="oklab",e.ProPhoto_RGB="prophoto-rgb",e.RGB="rgb",e.sRGB="srgb",e.Rec2020="rec2020",e.XYZ_D50="xyz-d50",e.XYZ_D65="xyz-d65"}(_||(_={})),function(e){e.ColorKeyword="color-keyword",e.HasAlpha="has-alpha",e.HasDimensionValues="has-dimension-values",e.HasNoneKeywords="has-none-keywords",e.HasNumberValues="has-number-values",e.HasPercentageAlpha="has-percentage-alpha",e.HasPercentageValues="has-percentage-values",e.HasVariableAlpha="has-variable-alpha",e.Hex="hex",e.LegacyHSL="legacy-hsl",e.LegacyRGB="legacy-rgb",e.NamedColor="named-color",e.RelativeColorSyntax="relative-color-syntax",e.ColorMix="color-mix"}(g||(g={}));const v=new Set([_.A98_RGB,_.Display_P3,_.HEX,_.Linear_sRGB,_.ProPhoto_RGB,_.RGB,_.sRGB,_.Rec2020,_.XYZ_D50,_.XYZ_D65]);function colorDataTo(e,a){const r={...e};if(e.colorNotation!==a){const e=colorData_to_XYZ_D50(r);switch(a){case _.HEX:case _.RGB:r.colorNotation=_.RGB,r.channels=n.XYZ_D50_to_sRGB(e.channels);break;case _.sRGB:r.colorNotation=_.sRGB,r.channels=n.XYZ_D50_to_sRGB(e.channels);break;case _.Linear_sRGB:r.colorNotation=_.Linear_sRGB,r.channels=n.XYZ_D50_to_lin_sRGB(e.channels);break;case _.Display_P3:r.colorNotation=_.Display_P3,r.channels=n.XYZ_D50_to_P3(e.channels);break;case _.Rec2020:r.colorNotation=_.Rec2020,r.channels=n.XYZ_D50_to_rec_2020(e.channels);break;case _.ProPhoto_RGB:r.colorNotation=_.ProPhoto_RGB,r.channels=n.XYZ_D50_to_ProPhoto(e.channels);break;case _.A98_RGB:r.colorNotation=_.A98_RGB,r.channels=n.XYZ_D50_to_a98_RGB(e.channels);break;case _.HSL:r.colorNotation=_.HSL,r.channels=n.XYZ_D50_to_HSL(e.channels);break;case _.HWB:r.colorNotation=_.HWB,r.channels=n.XYZ_D50_to_HWB(e.channels);break;case _.Lab:r.colorNotation=_.Lab,r.channels=n.XYZ_D50_to_Lab(e.channels);break;case _.LCH:r.colorNotation=_.LCH,r.channels=n.XYZ_D50_to_LCH(e.channels);break;case _.OKLCH:r.colorNotation=_.OKLCH,r.channels=n.XYZ_D50_to_OKLCH(e.channels);break;case _.OKLab:r.colorNotation=_.OKLab,r.channels=n.XYZ_D50_to_OKLab(e.channels);break;case _.XYZ_D50:r.colorNotation=_.XYZ_D50,r.channels=n.XYZ_D50_to_XYZ_D50(e.channels);break;case _.XYZ_D65:r.colorNotation=_.XYZ_D65,r.channels=n.XYZ_D50_to_XYZ_D65(e.channels);break;default:throw new Error("Unsupported color notation")}}else r.channels=e.channels.map((e=>Number.isNaN(e)?0:e));if(a===e.colorNotation)r.channels=carryForwardMissingComponents(e.channels,[0,1,2],r.channels,[0,1,2]);else if(v.has(a)&&v.has(e.colorNotation))r.channels=carryForwardMissingComponents(e.channels,[0,1,2],r.channels,[0,1,2]);else switch(a){case _.HSL:switch(e.colorNotation){case _.HWB:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[0]);break;case _.Lab:case _.OKLab:r.channels=carryForwardMissingComponents(e.channels,[2],r.channels,[0]);break;case _.LCH:case _.OKLCH:r.channels=carryForwardMissingComponents(e.channels,[0,1,2],r.channels,[2,1,0])}break;case _.HWB:switch(e.colorNotation){case _.HSL:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[0]);break;case _.LCH:case _.OKLCH:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[2])}break;case _.Lab:case _.OKLab:switch(e.colorNotation){case _.HSL:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[2]);break;case _.Lab:case _.OKLab:r.channels=carryForwardMissingComponents(e.channels,[0,1,2],r.channels,[0,1,2]);break;case _.LCH:case _.OKLCH:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[0])}break;case _.LCH:case _.OKLCH:switch(e.colorNotation){case _.HSL:r.channels=carryForwardMissingComponents(e.channels,[0,1,2],r.channels,[2,1,0]);break;case _.HWB:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[2]);break;case _.Lab:case _.OKLab:r.channels=carryForwardMissingComponents(e.channels,[0],r.channels,[0]);break;case _.LCH:case _.OKLCH:r.channels=carryForwardMissingComponents(e.channels,[0,1,2],r.channels,[0,1,2])}}return r.channels=convertPowerlessComponentsToMissingComponents(r.channels,a),r}function convertPowerlessComponentsToMissingComponents(e,a){const n=[...e];switch(a){case _.HSL:reducePrecision(n[1],4)<=0&&(n[0]=NaN);break;case _.HWB:Math.max(0,reducePrecision(n[1],4))+Math.max(0,reducePrecision(n[2],4))>=100&&(n[0]=NaN);break;case _.LCH:reducePrecision(n[1],4)<=0&&(n[2]=NaN);break;case _.OKLCH:reducePrecision(n[1],6)<=0&&(n[2]=NaN)}return n}function convertPowerlessComponentsToZeroValuesForDisplay(e,a){const n=[...e];switch(a){case _.HSL:(reducePrecision(n[2])<=0||reducePrecision(n[2])>=100)&&(n[0]=NaN,n[1]=NaN),reducePrecision(n[1])<=0&&(n[0]=NaN);break;case _.HWB:Math.max(0,reducePrecision(n[1]))+Math.max(0,reducePrecision(n[2]))>=100&&(n[0]=NaN);break;case _.Lab:(reducePrecision(n[0])<=0||reducePrecision(n[0])>=100)&&(n[1]=NaN,n[2]=NaN);break;case _.LCH:reducePrecision(n[1])<=0&&(n[2]=NaN),(reducePrecision(n[0])<=0||reducePrecision(n[0])>=100)&&(n[1]=NaN,n[2]=NaN);break;case _.OKLab:(reducePrecision(n[0])<=0||reducePrecision(n[0])>=1)&&(n[1]=NaN,n[2]=NaN);break;case _.OKLCH:reducePrecision(n[1])<=0&&(n[2]=NaN),(reducePrecision(n[0])<=0||reducePrecision(n[0])>=1)&&(n[1]=NaN,n[2]=NaN)}return n}function carryForwardMissingComponents(e,a,n,r){const o=[...n];for(const n of a)Number.isNaN(e[a[n]])&&(o[r[n]]=NaN);return o}function normalizeRelativeColorDataChannels(e){const a=new Map;switch(e.colorNotation){case _.RGB:case _.HEX:a.set("r",dummyNumberToken(255*e.channels[0])),a.set("g",dummyNumberToken(255*e.channels[1])),a.set("b",dummyNumberToken(255*e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha));break;case _.HSL:a.set("h",dummyNumberToken(e.channels[0])),a.set("s",dummyNumberToken(e.channels[1])),a.set("l",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha));break;case _.HWB:a.set("h",dummyNumberToken(e.channels[0])),a.set("w",dummyNumberToken(e.channels[1])),a.set("b",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha));break;case _.Lab:case _.OKLab:a.set("l",dummyNumberToken(e.channels[0])),a.set("a",dummyNumberToken(e.channels[1])),a.set("b",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha));break;case _.LCH:case _.OKLCH:a.set("l",dummyNumberToken(e.channels[0])),a.set("c",dummyNumberToken(e.channels[1])),a.set("h",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha));break;case _.sRGB:case _.A98_RGB:case _.Display_P3:case _.Rec2020:case _.Linear_sRGB:case _.ProPhoto_RGB:a.set("r",dummyNumberToken(e.channels[0])),a.set("g",dummyNumberToken(e.channels[1])),a.set("b",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha));break;case _.XYZ_D50:case _.XYZ_D65:a.set("x",dummyNumberToken(e.channels[0])),a.set("y",dummyNumberToken(e.channels[1])),a.set("z",dummyNumberToken(e.channels[2])),"number"==typeof e.alpha&&a.set("alpha",dummyNumberToken(e.alpha))}return a}function noneToZeroInRelativeColorDataChannels(e){const a=new Map;for(const[n,r]of e)Number.isNaN(r[4].value)?a.set(n,dummyNumberToken(0)):a.set(n,r);return a}function dummyNumberToken(n){return[e.Number,n.toString(),-1,-1,{value:n,type:a.Number}]}function reducePrecision(e,a=7){if(Number.isNaN(e))return 0;const n=Math.pow(10,a);return Math.round(e*n)/n}function colorDataFitsRGB_Gamut(e){const a=JSON.parse(JSON.stringify(e));a.channels=convertPowerlessComponentsToZeroValuesForDisplay(a.channels,a.colorNotation);return!colorDataTo(a,_.RGB).channels.find((e=>e<-1e-5||e>1.00001))}function normalize(e,a,n,r){return Math.min(Math.max(e/a,n),r)}const d=/[A-Z]/g;function toLowerCaseAZ(e){return e.replace(d,(e=>String.fromCharCode(e.charCodeAt(0)+32)))}function normalize_Color_ChannelValues(n,r,o){if(n[0]===e.Ident&&"none"===toLowerCaseAZ(n[4].value))return o.syntaxFlags.add(g.HasNoneKeywords),[e.Number,"none",n[2],n[3],{value:NaN,type:a.Number}];if(n[0]===e.Percentage){3!==r&&o.syntaxFlags.add(g.HasPercentageValues);let t=normalize(n[4].value,100,-1/0,1/0);return 3===r&&(t=normalize(n[4].value,100,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}if(n[0]===e.Number){3!==r&&o.syntaxFlags.add(g.HasNumberValues);let t=normalize(n[4].value,1,-1/0,1/0);return 3===r&&(t=normalize(n[4].value,1,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}return!1}const f=new Set(["srgb","srgb-linear","display-p3","a98-rgb","prophoto-rgb","rec2020","xyz","xyz-d50","xyz-d65"]);function color$1(a,n){const r=[],o=[],t=[],l=[];let h,N,v=!1,d=!1;const y={colorNotation:_.sRGB,channels:[0,0,0],alpha:1,syntaxFlags:new Set([])};let C=r;for(let _=0;_=0){l=m.value[4].value;continue}}return!1}if(!t)return!1;r.push({color:t,percentage:l}),t=!1,l=!1}}if(t&&r.push({color:t,percentage:l}),2!==r.length)return!1;let m=r[0].percentage,h=r[1].percentage;return(!1===m||!(m<0||m>100))&&((!1===h||!(h<0||h>100))&&(!1===m&&!1===h?(m=50,h=50):!1!==m&&!1===h?h=100-m:!1===m&&!1!==h&&(m=100-h),(0!==m||0!==h)&&(!1!==m&&!1!==h&&(m+h>100&&(m=m/(m+h)*100,h=h/(m+h)*100),m+h<100&&(o=(m+h)/100,m=m/(m+h)*100,h=h/(m+h)*100),{a:{color:r[0].color,percentage:m},b:{color:r[1].color,percentage:h},alphaMultiplier:o}))))}function colorMixRectangular(e,a){if(!a)return!1;const n=a.a.color,r=a.b.color,o=a.a.percentage/100;let t=n.channels,l=r.channels,s=_.RGB,u=n.alpha;if("number"!=typeof u)return!1;let c=r.alpha;if("number"!=typeof c)return!1;switch(u=Number.isNaN(u)?c:u,c=Number.isNaN(c)?u:c,e){case"srgb":s=_.RGB;break;case"srgb-linear":s=_.Linear_sRGB;break;case"lab":s=_.Lab;break;case"oklab":s=_.OKLab;break;case"xyz-d50":s=_.XYZ_D50;break;case"xyz":case"xyz-d65":s=_.XYZ_D65}t=colorDataTo(n,s).channels,l=colorDataTo(r,s).channels,t[0]=premultiply(t[0],u),t[1]=premultiply(t[1],u),t[2]=premultiply(t[2],u),l[0]=premultiply(l[0],c),l[1]=premultiply(l[1],c),l[2]=premultiply(l[2],c);const i=interpolate(u,c,o);return{colorNotation:s,channels:[un_premultiply(interpolate(t[0],l[0],o),i),un_premultiply(interpolate(t[1],l[1],o),i),un_premultiply(interpolate(t[2],l[2],o),i)],alpha:i*a.alphaMultiplier,syntaxFlags:new Set([g.ColorMix])}}function colorMixPolar(e,a,n){if(!n)return!1;const r=n.a.color,o=n.b.color,t=n.a.percentage/100;let l=r.channels,s=o.channels,u=0,c=0,i=0,m=0,h=0,N=0,b=_.RGB,p=r.alpha;if("number"!=typeof p)return!1;let v=o.alpha;if("number"!=typeof v)return!1;switch(p=Number.isNaN(p)?v:p,v=Number.isNaN(v)?p:v,e){case"hsl":b=_.HSL;break;case"hwb":b=_.HWB;break;case"lch":b=_.LCH;break;case"oklch":b=_.OKLCH}switch(l=colorDataTo(r,b).channels,s=colorDataTo(o,b).channels,e){case"hsl":case"hwb":u=l[0],c=s[0],i=l[1],m=s[1],h=l[2],N=s[2];break;case"lch":case"oklch":i=l[0],m=s[0],h=l[1],N=s[1],u=l[2],c=s[2]}if(!Number.isNaN(u)&&!Number.isNaN(c)){const e=c-u;switch(a){case"shorter":e>180?u+=360:e<-180&&(c+=360);break;case"longer":-1800?u+=360:c+=360);break;case"increasing":e<0&&(c+=360);break;case"decreasing":e>0&&(u+=360);break;default:throw new Error("Unknown hue interpolation method")}}i=premultiply(i,p),h=premultiply(h,p),m=premultiply(m,v),N=premultiply(N,v);let d=[0,0,0];const f=interpolate(p,v,t);switch(e){case"hsl":case"hwb":d=[interpolate(u,c,t),un_premultiply(interpolate(i,m,t),f),un_premultiply(interpolate(h,N,t),f)];break;case"lch":case"oklch":d=[un_premultiply(interpolate(i,m,t),f),un_premultiply(interpolate(h,N,t),f),interpolate(u,c,t)]}return{colorNotation:b,channels:d,alpha:f*n.alphaMultiplier,syntaxFlags:new Set([g.ColorMix])}}function interpolate(e,a,n){return Number.isNaN(e)?a:Number.isNaN(a)?e:e*n+a*(1-n)}function premultiply(e,a){return Number.isNaN(a)?e:Number.isNaN(e)?NaN:e*a}function un_premultiply(e,a){return 0===a||Number.isNaN(a)?e:Number.isNaN(e)?NaN:e/a}function hex(e){const a=toLowerCaseAZ(e[4].value);if(a.match(/[^a-f0-9]/))return!1;const n={colorNotation:_.HEX,channels:[0,0,0],alpha:1,syntaxFlags:new Set([g.Hex])},r=a.length;if(3===r){const e=a[0],r=a[1],o=a[2];return n.channels=[parseInt(e+e,16)/255,parseInt(r+r,16)/255,parseInt(o+o,16)/255],n}if(6===r){const e=a[0]+a[1],r=a[2]+a[3],o=a[4]+a[5];return n.channels=[parseInt(e,16)/255,parseInt(r,16)/255,parseInt(o,16)/255],n}if(4===r){const e=a[0],r=a[1],o=a[2],t=a[3];return n.channels=[parseInt(e+e,16)/255,parseInt(r+r,16)/255,parseInt(o+o,16)/255],n.alpha=parseInt(t+t,16)/255,n.syntaxFlags.add(g.HasAlpha),n}if(8===r){const e=a[0]+a[1],r=a[2]+a[3],o=a[4]+a[5],t=a[6]+a[7];return n.channels=[parseInt(e,16)/255,parseInt(r,16)/255,parseInt(o,16)/255],n.alpha=parseInt(t,16)/255,n.syntaxFlags.add(g.HasAlpha),n}return!1}function normalizeHue(n){if(n[0]===e.Number)return n[4].value=n[4].value%360,n[1]=n[4].value.toString(),n;if(n[0]===e.Dimension){let r=n[4].value;switch(toLowerCaseAZ(n[4].unit)){case"deg":break;case"rad":r=180*n[4].value/Math.PI;break;case"grad":r=.9*n[4].value;break;case"turn":r=360*n[4].value;break;default:return!1}return r%=360,[e.Number,r.toString(),n[2],n[3],{value:r,type:a.Number}]}return!1}function normalize_legacy_HSL_ChannelValues(n,r,o){if(0===r){const a=normalizeHue(n);return!1!==a&&(n[0]===e.Dimension&&o.syntaxFlags.add(g.HasDimensionValues),a)}if(n[0]===e.Percentage){3===r?o.syntaxFlags.add(g.HasPercentageAlpha):o.syntaxFlags.add(g.HasPercentageValues);let t=normalize(n[4].value,1,0,100);return 3===r&&(t=normalize(n[4].value,100,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}if(n[0]===e.Number){if(3!==r)return!1;let o=normalize(n[4].value,1,0,100);return 3===r&&(o=normalize(n[4].value,1,0,1)),[e.Number,o.toString(),n[2],n[3],{value:o,type:a.Number}]}return!1}function normalize_modern_HSL_ChannelValues(n,r,o){if(n[0]===e.Ident&&"none"===toLowerCaseAZ(n[4].value))return o.syntaxFlags.add(g.HasNoneKeywords),[e.Number,"none",n[2],n[3],{value:NaN,type:a.Number}];if(0===r){const a=normalizeHue(n);return!1!==a&&(n[0]===e.Dimension&&o.syntaxFlags.add(g.HasDimensionValues),a)}if(n[0]===e.Percentage){3===r?o.syntaxFlags.add(g.HasPercentageAlpha):o.syntaxFlags.add(g.HasPercentageValues);let t=normalize(n[4].value,1,0,100);return 3===r&&(t=normalize(n[4].value,100,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}if(n[0]===e.Number){3!==r&&o.syntaxFlags.add(g.HasNumberValues);let t=normalize(n[4].value,1,0,100);return 3===r&&(t=normalize(n[4].value,1,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}return!1}function threeChannelLegacySyntax(a,n,r,o){const t=[],l=[],m=[],h=[],N={colorNotation:r,channels:[0,0,0],alpha:1,syntaxFlags:new Set(o)};let _=t;for(let n=0;n.999999&&(l=[1,0,0]),t.mapGamut(l,(e=>(e=o.OKLCH_to_OKLab(e),e=o.OKLab_to_XYZ(e),e=o.XYZ_to_lin_sRGB(e),o.gam_sRGB(e))),(e=>(e=o.lin_sRGB(e),e=o.lin_sRGB_to_XYZ(e),e=o.XYZ_to_OKLab(e),o.OKLab_to_OKLCH(e))))}function threeChannelSpaceSeparated(a,n,r,t,l){const h=toLowerCaseAZ(a.getName()),N=[],v=[],d=[],f=[];let y,C,L=!1;const H={colorNotation:r,channels:[0,0,0],alpha:1,syntaxFlags:new Set(t)};let w=N;for(let n=0;nc(a)&&a.value[0]===e.Comma))){const e=hslCommaSeparated(a);if(!1!==e)return e}{const e=hslSpaceSeparated(a,n);if(!1!==e)return e}return!1}function hslCommaSeparated(e){return threeChannelLegacySyntax(e,normalize_legacy_HSL_ChannelValues,_.HSL,[g.LegacyHSL])}function hslSpaceSeparated(e,a){return threeChannelSpaceSeparated(e,normalize_modern_HSL_ChannelValues,_.HSL,[],a)}function normalize_HWB_ChannelValues(n,r,o){if(n[0]===e.Ident&&"none"===toLowerCaseAZ(n[4].value))return o.syntaxFlags.add(g.HasNoneKeywords),[e.Number,"none",n[2],n[3],{value:NaN,type:a.Number}];if(0===r){const a=normalizeHue(n);return!1!==a&&(n[0]===e.Dimension&&o.syntaxFlags.add(g.HasDimensionValues),a)}if(n[0]===e.Percentage){3===r?o.syntaxFlags.add(g.HasPercentageAlpha):o.syntaxFlags.add(g.HasPercentageValues);let t=normalize(n[4].value,1,0,100);return 3===r&&(t=normalize(n[4].value,100,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}if(n[0]===e.Number){3!==r&&o.syntaxFlags.add(g.HasNumberValues);let t=normalize(n[4].value,1,0,100);return 3===r&&(t=normalize(n[4].value,1,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}return!1}function normalize_Lab_ChannelValues(n,r,o){if(n[0]===e.Ident&&"none"===toLowerCaseAZ(n[4].value))return o.syntaxFlags.add(g.HasNoneKeywords),[e.Number,"none",n[2],n[3],{value:NaN,type:a.Number}];if(n[0]===e.Percentage){3!==r&&o.syntaxFlags.add(g.HasPercentageValues);let t=normalize(n[4].value,1,0,100);return 1===r||2===r?t=normalize(n[4].value,.8,-1/0,1/0):3===r&&(t=normalize(n[4].value,100,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}if(n[0]===e.Number){3!==r&&o.syntaxFlags.add(g.HasNumberValues);let t=normalize(n[4].value,1,0,100);return 1===r||2===r?t=normalize(n[4].value,1,-1/0,1/0):3===r&&(t=normalize(n[4].value,1,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}return!1}function lab(e,a){return threeChannelSpaceSeparated(e,normalize_Lab_ChannelValues,_.Lab,[],a)}function normalize_LCH_ChannelValues(n,r,o){if(n[0]===e.Ident&&"none"===toLowerCaseAZ(n[4].value))return o.syntaxFlags.add(g.HasNoneKeywords),[e.Number,"none",n[2],n[3],{value:NaN,type:a.Number}];if(2===r){const a=normalizeHue(n);return!1!==a&&(n[0]===e.Dimension&&o.syntaxFlags.add(g.HasDimensionValues),a)}if(n[0]===e.Percentage){3!==r&&o.syntaxFlags.add(g.HasPercentageValues);let t=normalize(n[4].value,1,0,100);return 1===r?t=normalize(n[4].value,100/150,0,1/0):3===r&&(t=normalize(n[4].value,100,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}if(n[0]===e.Number){3!==r&&o.syntaxFlags.add(g.HasNumberValues);let t=normalize(n[4].value,1,0,100);return 1===r?t=normalize(n[4].value,1,0,1/0):3===r&&(t=normalize(n[4].value,1,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}return!1}function lch(e,a){return threeChannelSpaceSeparated(e,normalize_LCH_ChannelValues,_.LCH,[],a)}const H=new Map;for(const[e,a]of Object.entries(l))H.set(e,a);function namedColor(e){const a=H.get(toLowerCaseAZ(e));return!!a&&{colorNotation:_.RGB,channels:[a[0]/255,a[1]/255,a[2]/255],alpha:1,syntaxFlags:new Set([g.ColorKeyword,g.NamedColor])}}function normalize_OKLab_ChannelValues(n,r,o){if(n[0]===e.Ident&&"none"===toLowerCaseAZ(n[4].value))return o.syntaxFlags.add(g.HasNoneKeywords),[e.Number,"none",n[2],n[3],{value:NaN,type:a.Number}];if(n[0]===e.Percentage){3!==r&&o.syntaxFlags.add(g.HasPercentageValues);let t=normalize(n[4].value,100,0,1);return 1===r||2===r?t=normalize(n[4].value,250,-1/0,1/0):3===r&&(t=normalize(n[4].value,100,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}if(n[0]===e.Number){3!==r&&o.syntaxFlags.add(g.HasNumberValues);let t=normalize(n[4].value,1,0,1);return 1===r||2===r?t=normalize(n[4].value,1,-1/0,1/0):3===r&&(t=normalize(n[4].value,1,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}return!1}function oklab(e,a){return threeChannelSpaceSeparated(e,normalize_OKLab_ChannelValues,_.OKLab,[],a)}function normalize_OKLCH_ChannelValues(n,r,o){if(n[0]===e.Ident&&"none"===toLowerCaseAZ(n[4].value))return o.syntaxFlags.add(g.HasNoneKeywords),[e.Number,"none",n[2],n[3],{value:NaN,type:a.Number}];if(2===r){const a=normalizeHue(n);return!1!==a&&(n[0]===e.Dimension&&o.syntaxFlags.add(g.HasDimensionValues),a)}if(n[0]===e.Percentage){3!==r&&o.syntaxFlags.add(g.HasPercentageValues);let t=normalize(n[4].value,100,0,1);return 1===r?t=normalize(n[4].value,250,0,1/0):3===r&&(t=normalize(n[4].value,100,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}if(n[0]===e.Number){3!==r&&o.syntaxFlags.add(g.HasNumberValues);let t=normalize(n[4].value,1,0,1);return 1===r?t=normalize(n[4].value,1,0,1/0):3===r&&(t=normalize(n[4].value,1,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}return!1}function oklch(e,a){return threeChannelSpaceSeparated(e,normalize_OKLCH_ChannelValues,_.OKLCH,[],a)}function normalize_legacy_sRGB_ChannelValues(n,r,o){if(n[0]===e.Percentage){3===r?o.syntaxFlags.add(g.HasPercentageAlpha):o.syntaxFlags.add(g.HasPercentageValues);const t=normalize(n[4].value,100,0,1);return[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}if(n[0]===e.Number){3!==r&&o.syntaxFlags.add(g.HasNumberValues);let t=normalize(n[4].value,255,0,1);return 3===r&&(t=normalize(n[4].value,1,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}return!1}function normalize_modern_sRGB_ChannelValues(n,r,o){if(n[0]===e.Ident&&"none"===toLowerCaseAZ(n[4].value))return o.syntaxFlags.add(g.HasNoneKeywords),[e.Number,"none",n[2],n[3],{value:NaN,type:a.Number}];if(n[0]===e.Percentage){3!==r&&o.syntaxFlags.add(g.HasPercentageValues);const t=normalize(n[4].value,100,0,1);return[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}if(n[0]===e.Number){3!==r&&o.syntaxFlags.add(g.HasNumberValues);let t=normalize(n[4].value,255,0,1);return 3===r&&(t=normalize(n[4].value,1,0,1)),[e.Number,t.toString(),n[2],n[3],{value:t,type:a.Number}]}return!1}function rgb(a,n){if(a.value.some((a=>c(a)&&a.value[0]===e.Comma))){const e=rgbCommaSeparated(a);if(!1!==e)return(!e.syntaxFlags.has(g.HasNumberValues)||!e.syntaxFlags.has(g.HasPercentageValues))&&e}else{const e=rgbSpaceSeparated(a,n);if(!1!==e)return e}return!1}function rgbCommaSeparated(e){return threeChannelLegacySyntax(e,normalize_legacy_sRGB_ChannelValues,_.RGB,[g.LegacyRGB])}function rgbSpaceSeparated(e,a){return threeChannelSpaceSeparated(e,normalize_modern_sRGB_ChannelValues,_.RGB,[],a)}function toPrecision(e,a=7){e=+e,a=+a;const n=(Math.floor(e)+"").length;if(a>n)return+e.toFixed(a-n);{const r=10**(n-a);return Math.round(e/r)*r}}function XYZ_D50_to_P3_Gamut(e){const a=n.XYZ_D50_to_P3(e);if(r.inGamut(a))return r.clip(a);let l=e.slice();return l=o.D50_to_D65(l),l=o.XYZ_to_OKLab(l),l=o.OKLab_to_OKLCH(l),l[0]<1e-6&&(l=[0,0,0]),l[0]>.999999&&(l=[1,0,0]),t.mapGamut(l,(e=>(e=o.OKLCH_to_OKLab(e),e=o.OKLab_to_XYZ(e),e=o.XYZ_to_lin_P3(e),o.gam_P3(e))),(e=>(e=o.lin_P3(e),e=o.lin_P3_to_XYZ(e),e=o.XYZ_to_OKLab(e),o.OKLab_to_OKLCH(e))))}function serializeWithAlpha(n,r,o,t){const l=[e.CloseParen,")",-1,-1,void 0];if("number"==typeof n.alpha){const s=Math.min(1,Math.max(0,toPrecision(Number.isNaN(n.alpha)?0:n.alpha)));return 1===toPrecision(s,4)?new h(r,l,t):new h(r,l,[...t,new N([o]),new m([e.Delim,"/",-1,-1,{value:"/"}]),new N([o]),new m([e.Number,toPrecision(s,4).toString(),-1,-1,{value:n.alpha,type:a.Integer}])])}return new h(r,l,[...t,new N([o]),new m([e.Delim,"/",-1,-1,{value:"/"}]),new N([o]),n.alpha])}function serializeP3(r,o=!0){r.channels=convertPowerlessComponentsToZeroValuesForDisplay(r.channels,r.colorNotation);let t=r.channels.map((e=>Number.isNaN(e)?0:e));r.colorNotation!==_.Display_P3&&(t=o?XYZ_D50_to_P3_Gamut(colorData_to_XYZ_D50(r).channels):n.XYZ_D50_to_P3(colorData_to_XYZ_D50(r).channels));const l=toPrecision(t[0],6),s=toPrecision(t[1],6),u=toPrecision(t[2],6),c=[e.Function,"color(",-1,-1,{value:"color"}],i=[e.Whitespace," ",-1,-1,void 0];return serializeWithAlpha(r,c,i,[new m([e.Ident,"display-p3",-1,-1,{value:"display-p3"}]),new N([i]),new m([e.Number,l.toString(),-1,-1,{value:t[0],type:a.Number}]),new N([i]),new m([e.Number,s.toString(),-1,-1,{value:t[1],type:a.Number}]),new N([i]),new m([e.Number,u.toString(),-1,-1,{value:t[2],type:a.Number}])])}function serializeRGB(r,t=!0){r.channels=convertPowerlessComponentsToZeroValuesForDisplay(r.channels,r.colorNotation);let l=r.channels.map((e=>Number.isNaN(e)?0:e));r.colorNotation===_.HWB?l=o.HWB_to_sRGB(l):r.colorNotation===_.HSL?l=o.HSL_to_sRGB(l):r.colorNotation!==_.RGB&&r.colorNotation!==_.HEX&&(l=t?XYZ_D50_to_sRGB_Gamut(colorData_to_XYZ_D50(r).channels):n.XYZ_D50_to_sRGB(colorData_to_XYZ_D50(r).channels));const s=Math.min(255,Math.max(0,Math.round(255*toPrecision(l[0])))),u=Math.min(255,Math.max(0,Math.round(255*toPrecision(l[1])))),c=Math.min(255,Math.max(0,Math.round(255*toPrecision(l[2])))),i=[e.CloseParen,")",-1,-1,void 0],b=[e.Whitespace," ",-1,-1,void 0],p=[e.Comma,",",-1,-1,void 0],g=[new m([e.Number,s.toString(),-1,-1,{value:l[0],type:a.Integer}]),new m(p),new N([b]),new m([e.Number,u.toString(),-1,-1,{value:l[1],type:a.Integer}]),new m(p),new N([b]),new m([e.Number,c.toString(),-1,-1,{value:l[2],type:a.Integer}])];if("number"==typeof r.alpha){const n=Math.min(1,Math.max(0,toPrecision(Number.isNaN(r.alpha)?0:r.alpha)));return 1===toPrecision(n,4)?new h([e.Function,"rgb(",-1,-1,{value:"rgb"}],i,g):new h([e.Function,"rgba(",-1,-1,{value:"rgba"}],i,[...g,new m(p),new N([b]),new m([e.Number,toPrecision(n,4).toString(),-1,-1,{value:r.alpha,type:a.Number}])])}return new h([e.Function,"rgba(",-1,-1,{value:"rgba"}],i,[...g,new m(p),new N([b]),r.alpha])}function serializeOKLCH(r){r.channels=convertPowerlessComponentsToZeroValuesForDisplay(r.channels,r.colorNotation);let o=r.channels.map((e=>Number.isNaN(e)?0:e));r.colorNotation!==_.OKLCH&&(o=n.XYZ_D50_to_OKLCH(colorData_to_XYZ_D50(r).channels));const t=toPrecision(o[0],6),l=toPrecision(o[1],6),s=toPrecision(o[2],6),u=[e.Function,"oklch(",-1,-1,{value:"oklch"}],c=[e.Whitespace," ",-1,-1,void 0];return serializeWithAlpha(r,u,c,[new m([e.Number,t.toString(),-1,-1,{value:o[0],type:a.Number}]),new N([c]),new m([e.Number,l.toString(),-1,-1,{value:o[1],type:a.Number}]),new N([c]),new m([e.Number,s.toString(),-1,-1,{value:o[2],type:a.Number}])])}function color(a){if(i(a)){switch(toLowerCaseAZ(a.getName())){case"rgb":case"rgba":return rgb(a,color);case"hsl":case"hsla":return hsl(a,color);case"hwb":return n=color,threeChannelSpaceSeparated(a,normalize_HWB_ChannelValues,_.HWB,[],n);case"lab":return lab(a,color);case"lch":return lch(a,color);case"oklab":return oklab(a,color);case"oklch":return oklch(a,color);case"color":return color$1(a,color);case"color-mix":return colorMix(a,color)}}var n;if(c(a)){if(a.value[0]===e.Hash)return hex(a.value);if(a.value[0]===e.Ident){const e=namedColor(a.value[4].value);return!1!==e?e:"transparent"===toLowerCaseAZ(a.value[4].value)&&{colorNotation:_.RGB,channels:[0,0,0],alpha:0,syntaxFlags:new Set([g.ColorKeyword])}}}return!1}export{_ as ColorNotation,g as SyntaxFlag,color,colorDataFitsRGB_Gamut,colorDataTo,serializeOKLCH,serializeP3,serializeRGB}; diff --git a/packages/css-color-parser/src/functions/color-normalize-channel-values.ts b/packages/css-color-parser/src/functions/color-normalize-channel-values.ts index 154a1cf37..5cd0584ae 100644 --- a/packages/css-color-parser/src/functions/color-normalize-channel-values.ts +++ b/packages/css-color-parser/src/functions/color-normalize-channel-values.ts @@ -1,79 +1,68 @@ import type { ColorData } from '../color-data'; -import { CSSToken, NumberType, TokenNumber, TokenType } from '@csstools/css-tokenizer'; +import { CSSToken, NumberType, TokenType } from '@csstools/css-tokenizer'; import { SyntaxFlag } from '../color-data'; import { normalize } from './normalize'; import { toLowerCaseAZ } from '../util/to-lower-case-a-z'; -export function normalize_Color_ChannelValues(tokens: Array, colorData: ColorData): Array | false { - const result: Array = []; +export function normalize_Color_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false { + if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { + colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index]; - - if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { - colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); + return [ + TokenType.Number, + 'none', + token[2], + token[3], + { + value: NaN, + type: NumberType.Number, + }, + ]; + } - result.push([ - TokenType.Number, - 'none', - token[2], - token[3], - { - value: NaN, - type: NumberType.Number, - }, - ]); - continue; + if (token[0] === TokenType.Percentage) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); } - if (token[0] === TokenType.Percentage) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); - } - - let value = normalize(token[4].value, 100, -Infinity, Infinity); - if (index === 3) { - value = normalize(token[4].value, 100, 0, 1); - } - - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 100, -Infinity, Infinity); + if (index === 3) { + value = normalize(token[4].value, 100, 0, 1); } - if (token[0] === TokenType.Number) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); - } + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; + } - let value = normalize(token[4].value, 1, -Infinity, Infinity); - if (index === 3) { - value = normalize(token[4].value, 1, 0, 1); - } + if (token[0] === TokenType.Number) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); + } - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 1, -Infinity, Infinity); + if (index === 3) { + value = normalize(token[4].value, 1, 0, 1); } - return false; + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; } - return result; + return false; } diff --git a/packages/css-color-parser/src/functions/color.ts b/packages/css-color-parser/src/functions/color.ts index 64f7820d2..9cc4fdf58 100644 --- a/packages/css-color-parser/src/functions/color.ts +++ b/packages/css-color-parser/src/functions/color.ts @@ -2,7 +2,7 @@ import { ColorData, SyntaxFlag, colorDataTo, noneToZeroInRelativeColorDataChanne import type { ColorParser } from '../color-parser'; import { ColorNotation } from '../color-notation'; import { ComponentValue, FunctionNode, TokenNode, isCommentNode, isFunctionNode, isTokenNode, isWhitespaceNode } from '@csstools/css-parser-algorithms'; -import { CSSToken, TokenDimension, TokenNumber, TokenPercentage, TokenType } from '@csstools/css-tokenizer'; +import { TokenDimension, TokenNumber, TokenPercentage, TokenType } from '@csstools/css-tokenizer'; import { normalize_Color_ChannelValues } from './color-normalize-channel-values'; import { toLowerCaseAZ } from '../util/to-lower-case-a-z'; import { calcFromComponentValues, mathFunctionNames } from '@csstools/css-calc'; @@ -187,38 +187,58 @@ export function color(colorFunctionNode: FunctionNode, colorParser: ColorParser) return false; } - const channelValues: Array = [ - channel1[0].value, - channel2[0].value, - channel3[0].value, + const channelValue1 = normalize_Color_ChannelValues(channel1[0].value, 0, colorData); + if (!channelValue1 || channelValue1[0] !== TokenType.Number) { + return false; + } + + const channelValue2 = normalize_Color_ChannelValues(channel2[0].value, 1, colorData); + if (!channelValue2 || channelValue2[0] !== TokenType.Number) { + return false; + } + + const channelValue3 = normalize_Color_ChannelValues(channel3[0].value, 2, colorData); + if (!channelValue3 || channelValue3[0] !== TokenType.Number) { + return false; + } + + const channelValues: Array = [ + channelValue1, + channelValue2, + channelValue3, ]; if (channelAlpha.length === 1) { colorData.syntaxFlags.add(SyntaxFlag.HasAlpha); if (isTokenNode(channelAlpha[0])) { - channelValues.push(channelAlpha[0].value); + const channelValueAlpha = normalize_Color_ChannelValues(channelAlpha[0].value, 3, colorData); + if (!channelValueAlpha || channelValueAlpha[0] !== TokenType.Number) { + return false; + } + + channelValues.push(channelValueAlpha); } else { colorData.alpha = channelAlpha[0]; } } else if (relativeColorChannels && relativeColorChannels.has('alpha')) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - channelValues.push(relativeColorChannels.get('alpha')!); - } + const channelValueAlpha = normalize_Color_ChannelValues(relativeColorChannels.get('alpha')!, 3, colorData); + if (!channelValueAlpha || channelValueAlpha[0] !== TokenType.Number) { + return false; + } - const normalizedChannelValues = normalize_Color_ChannelValues(channelValues, colorData); - if (normalizedChannelValues === false) { - return false; + channelValues.push(channelValueAlpha); } colorData.channels = [ - normalizedChannelValues[0][4].value, - normalizedChannelValues[1][4].value, - normalizedChannelValues[2][4].value, + channelValues[0][4].value, + channelValues[1][4].value, + channelValues[2][4].value, ]; - if (normalizedChannelValues.length === 4) { - colorData.alpha = normalizedChannelValues[3][4].value; + if (channelValues.length === 4) { + colorData.alpha = channelValues[3][4].value; } return colorData; diff --git a/packages/css-color-parser/src/functions/hsl-normalize-channel-values.ts b/packages/css-color-parser/src/functions/hsl-normalize-channel-values.ts index e07a48e7c..746ca487f 100644 --- a/packages/css-color-parser/src/functions/hsl-normalize-channel-values.ts +++ b/packages/css-color-parser/src/functions/hsl-normalize-channel-values.ts @@ -1,175 +1,147 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken, NumberType, TokenType } from '@csstools/css-tokenizer'; import { SyntaxFlag } from '../color-data'; import { normalize } from './normalize'; import { normalizeHue } from './hue-normalize-channel-value'; import { toLowerCaseAZ } from '../util/to-lower-case-a-z'; -export function normalize_legacy_HSL_ChannelValues(tokens: Array, colorData: ColorData): Array | false { - const result: Array = []; +export function normalize_legacy_HSL_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false { + if (index === 0) { + const hueToken = normalizeHue(token); + if (hueToken === false) { + return false; + } - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index]; + if (token[0] === TokenType.Dimension) { + colorData.syntaxFlags.add(SyntaxFlag.HasDimensionValues); + } - if (index === 0) { - const hueToken = normalizeHue(token); - if (hueToken === false) { - return false; - } + return hueToken; + } - if (token[0] === TokenType.Dimension) { - colorData.syntaxFlags.add(SyntaxFlag.HasDimensionValues); - } + if (token[0] === TokenType.Percentage) { + if (index === 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageAlpha); + } else { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); + } - result.push(hueToken); - continue; + let value = normalize(token[4].value, 1, 0, 100); + if (index === 3) { + value = normalize(token[4].value, 100, 0, 1); } - if (token[0] === TokenType.Percentage) { - if (index === 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageAlpha); - } else { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); - } - - let value = normalize(token[4].value, 1, 0, 100); - if (index === 3) { - value = normalize(token[4].value, 100, 0, 1); - } - - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; + } + + if (token[0] === TokenType.Number) { + if (index !== 3) { + return false; } - if (token[0] === TokenType.Number) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); - } - - let value = normalize(token[4].value, 1, 0, 100); - if (index === 3) { - value = normalize(token[4].value, 1, 0, 1); - } - - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 1, 0, 100); + if (index === 3) { + value = normalize(token[4].value, 1, 0, 1); } - return false; + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; } - if (colorData.syntaxFlags.has(SyntaxFlag.HasNumberValues)) { - return false; + return false; +} + +export function normalize_modern_HSL_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false { + if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { + colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); + + return [ + TokenType.Number, + 'none', + token[2], + token[3], + { + value: NaN, + type: NumberType.Number, + }, + ]; } - return result; -} + if (index === 0) { + const hueToken = normalizeHue(token); + if (hueToken === false) { + return false; + } -export function normalize_modern_HSL_ChannelValues(tokens: Array, colorData: ColorData): Array | false { - const result: Array = []; - - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index]; - - if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { - colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); - - result.push([ - TokenType.Number, - 'none', - token[2], - token[3], - { - value: NaN, - type: NumberType.Number, - }, - ]); - continue; + if (token[0] === TokenType.Dimension) { + colorData.syntaxFlags.add(SyntaxFlag.HasDimensionValues); } - if (index === 0) { - const hueToken = normalizeHue(token); - if (hueToken === false) { - return false; - } + return hueToken; + } - if (token[0] === TokenType.Dimension) { - colorData.syntaxFlags.add(SyntaxFlag.HasDimensionValues); - } + if (token[0] === TokenType.Percentage) { + if (index === 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageAlpha); + } else { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); + } - result.push(hueToken); - continue; + let value = normalize(token[4].value, 1, 0, 100); + if (index === 3) { + value = normalize(token[4].value, 100, 0, 1); } - if (token[0] === TokenType.Percentage) { - if (index === 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageAlpha); - } else { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); - } - - let value = normalize(token[4].value, 1, 0, 100); - if (index === 3) { - value = normalize(token[4].value, 100, 0, 1); - } - - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; + } + + if (token[0] === TokenType.Number) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); } - if (token[0] === TokenType.Number) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); - } - - let value = normalize(token[4].value, 1, 0, 100); - if (index === 3) { - value = normalize(token[4].value, 1, 0, 1); - } - - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 1, 0, 100); + if (index === 3) { + value = normalize(token[4].value, 1, 0, 1); } - return false; + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; } - return result; + return false; } diff --git a/packages/css-color-parser/src/functions/hwb-normalize-channel-values.ts b/packages/css-color-parser/src/functions/hwb-normalize-channel-values.ts index 15f5830f9..b76ae964c 100644 --- a/packages/css-color-parser/src/functions/hwb-normalize-channel-values.ts +++ b/packages/css-color-parser/src/functions/hwb-normalize-channel-values.ts @@ -1,97 +1,84 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken, NumberType, TokenType } from '@csstools/css-tokenizer'; import { SyntaxFlag } from '../color-data'; import { normalize } from './normalize'; import { normalizeHue } from './hue-normalize-channel-value'; import { toLowerCaseAZ } from '../util/to-lower-case-a-z'; -export function normalize_HWB_ChannelValues(tokens: Array, colorData: ColorData): Array | false { - const result: Array = []; +export function normalize_HWB_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false { + if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { + colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index]; - - if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { - colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); + return [ + TokenType.Number, + 'none', + token[2], + token[3], + { + value: NaN, + type: NumberType.Number, + }, + ]; + } - result.push([ - TokenType.Number, - 'none', - token[2], - token[3], - { - value: NaN, - type: NumberType.Number, - }, - ]); - continue; + if (index === 0) { + const hueToken = normalizeHue(token); + if (hueToken === false) { + return false; } - if (index === 0) { - const hueToken = normalizeHue(token); - if (hueToken === false) { - return false; - } - - if (token[0] === TokenType.Dimension) { - colorData.syntaxFlags.add(SyntaxFlag.HasDimensionValues); - } - - result.push(hueToken); - continue; + if (token[0] === TokenType.Dimension) { + colorData.syntaxFlags.add(SyntaxFlag.HasDimensionValues); } - if (token[0] === TokenType.Percentage) { - if (index === 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageAlpha); - } else { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); - } + return hueToken; + } - let value = normalize(token[4].value, 1, 0, 100); - if (index === 3) { - value = normalize(token[4].value, 100, 0, 1); - } + if (token[0] === TokenType.Percentage) { + if (index === 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageAlpha); + } else { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); + } - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 1, 0, 100); + if (index === 3) { + value = normalize(token[4].value, 100, 0, 1); } - if (token[0] === TokenType.Number) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); - } + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; + } - let value = normalize(token[4].value, 1, 0, 100); - if (index === 3) { - value = normalize(token[4].value, 1, 0, 1); - } + if (token[0] === TokenType.Number) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); + } - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 1, 0, 100); + if (index === 3) { + value = normalize(token[4].value, 1, 0, 1); } - return false; + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; } - return result; + return false; } diff --git a/packages/css-color-parser/src/functions/lab-normalize-channel-values.ts b/packages/css-color-parser/src/functions/lab-normalize-channel-values.ts index a300ed3e1..94a7124db 100644 --- a/packages/css-color-parser/src/functions/lab-normalize-channel-values.ts +++ b/packages/css-color-parser/src/functions/lab-normalize-channel-values.ts @@ -1,84 +1,72 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken, NumberType, TokenType } from '@csstools/css-tokenizer'; import { SyntaxFlag } from '../color-data'; import { normalize } from './normalize'; import { toLowerCaseAZ } from '../util/to-lower-case-a-z'; -export function normalize_Lab_ChannelValues(tokens: Array, colorData: ColorData): Array | false { - const result: Array = []; +export function normalize_Lab_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false { + if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { + colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index]; - - if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { - colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); + return [ + TokenType.Number, + 'none', + token[2], + token[3], + { + value: NaN, + type: NumberType.Number, + }, + ]; + } - result.push([ - TokenType.Number, - 'none', - token[2], - token[3], - { - value: NaN, - type: NumberType.Number, - }, - ]); - continue; + if (token[0] === TokenType.Percentage) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); } - if (token[0] === TokenType.Percentage) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); - } - - let value = normalize(token[4].value, 1, 0, 100); - if (index === 1 || index === 2) { - value = normalize(token[4].value, 0.8, -Infinity, Infinity); - } else if (index === 3) { - value = normalize(token[4].value, 100, 0, 1); - } - - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 1, 0, 100); + if (index === 1 || index === 2) { + value = normalize(token[4].value, 0.8, -Infinity, Infinity); + } else if (index === 3) { + value = normalize(token[4].value, 100, 0, 1); } - if (token[0] === TokenType.Number) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); - } + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; + } - let value = normalize(token[4].value, 1, 0, 100); - if (index === 1 || index === 2) { - value = normalize(token[4].value, 1, -Infinity, Infinity); - } else if (index === 3) { - value = normalize(token[4].value, 1, 0, 1); - } + if (token[0] === TokenType.Number) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); + } - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 1, 0, 100); + if (index === 1 || index === 2) { + value = normalize(token[4].value, 1, -Infinity, Infinity); + } else if (index === 3) { + value = normalize(token[4].value, 1, 0, 1); } - return false; + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; } - return result; + return false; } diff --git a/packages/css-color-parser/src/functions/lch-normalize-channel-values.ts b/packages/css-color-parser/src/functions/lch-normalize-channel-values.ts index a4a00ecbf..b05526d1d 100644 --- a/packages/css-color-parser/src/functions/lch-normalize-channel-values.ts +++ b/packages/css-color-parser/src/functions/lch-normalize-channel-values.ts @@ -1,99 +1,86 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken, NumberType, TokenType } from '@csstools/css-tokenizer'; import { SyntaxFlag } from '../color-data'; import { normalize } from './normalize'; import { normalizeHue } from './hue-normalize-channel-value'; import { toLowerCaseAZ } from '../util/to-lower-case-a-z'; -export function normalize_LCH_ChannelValues(tokens: Array, colorData: ColorData): Array | false { - const result: Array = []; +export function normalize_LCH_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false { + if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { + colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index]; - - if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { - colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); + return [ + TokenType.Number, + 'none', + token[2], + token[3], + { + value: NaN, + type: NumberType.Number, + }, + ]; + } - result.push([ - TokenType.Number, - 'none', - token[2], - token[3], - { - value: NaN, - type: NumberType.Number, - }, - ]); - continue; + if (index === 2) { + const hueToken = normalizeHue(token); + if (hueToken === false) { + return false; } - if (index === 2) { - const hueToken = normalizeHue(token); - if (hueToken === false) { - return false; - } - - if (token[0] === TokenType.Dimension) { - colorData.syntaxFlags.add(SyntaxFlag.HasDimensionValues); - } - - result.push(hueToken); - continue; + if (token[0] === TokenType.Dimension) { + colorData.syntaxFlags.add(SyntaxFlag.HasDimensionValues); } - if (token[0] === TokenType.Percentage) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); - } + return hueToken; + } - let value = normalize(token[4].value, 1, 0, 100); - if (index === 1) { - value = normalize(token[4].value, (100 / 150), 0, Infinity); - } else if (index === 3) { - value = normalize(token[4].value, 100, 0, 1); - } + if (token[0] === TokenType.Percentage) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); + } - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 1, 0, 100); + if (index === 1) { + value = normalize(token[4].value, (100 / 150), 0, Infinity); + } else if (index === 3) { + value = normalize(token[4].value, 100, 0, 1); } - if (token[0] === TokenType.Number) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); - } + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; + } - let value = normalize(token[4].value, 1, 0, 100); - if (index === 1) { - value = normalize(token[4].value, 1, 0, Infinity); - } else if (index === 3) { - value = normalize(token[4].value, 1, 0, 1); - } + if (token[0] === TokenType.Number) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); + } - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 1, 0, 100); + if (index === 1) { + value = normalize(token[4].value, 1, 0, Infinity); + } else if (index === 3) { + value = normalize(token[4].value, 1, 0, 1); } - return false; + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; } - return result; + return false; } diff --git a/packages/css-color-parser/src/functions/normalize-channel-values.ts b/packages/css-color-parser/src/functions/normalize-channel-values.ts index add3a2898..e627813ba 100644 --- a/packages/css-color-parser/src/functions/normalize-channel-values.ts +++ b/packages/css-color-parser/src/functions/normalize-channel-values.ts @@ -1,5 +1,4 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken } from '@csstools/css-tokenizer'; -export type normalizeChannelValuesFn = (tokens: Array, colorData: ColorData) => Array | false; +export type normalizeChannelValuesFn = (token: CSSToken, index: number, colorData: ColorData) => CSSToken | false; diff --git a/packages/css-color-parser/src/functions/oklab-normalize-channel-values.ts b/packages/css-color-parser/src/functions/oklab-normalize-channel-values.ts index 619f3d94c..136e31f29 100644 --- a/packages/css-color-parser/src/functions/oklab-normalize-channel-values.ts +++ b/packages/css-color-parser/src/functions/oklab-normalize-channel-values.ts @@ -1,84 +1,72 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken, NumberType, TokenType } from '@csstools/css-tokenizer'; import { SyntaxFlag } from '../color-data'; import { normalize } from './normalize'; import { toLowerCaseAZ } from '../util/to-lower-case-a-z'; -export function normalize_OKLab_ChannelValues(tokens: Array, colorData: ColorData): Array | false { - const result: Array = []; +export function normalize_OKLab_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false { + if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { + colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index]; - - if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { - colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); + return [ + TokenType.Number, + 'none', + token[2], + token[3], + { + value: NaN, + type: NumberType.Number, + }, + ]; + } - result.push([ - TokenType.Number, - 'none', - token[2], - token[3], - { - value: NaN, - type: NumberType.Number, - }, - ]); - continue; + if (token[0] === TokenType.Percentage) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); } - if (token[0] === TokenType.Percentage) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); - } - - let value = normalize(token[4].value, 100, 0, 1); - if (index === 1 || index === 2) { - value = normalize(token[4].value, 250, -Infinity, Infinity); - } else if (index === 3) { - value = normalize(token[4].value, 100, 0, 1); - } - - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 100, 0, 1); + if (index === 1 || index === 2) { + value = normalize(token[4].value, 250, -Infinity, Infinity); + } else if (index === 3) { + value = normalize(token[4].value, 100, 0, 1); } - if (token[0] === TokenType.Number) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); - } + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; + } - let value = normalize(token[4].value, 1, 0, 1); - if (index === 1 || index === 2) { - value = normalize(token[4].value, 1, -Infinity, Infinity); - } else if (index === 3) { - value = normalize(token[4].value, 1, 0, 1); - } + if (token[0] === TokenType.Number) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); + } - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 1, 0, 1); + if (index === 1 || index === 2) { + value = normalize(token[4].value, 1, -Infinity, Infinity); + } else if (index === 3) { + value = normalize(token[4].value, 1, 0, 1); } - return false; + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; } - return result; + return false; } diff --git a/packages/css-color-parser/src/functions/oklch-normalize-channel-values.ts b/packages/css-color-parser/src/functions/oklch-normalize-channel-values.ts index 6d2f9fbad..095d42179 100644 --- a/packages/css-color-parser/src/functions/oklch-normalize-channel-values.ts +++ b/packages/css-color-parser/src/functions/oklch-normalize-channel-values.ts @@ -1,99 +1,86 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken, NumberType, TokenType } from '@csstools/css-tokenizer'; import { SyntaxFlag } from '../color-data'; import { normalize } from './normalize'; import { normalizeHue } from './hue-normalize-channel-value'; import { toLowerCaseAZ } from '../util/to-lower-case-a-z'; -export function normalize_OKLCH_ChannelValues(tokens: Array, colorData: ColorData): Array | false { - const result: Array = []; +export function normalize_OKLCH_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false { + if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { + colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index]; - - if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { - colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); + return [ + TokenType.Number, + 'none', + token[2], + token[3], + { + value: NaN, + type: NumberType.Number, + }, + ]; + } - result.push([ - TokenType.Number, - 'none', - token[2], - token[3], - { - value: NaN, - type: NumberType.Number, - }, - ]); - continue; + if (index === 2) { + const hueToken = normalizeHue(token); + if (hueToken === false) { + return false; } - if (index === 2) { - const hueToken = normalizeHue(token); - if (hueToken === false) { - return false; - } - - if (token[0] === TokenType.Dimension) { - colorData.syntaxFlags.add(SyntaxFlag.HasDimensionValues); - } - - result.push(hueToken); - continue; + if (token[0] === TokenType.Dimension) { + colorData.syntaxFlags.add(SyntaxFlag.HasDimensionValues); } - if (token[0] === TokenType.Percentage) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); - } + return hueToken; + } - let value = normalize(token[4].value, 100, 0, 1); - if (index === 1) { - value = normalize(token[4].value, 250, 0, Infinity); - } else if (index === 3) { - value = normalize(token[4].value, 100, 0, 1); - } + if (token[0] === TokenType.Percentage) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); + } - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 100, 0, 1); + if (index === 1) { + value = normalize(token[4].value, 250, 0, Infinity); + } else if (index === 3) { + value = normalize(token[4].value, 100, 0, 1); } - if (token[0] === TokenType.Number) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); - } + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; + } - let value = normalize(token[4].value, 1, 0, 1); - if (index === 1) { - value = normalize(token[4].value, 1, 0, Infinity); - } else if (index === 3) { - value = normalize(token[4].value, 1, 0, 1); - } + if (token[0] === TokenType.Number) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); + } - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 1, 0, 1); + if (index === 1) { + value = normalize(token[4].value, 1, 0, Infinity); + } else if (index === 3) { + value = normalize(token[4].value, 1, 0, 1); } - return false; + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; } - return result; + return false; } diff --git a/packages/css-color-parser/src/functions/rgb-normalize-channel-values.ts b/packages/css-color-parser/src/functions/rgb-normalize-channel-values.ts index 4d94b49a8..28da9896a 100644 --- a/packages/css-color-parser/src/functions/rgb-normalize-channel-values.ts +++ b/packages/css-color-parser/src/functions/rgb-normalize-channel-values.ts @@ -1,141 +1,112 @@ import type { ColorData } from '../color-data'; -import type { TokenNumber } from '@csstools/css-tokenizer'; import { CSSToken, NumberType, TokenType } from '@csstools/css-tokenizer'; import { SyntaxFlag } from '../color-data'; import { normalize } from './normalize'; import { toLowerCaseAZ } from '../util/to-lower-case-a-z'; -export function normalize_legacy_sRGB_ChannelValues(tokens: Array, colorData: ColorData): Array | false { - const result: Array = []; - - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index]; - - if (token[0] === TokenType.Percentage) { - if (index === 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageAlpha); - } else { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); - } - - const value = normalize(token[4].value, 100, 0, 1); - - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; +export function normalize_legacy_sRGB_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false { + if (token[0] === TokenType.Percentage) { + if (index === 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageAlpha); + } else { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); } - if (token[0] === TokenType.Number) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); - } - - let value = normalize(token[4].value, 255, 0, 1); - if (index === 3) { - value = normalize(token[4].value, 1, 0, 1); - } - - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + const value = normalize(token[4].value, 100, 0, 1); + + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; + } + + if (token[0] === TokenType.Number) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); } - return false; - } + let value = normalize(token[4].value, 255, 0, 1); + if (index === 3) { + value = normalize(token[4].value, 1, 0, 1); + } - if ( - colorData.syntaxFlags.has(SyntaxFlag.HasNumberValues) && - colorData.syntaxFlags.has(SyntaxFlag.HasPercentageValues) - ) { - return false; + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; } - return result; + return false; } -export function normalize_modern_sRGB_ChannelValues(tokens: Array, colorData: ColorData): Array | false { - const result: Array = []; - - for (let index = 0; index < tokens.length; index++) { - const token = tokens[index]; - - if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { - colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); - - result.push([ - TokenType.Number, - 'none', - token[2], - token[3], - { - value: NaN, - type: NumberType.Number, - }, - ]); - continue; +export function normalize_modern_sRGB_ChannelValues(token: CSSToken, index: number, colorData: ColorData): CSSToken | false { + if (token[0] === TokenType.Ident && toLowerCaseAZ(token[4].value) === 'none') { + colorData.syntaxFlags.add(SyntaxFlag.HasNoneKeywords); + + return [ + TokenType.Number, + 'none', + token[2], + token[3], + { + value: NaN, + type: NumberType.Number, + }, + ]; + } + + if (token[0] === TokenType.Percentage) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); } - if (token[0] === TokenType.Percentage) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasPercentageValues); - } - - const value = normalize(token[4].value, 100, 0, 1); - - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + const value = normalize(token[4].value, 100, 0, 1); + + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; + } + + if (token[0] === TokenType.Number) { + if (index !== 3) { + colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); } - if (token[0] === TokenType.Number) { - if (index !== 3) { - colorData.syntaxFlags.add(SyntaxFlag.HasNumberValues); - } - - let value = normalize(token[4].value, 255, 0, 1); - if (index === 3) { - value = normalize(token[4].value, 1, 0, 1); - } - - result.push([ - TokenType.Number, - value.toString(), - token[2], - token[3], - { - value: value, - type: NumberType.Number, - }, - ]); - continue; + let value = normalize(token[4].value, 255, 0, 1); + if (index === 3) { + value = normalize(token[4].value, 1, 0, 1); } - return false; + return [ + TokenType.Number, + value.toString(), + token[2], + token[3], + { + value: value, + type: NumberType.Number, + }, + ]; } - return result; + return false; } diff --git a/packages/css-color-parser/src/functions/rgb.ts b/packages/css-color-parser/src/functions/rgb.ts index 3d29c1ceb..5e9312aa1 100644 --- a/packages/css-color-parser/src/functions/rgb.ts +++ b/packages/css-color-parser/src/functions/rgb.ts @@ -12,6 +12,13 @@ export function rgb(rgbNode: FunctionNode, colorParser: ColorParser): ColorData if (rgbNode.value.some((x) => isTokenNode(x) && x.value[0] === TokenType.Comma)) { const output = rgbCommaSeparated(rgbNode); if (output !== false) { + if ( + output.syntaxFlags.has(SyntaxFlag.HasNumberValues) && + output.syntaxFlags.has(SyntaxFlag.HasPercentageValues) + ) { + return false; + } + return output; } } else { diff --git a/packages/css-color-parser/src/functions/three-channel-legacy-syntax.ts b/packages/css-color-parser/src/functions/three-channel-legacy-syntax.ts index 0e6446647..0948ed3fc 100644 --- a/packages/css-color-parser/src/functions/three-channel-legacy-syntax.ts +++ b/packages/css-color-parser/src/functions/three-channel-legacy-syntax.ts @@ -1,6 +1,6 @@ import type { ColorData } from '../color-data'; import type { ComponentValue, FunctionNode } from '@csstools/css-parser-algorithms'; -import { CSSToken, TokenType } from '@csstools/css-tokenizer'; +import { TokenNumber, TokenType } from '@csstools/css-tokenizer'; import { ColorNotation } from '../color-notation'; import { SyntaxFlag } from '../color-data'; import { calcFromComponentValues } from '@csstools/css-calc'; @@ -113,35 +113,50 @@ export function threeChannelLegacySyntax( return false; } - const channelValues: Array = [ - channel1[0].value, - channel2[0].value, - channel3[0].value, + const channelValue1 = normalizeChannelValues(channel1[0].value, 0, colorData); + if (!channelValue1 || channelValue1[0] !== TokenType.Number) { + return false; + } + + const channelValue2 = normalizeChannelValues(channel2[0].value, 1, colorData); + if (!channelValue2 || channelValue2[0] !== TokenType.Number) { + return false; + } + + const channelValue3 = normalizeChannelValues(channel3[0].value, 2, colorData); + if (!channelValue3 || channelValue3[0] !== TokenType.Number) { + return false; + } + + const channelValues: Array = [ + channelValue1, + channelValue2, + channelValue3, ]; if (channelAlpha.length === 1) { colorData.syntaxFlags.add(SyntaxFlag.HasAlpha); if (isTokenNode(channelAlpha[0])) { - channelValues.push(channelAlpha[0].value); + const channelValueAlpha = normalizeChannelValues(channelAlpha[0].value, 3, colorData); + if (!channelValueAlpha || channelValueAlpha[0] !== TokenType.Number) { + return false; + } + + channelValues.push(channelValueAlpha); } else { colorData.alpha = channelAlpha[0]; } } - const normalizedChannelValues = normalizeChannelValues(channelValues, colorData); - if (normalizedChannelValues === false) { - return false; - } - colorData.channels = [ - normalizedChannelValues[0][4].value, - normalizedChannelValues[1][4].value, - normalizedChannelValues[2][4].value, + channelValues[0][4].value, + channelValues[1][4].value, + channelValues[2][4].value, ]; - if (normalizedChannelValues.length === 4) { - colorData.alpha = normalizedChannelValues[3][4].value; + if (channelValues.length === 4) { + colorData.alpha = channelValues[3][4].value; } return colorData; diff --git a/packages/css-color-parser/src/functions/three-channel-space-separated.ts b/packages/css-color-parser/src/functions/three-channel-space-separated.ts index 60ecba57a..0e8318c17 100644 --- a/packages/css-color-parser/src/functions/three-channel-space-separated.ts +++ b/packages/css-color-parser/src/functions/three-channel-space-separated.ts @@ -1,6 +1,6 @@ import { ColorData, colorData_to_XYZ_D50, noneToZeroInRelativeColorDataChannels, normalizeRelativeColorDataChannels } from '../color-data'; import { ComponentValue, FunctionNode, TokenNode } from '@csstools/css-parser-algorithms'; -import { CSSToken, TokenDimension, TokenNumber, TokenPercentage, TokenType } from '@csstools/css-tokenizer'; +import { TokenDimension, TokenNumber, TokenPercentage, TokenType } from '@csstools/css-tokenizer'; import { ColorNotation } from '../color-notation'; import { SyntaxFlag } from '../color-data'; import { calcFromComponentValues } from '@csstools/css-calc'; @@ -194,38 +194,58 @@ export function threeChannelSpaceSeparated( return false; } - const channelValues: Array = [ - channel1[0].value, - channel2[0].value, - channel3[0].value, + const channelValue1 = normalizeChannelValues(channel1[0].value, 0, colorData); + if (!channelValue1 || channelValue1[0] !== TokenType.Number) { + return false; + } + + const channelValue2 = normalizeChannelValues(channel2[0].value, 1, colorData); + if (!channelValue2 || channelValue2[0] !== TokenType.Number) { + return false; + } + + const channelValue3 = normalizeChannelValues(channel3[0].value, 2, colorData); + if (!channelValue3 || channelValue3[0] !== TokenType.Number) { + return false; + } + + const channelValues: Array = [ + channelValue1, + channelValue2, + channelValue3, ]; if (channelAlpha.length === 1) { colorData.syntaxFlags.add(SyntaxFlag.HasAlpha); if (isTokenNode(channelAlpha[0])) { - channelValues.push(channelAlpha[0].value); + const channelValueAlpha = normalizeChannelValues(channelAlpha[0].value, 3, colorData); + if (!channelValueAlpha || channelValueAlpha[0] !== TokenType.Number) { + return false; + } + + channelValues.push(channelValueAlpha); } else { colorData.alpha = channelAlpha[0]; } } else if (relativeColorChannels && relativeColorChannels.has('alpha')) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - channelValues.push(relativeColorChannels.get('alpha')!); - } + const channelValueAlpha = normalizeChannelValues(relativeColorChannels.get('alpha')!, 3, colorData); + if (!channelValueAlpha || channelValueAlpha[0] !== TokenType.Number) { + return false; + } - const normalizedChannelValues = normalizeChannelValues(channelValues, colorData); - if (normalizedChannelValues === false) { - return false; + channelValues.push(channelValueAlpha); } colorData.channels = [ - normalizedChannelValues[0][4].value, - normalizedChannelValues[1][4].value, - normalizedChannelValues[2][4].value, + channelValues[0][4].value, + channelValues[1][4].value, + channelValues[2][4].value, ]; - if (normalizedChannelValues.length === 4) { - colorData.alpha = normalizedChannelValues[3][4].value; + if (channelValues.length === 4) { + colorData.alpha = channelValues[3][4].value; } return colorData; diff --git a/packages/css-color-parser/test/wpt/color-mix-out-of-gamut.mjs b/packages/css-color-parser/test/wpt/color-mix-out-of-gamut.mjs new file mode 100644 index 000000000..dcfd5ff45 --- /dev/null +++ b/packages/css-color-parser/test/wpt/color-mix-out-of-gamut.mjs @@ -0,0 +1,35 @@ +import { color } from '@csstools/css-color-parser'; +import assert from 'assert'; +import { canonicalize } from '../util/canonical.mjs'; +import { parse } from '../util/parse.mjs'; +import { serialize_sRGB_data } from '../util/serialize.mjs'; + +const tests = [ + ['color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb -0.511814 1.01832 -0.310726)')], + ['color-mix(in hsl, lab(100 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 1.59343 0.58802 1.40564)')], + ['color-mix(in hsl, lab(0 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 0.351376 -0.213938 0.299501)')], + ['color-mix(in hsl, lch(100 116 334) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 1.59328 0.588284 1.40527)')], + ['color-mix(in hsl, lch(0 116 334) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 0.351307 -0.213865 0.299236)')], + ['color-mix(in hsl, oklab(1 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 1.59295 0.360371 1.38571)')], + ['color-mix(in hsl, oklab(0 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 0.0763893 -0.0456266 0.0932598)')], + ['color-mix(in hsl, oklch(1 0.399 336.3) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 1.59328 0.358734 1.38664)')], + ['color-mix(in hsl, oklch(0 0.399 336.3) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 0.076536 -0.045825 0.0937443)')], + + ['color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb -0.511814 1.01832 -0.310726)')], + ['color-mix(in hwb, lab(100 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 1.59343 0.58802 1.40564)')], + ['color-mix(in hwb, lab(0 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 0.351376 -0.213938 0.299501)')], + ['color-mix(in hwb, lch(100 116 334) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 1.59328 0.588284 1.40527)')], + ['color-mix(in hwb, lch(0 116 334) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 0.351307 -0.213865 0.299236)')], + ['color-mix(in hwb, oklab(1 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 1.59295 0.360371 1.38571)')], + ['color-mix(in hwb, oklab(0 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 0.0763893 -0.0456266 0.0932598)')], + ['color-mix(in hwb, oklch(1 0.399 336.3) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 1.59328 0.358736 1.38664)')], + ['color-mix(in hwb, oklch(0 0.399 336.3) 100%, rgb(0, 0, 0) 0%)', canonicalize('color(srgb 0.0765361 -0.045825 0.0937443)')], +]; + +for (const test of tests) { + assert.deepStrictEqual( + serialize_sRGB_data(color(parse(test[0]))), + test[1], + `"${test[0]}" : ${test[1]}`, + ); +} diff --git a/packages/css-color-parser/test/wpt/index.mjs b/packages/css-color-parser/test/wpt/index.mjs index aa7b5c524..ed5779c13 100644 --- a/packages/css-color-parser/test/wpt/index.mjs +++ b/packages/css-color-parser/test/wpt/index.mjs @@ -17,3 +17,4 @@ import './color-invalid-hwb.mjs'; import './color-invalid-named-color.mjs'; import './color-invalid-relative-color.mjs'; import './color-invalid-rgb.mjs'; +// import './color-mix-out-of-gamut.mjs';