UNPKG

@tbela99/css-parser

Version:

CSS parser for node and the browser

1,306 lines (1,289 loc) 709 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.CSSParser = {})); })(this, (function (exports) { 'use strict'; var ValidationLevel; (function (ValidationLevel) { ValidationLevel[ValidationLevel["Valid"] = 0] = "Valid"; ValidationLevel[ValidationLevel["Drop"] = 1] = "Drop"; ValidationLevel[ValidationLevel["Lenient"] = 2] = "Lenient"; /* preserve unknown at-rules, declarations and pseudo-classes */ })(ValidationLevel || (ValidationLevel = {})); exports.EnumToken = void 0; (function (EnumToken) { EnumToken[EnumToken["CommentTokenType"] = 0] = "CommentTokenType"; EnumToken[EnumToken["CDOCOMMTokenType"] = 1] = "CDOCOMMTokenType"; EnumToken[EnumToken["StyleSheetNodeType"] = 2] = "StyleSheetNodeType"; EnumToken[EnumToken["AtRuleNodeType"] = 3] = "AtRuleNodeType"; EnumToken[EnumToken["RuleNodeType"] = 4] = "RuleNodeType"; EnumToken[EnumToken["DeclarationNodeType"] = 5] = "DeclarationNodeType"; EnumToken[EnumToken["LiteralTokenType"] = 6] = "LiteralTokenType"; EnumToken[EnumToken["IdenTokenType"] = 7] = "IdenTokenType"; EnumToken[EnumToken["DashedIdenTokenType"] = 8] = "DashedIdenTokenType"; EnumToken[EnumToken["CommaTokenType"] = 9] = "CommaTokenType"; EnumToken[EnumToken["ColonTokenType"] = 10] = "ColonTokenType"; EnumToken[EnumToken["SemiColonTokenType"] = 11] = "SemiColonTokenType"; EnumToken[EnumToken["NumberTokenType"] = 12] = "NumberTokenType"; EnumToken[EnumToken["AtRuleTokenType"] = 13] = "AtRuleTokenType"; EnumToken[EnumToken["PercentageTokenType"] = 14] = "PercentageTokenType"; EnumToken[EnumToken["FunctionTokenType"] = 15] = "FunctionTokenType"; EnumToken[EnumToken["TimelineFunctionTokenType"] = 16] = "TimelineFunctionTokenType"; EnumToken[EnumToken["TimingFunctionTokenType"] = 17] = "TimingFunctionTokenType"; EnumToken[EnumToken["UrlFunctionTokenType"] = 18] = "UrlFunctionTokenType"; EnumToken[EnumToken["ImageFunctionTokenType"] = 19] = "ImageFunctionTokenType"; EnumToken[EnumToken["StringTokenType"] = 20] = "StringTokenType"; EnumToken[EnumToken["UnclosedStringTokenType"] = 21] = "UnclosedStringTokenType"; EnumToken[EnumToken["DimensionTokenType"] = 22] = "DimensionTokenType"; EnumToken[EnumToken["LengthTokenType"] = 23] = "LengthTokenType"; EnumToken[EnumToken["AngleTokenType"] = 24] = "AngleTokenType"; EnumToken[EnumToken["TimeTokenType"] = 25] = "TimeTokenType"; EnumToken[EnumToken["FrequencyTokenType"] = 26] = "FrequencyTokenType"; EnumToken[EnumToken["ResolutionTokenType"] = 27] = "ResolutionTokenType"; EnumToken[EnumToken["HashTokenType"] = 28] = "HashTokenType"; EnumToken[EnumToken["BlockStartTokenType"] = 29] = "BlockStartTokenType"; EnumToken[EnumToken["BlockEndTokenType"] = 30] = "BlockEndTokenType"; EnumToken[EnumToken["AttrStartTokenType"] = 31] = "AttrStartTokenType"; EnumToken[EnumToken["AttrEndTokenType"] = 32] = "AttrEndTokenType"; EnumToken[EnumToken["StartParensTokenType"] = 33] = "StartParensTokenType"; EnumToken[EnumToken["EndParensTokenType"] = 34] = "EndParensTokenType"; EnumToken[EnumToken["ParensTokenType"] = 35] = "ParensTokenType"; EnumToken[EnumToken["WhitespaceTokenType"] = 36] = "WhitespaceTokenType"; EnumToken[EnumToken["IncludeMatchTokenType"] = 37] = "IncludeMatchTokenType"; EnumToken[EnumToken["DashMatchTokenType"] = 38] = "DashMatchTokenType"; EnumToken[EnumToken["EqualMatchTokenType"] = 39] = "EqualMatchTokenType"; EnumToken[EnumToken["LtTokenType"] = 40] = "LtTokenType"; EnumToken[EnumToken["LteTokenType"] = 41] = "LteTokenType"; EnumToken[EnumToken["GtTokenType"] = 42] = "GtTokenType"; EnumToken[EnumToken["GteTokenType"] = 43] = "GteTokenType"; EnumToken[EnumToken["PseudoClassTokenType"] = 44] = "PseudoClassTokenType"; EnumToken[EnumToken["PseudoClassFuncTokenType"] = 45] = "PseudoClassFuncTokenType"; EnumToken[EnumToken["DelimTokenType"] = 46] = "DelimTokenType"; EnumToken[EnumToken["UrlTokenTokenType"] = 47] = "UrlTokenTokenType"; EnumToken[EnumToken["EOFTokenType"] = 48] = "EOFTokenType"; EnumToken[EnumToken["ImportantTokenType"] = 49] = "ImportantTokenType"; EnumToken[EnumToken["ColorTokenType"] = 50] = "ColorTokenType"; EnumToken[EnumToken["AttrTokenType"] = 51] = "AttrTokenType"; EnumToken[EnumToken["BadCommentTokenType"] = 52] = "BadCommentTokenType"; EnumToken[EnumToken["BadCdoTokenType"] = 53] = "BadCdoTokenType"; EnumToken[EnumToken["BadUrlTokenType"] = 54] = "BadUrlTokenType"; EnumToken[EnumToken["BadStringTokenType"] = 55] = "BadStringTokenType"; EnumToken[EnumToken["BinaryExpressionTokenType"] = 56] = "BinaryExpressionTokenType"; EnumToken[EnumToken["UnaryExpressionTokenType"] = 57] = "UnaryExpressionTokenType"; EnumToken[EnumToken["FlexTokenType"] = 58] = "FlexTokenType"; /* catch all */ EnumToken[EnumToken["ListToken"] = 59] = "ListToken"; /* arithmetic tokens */ EnumToken[EnumToken["Add"] = 60] = "Add"; EnumToken[EnumToken["Mul"] = 61] = "Mul"; EnumToken[EnumToken["Div"] = 62] = "Div"; EnumToken[EnumToken["Sub"] = 63] = "Sub"; /* new tokens */ EnumToken[EnumToken["ColumnCombinatorTokenType"] = 64] = "ColumnCombinatorTokenType"; EnumToken[EnumToken["ContainMatchTokenType"] = 65] = "ContainMatchTokenType"; EnumToken[EnumToken["StartMatchTokenType"] = 66] = "StartMatchTokenType"; EnumToken[EnumToken["EndMatchTokenType"] = 67] = "EndMatchTokenType"; EnumToken[EnumToken["MatchExpressionTokenType"] = 68] = "MatchExpressionTokenType"; EnumToken[EnumToken["NameSpaceAttributeTokenType"] = 69] = "NameSpaceAttributeTokenType"; EnumToken[EnumToken["FractionTokenType"] = 70] = "FractionTokenType"; EnumToken[EnumToken["IdenListTokenType"] = 71] = "IdenListTokenType"; EnumToken[EnumToken["GridTemplateFuncTokenType"] = 72] = "GridTemplateFuncTokenType"; EnumToken[EnumToken["KeyFrameRuleNodeType"] = 73] = "KeyFrameRuleNodeType"; EnumToken[EnumToken["ClassSelectorTokenType"] = 74] = "ClassSelectorTokenType"; EnumToken[EnumToken["UniversalSelectorTokenType"] = 75] = "UniversalSelectorTokenType"; EnumToken[EnumToken["ChildCombinatorTokenType"] = 76] = "ChildCombinatorTokenType"; EnumToken[EnumToken["DescendantCombinatorTokenType"] = 77] = "DescendantCombinatorTokenType"; EnumToken[EnumToken["NextSiblingCombinatorTokenType"] = 78] = "NextSiblingCombinatorTokenType"; EnumToken[EnumToken["SubsequentSiblingCombinatorTokenType"] = 79] = "SubsequentSiblingCombinatorTokenType"; EnumToken[EnumToken["NestingSelectorTokenType"] = 80] = "NestingSelectorTokenType"; EnumToken[EnumToken["InvalidRuleTokenType"] = 81] = "InvalidRuleTokenType"; EnumToken[EnumToken["InvalidClassSelectorTokenType"] = 82] = "InvalidClassSelectorTokenType"; EnumToken[EnumToken["InvalidAttrTokenType"] = 83] = "InvalidAttrTokenType"; EnumToken[EnumToken["InvalidAtRuleTokenType"] = 84] = "InvalidAtRuleTokenType"; EnumToken[EnumToken["MediaQueryConditionTokenType"] = 85] = "MediaQueryConditionTokenType"; EnumToken[EnumToken["MediaFeatureTokenType"] = 86] = "MediaFeatureTokenType"; EnumToken[EnumToken["MediaFeatureOnlyTokenType"] = 87] = "MediaFeatureOnlyTokenType"; EnumToken[EnumToken["MediaFeatureNotTokenType"] = 88] = "MediaFeatureNotTokenType"; EnumToken[EnumToken["MediaFeatureAndTokenType"] = 89] = "MediaFeatureAndTokenType"; EnumToken[EnumToken["MediaFeatureOrTokenType"] = 90] = "MediaFeatureOrTokenType"; EnumToken[EnumToken["PseudoPageTokenType"] = 91] = "PseudoPageTokenType"; EnumToken[EnumToken["PseudoElementTokenType"] = 92] = "PseudoElementTokenType"; /* aliases */ EnumToken[EnumToken["Time"] = 25] = "Time"; EnumToken[EnumToken["Iden"] = 7] = "Iden"; EnumToken[EnumToken["EOF"] = 48] = "EOF"; EnumToken[EnumToken["Hash"] = 28] = "Hash"; EnumToken[EnumToken["Flex"] = 58] = "Flex"; EnumToken[EnumToken["Angle"] = 24] = "Angle"; EnumToken[EnumToken["Color"] = 50] = "Color"; EnumToken[EnumToken["Comma"] = 9] = "Comma"; EnumToken[EnumToken["String"] = 20] = "String"; EnumToken[EnumToken["Length"] = 23] = "Length"; EnumToken[EnumToken["Number"] = 12] = "Number"; EnumToken[EnumToken["Perc"] = 14] = "Perc"; EnumToken[EnumToken["Literal"] = 6] = "Literal"; EnumToken[EnumToken["Comment"] = 0] = "Comment"; EnumToken[EnumToken["UrlFunc"] = 18] = "UrlFunc"; EnumToken[EnumToken["Dimension"] = 22] = "Dimension"; EnumToken[EnumToken["Frequency"] = 26] = "Frequency"; EnumToken[EnumToken["Resolution"] = 27] = "Resolution"; EnumToken[EnumToken["Whitespace"] = 36] = "Whitespace"; EnumToken[EnumToken["IdenList"] = 71] = "IdenList"; EnumToken[EnumToken["DashedIden"] = 8] = "DashedIden"; EnumToken[EnumToken["GridTemplateFunc"] = 72] = "GridTemplateFunc"; EnumToken[EnumToken["ImageFunc"] = 19] = "ImageFunc"; EnumToken[EnumToken["CommentNodeType"] = 0] = "CommentNodeType"; EnumToken[EnumToken["CDOCOMMNodeType"] = 1] = "CDOCOMMNodeType"; EnumToken[EnumToken["TimingFunction"] = 17] = "TimingFunction"; EnumToken[EnumToken["TimelineFunction"] = 16] = "TimelineFunction"; })(exports.EnumToken || (exports.EnumToken = {})); const funcLike = [ exports.EnumToken.ParensTokenType, exports.EnumToken.FunctionTokenType, exports.EnumToken.UrlFunctionTokenType, exports.EnumToken.StartParensTokenType, exports.EnumToken.ImageFunctionTokenType, exports.EnumToken.TimingFunctionTokenType, exports.EnumToken.TimingFunctionTokenType, exports.EnumToken.PseudoClassFuncTokenType, exports.EnumToken.GridTemplateFuncTokenType ]; // from https://www.w3.org/TR/css-color-4/multiply-matrices.js /** * Simple matrix (and vector) multiplication * Warning: No error handling for incompatible dimensions! * @author Lea Verou 2020 MIT License */ // A is m x n. B is n x p. product is m x p. function multiplyMatrices(A, B) { let m = A.length; if (!Array.isArray(A[0])) { // A is vector, convert to [[a, b, c, ...]] A = [A]; } if (!Array.isArray(B[0])) { // B is vector, convert to [[a], [b], [c], ...]] B = B.map((x) => [x]); } let p = B[0].length; let B_cols = B[0].map((_, i) => B.map((x) => x[i])); // transpose B let product = A.map((row) => B_cols.map((col) => { if (!Array.isArray(row)) { return col.reduce((a, c) => a + c * row, 0); } return row.reduce((a, c, i) => a + c * (col[i] || 0), 0); })); if (m === 1) { product = product[0]; // Avoid [[a, b, c, ...]] } if (p === 1) { return product.map((x) => x[0]); // Avoid [[a], [b], [c], ...]] } return product; } const colorRange = { lab: { l: [0, 100], a: [-125, 125], b: [-125, 125] }, lch: { l: [0, 100], c: [0, 150], h: [0, 360] }, oklab: { l: [0, 1], a: [-0.4, .4], b: [-0.4, 0.4] }, oklch: { l: [0, 1], a: [0, .4], b: [0, 0.4] } }; const colorFuncColorSpace = ['srgb', 'srgb-linear', 'display-p3', 'prophoto-rgb', 'a98-rgb', 'rec2020', 'xyz', 'xyz-d65', 'xyz-d50']; ({ typ: exports.EnumToken.IdenTokenType}); const D50 = [0.3457 / 0.3585, 1.00000, (1.0 - 0.3457 - 0.3585) / 0.3585]; const k = Math.pow(29, 3) / Math.pow(3, 3); const e = Math.pow(6, 3) / Math.pow(29, 3); // color module v4 const systemColors = new Set(['ActiveText', 'ButtonBorder', 'ButtonFace', 'ButtonText', 'Canvas', 'CanvasText', 'Field', 'FieldText', 'GrayText', 'Highlight', 'HighlightText', 'LinkText', 'Mark', 'MarkText', 'VisitedText'].map(m => m.toLowerCase())); // deprecated const deprecatedSystemColors = new Set(['ActiveBorder', 'ActiveCaption', 'AppWorkspace', 'Background', 'ButtonFace', 'ButtonHighlight', 'ButtonShadow', 'ButtonText', 'CaptionText', 'GrayText', 'Highlight', 'HighlightText', 'InactiveBorder', 'InactiveCaption', 'InactiveCaptionText', 'InfoBackground', 'InfoText', 'Menu', 'MenuText', 'Scrollbar', 'ThreeDDarkShadow', 'ThreeDFace', 'ThreeDHighlight', 'ThreeDLightShadow', 'ThreeDShadow', 'Window', 'WindowFrame', 'WindowText'].map(t => t.toLowerCase())); // name to color const COLORS_NAMES = Object.seal({ 'aliceblue': '#f0f8ff', 'antiquewhite': '#faebd7', 'aqua': '#00ffff', 'aquamarine': '#7fffd4', 'azure': '#f0ffff', 'beige': '#f5f5dc', 'bisque': '#ffe4c4', 'black': '#000000', 'blanchedalmond': '#ffebcd', 'blue': '#0000ff', 'blueviolet': '#8a2be2', 'brown': '#a52a2a', 'burlywood': '#deb887', 'cadetblue': '#5f9ea0', 'chartreuse': '#7fff00', 'chocolate': '#d2691e', 'coral': '#ff7f50', 'cornflowerblue': '#6495ed', 'cornsilk': '#fff8dc', 'crimson': '#dc143c', 'cyan': '#00ffff', 'darkblue': '#00008b', 'darkcyan': '#008b8b', 'darkgoldenrod': '#b8860b', 'darkgray': '#a9a9a9', 'darkgrey': '#a9a9a9', 'darkgreen': '#006400', 'darkkhaki': '#bdb76b', 'darkmagenta': '#8b008b', 'darkolivegreen': '#556b2f', 'darkorange': '#ff8c00', 'darkorchid': '#9932cc', 'darkred': '#8b0000', 'darksalmon': '#e9967a', 'darkseagreen': '#8fbc8f', 'darkslateblue': '#483d8b', 'darkslategray': '#2f4f4f', 'darkslategrey': '#2f4f4f', 'darkturquoise': '#00ced1', 'darkviolet': '#9400d3', 'deeppink': '#ff1493', 'deepskyblue': '#00bfff', 'dimgray': '#696969', 'dimgrey': '#696969', 'dodgerblue': '#1e90ff', 'firebrick': '#b22222', 'floralwhite': '#fffaf0', 'forestgreen': '#228b22', 'fuchsia': '#ff00ff', 'gainsboro': '#dcdcdc', 'ghostwhite': '#f8f8ff', 'gold': '#ffd700', 'goldenrod': '#daa520', 'gray': '#808080', 'grey': '#808080', 'green': '#008000', 'greenyellow': '#adff2f', 'honeydew': '#f0fff0', 'hotpink': '#ff69b4', 'indianred': '#cd5c5c', 'indigo': '#4b0082', 'ivory': '#fffff0', 'khaki': '#f0e68c', 'lavender': '#e6e6fa', 'lavenderblush': '#fff0f5', 'lawngreen': '#7cfc00', 'lemonchiffon': '#fffacd', 'lightblue': '#add8e6', 'lightcoral': '#f08080', 'lightcyan': '#e0ffff', 'lightgoldenrodyellow': '#fafad2', 'lightgray': '#d3d3d3', 'lightgrey': '#d3d3d3', 'lightgreen': '#90ee90', 'lightpink': '#ffb6c1', 'lightsalmon': '#ffa07a', 'lightseagreen': '#20b2aa', 'lightskyblue': '#87cefa', 'lightslategray': '#778899', 'lightslategrey': '#778899', 'lightsteelblue': '#b0c4de', 'lightyellow': '#ffffe0', 'lime': '#00ff00', 'limegreen': '#32cd32', 'linen': '#faf0e6', 'magenta': '#ff00ff', 'maroon': '#800000', 'mediumaquamarine': '#66cdaa', 'mediumblue': '#0000cd', 'mediumorchid': '#ba55d3', 'mediumpurple': '#9370d8', 'mediumseagreen': '#3cb371', 'mediumslateblue': '#7b68ee', 'mediumspringgreen': '#00fa9a', 'mediumturquoise': '#48d1cc', 'mediumvioletred': '#c71585', 'midnightblue': '#191970', 'mintcream': '#f5fffa', 'mistyrose': '#ffe4e1', 'moccasin': '#ffe4b5', 'navajowhite': '#ffdead', 'navy': '#000080', 'oldlace': '#fdf5e6', 'olive': '#808000', 'olivedrab': '#6b8e23', 'orange': '#ffa500', 'orangered': '#ff4500', 'orchid': '#da70d6', 'palegoldenrod': '#eee8aa', 'palegreen': '#98fb98', 'paleturquoise': '#afeeee', 'palevioletred': '#d87093', 'papayawhip': '#ffefd5', 'peachpuff': '#ffdab9', 'peru': '#cd853f', 'pink': '#ffc0cb', 'plum': '#dda0dd', 'powderblue': '#b0e0e6', 'purple': '#800080', 'red': '#ff0000', 'rosybrown': '#bc8f8f', 'royalblue': '#4169e1', 'saddlebrown': '#8b4513', 'salmon': '#fa8072', 'sandybrown': '#f4a460', 'seagreen': '#2e8b57', 'seashell': '#fff5ee', 'sienna': '#a0522d', 'silver': '#c0c0c0', 'skyblue': '#87ceeb', 'slateblue': '#6a5acd', 'slategray': '#708090', 'slategrey': '#708090', 'snow': '#fffafa', 'springgreen': '#00ff7f', 'steelblue': '#4682b4', 'tan': '#d2b48c', 'teal': '#008080', 'thistle': '#d8bfd8', 'tomato': '#ff6347', 'turquoise': '#40e0d0', 'violet': '#ee82ee', 'wheat': '#f5deb3', 'white': '#ffffff', 'whitesmoke': '#f5f5f5', 'yellow': '#ffff00', 'yellowgreen': '#9acd32', 'rebeccapurple': '#663399', 'transparent': '#00000000' }); // color to name const NAMES_COLORS = Object.seal(Object.entries(COLORS_NAMES).reduce((acc, [key, value]) => { acc[value] = key; return acc; }, Object.create(null))); function toHexString(acc, value) { return acc + value.toString(16).padStart(2, '0'); } function reduceHexValue(value) { const named_color = NAMES_COLORS[expandHexValue(value)]; if (value.length == 7) { if (value[1] == value[2] && value[3] == value[4] && value[5] == value[6]) { value = `#${value[1]}${value[3]}${value[5]}`; } } else if (value.length == 9) { if (value[1] == value[2] && value[3] == value[4] && value[5] == value[6] && value[7] == value[8]) { value = `#${value[1]}${value[3]}${value[5]}${value[7]}`; } } return named_color != null && named_color.length <= value.length ? named_color : value; } function expandHexValue(value) { if (value.length == 4) { return `#${value[1]}${value[1]}${value[2]}${value[2]}${value[3]}${value[3]}`; } if (value.length == 5) { return `#${value[1]}${value[1]}${value[2]}${value[2]}${value[3]}${value[3]}${value[4]}${value[4]}`; } return value; } function rgb2hex(token) { let value = '#'; let t; // @ts-ignore const components = getComponents(token); // @ts-ignore for (let i = 0; i < 3; i++) { // @ts-ignore t = components[i]; // @ts-ignore value += (t.typ == exports.EnumToken.Iden && t.val == 'none' ? '0' : Math.round(getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? 255 : 1))).toString(16).padStart(2, '0'); } // @ts-ignore if (components.length == 4) { // @ts-ignore t = components[3]; // @ts-ignore const v = (t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') ? 1 : getNumber(t); // @ts-ignore if (v < 1) { // @ts-ignore value += Math.round(255 * getNumber(t)).toString(16).padStart(2, '0'); } } return value; } function hsl2hex(token) { return `${hsl2rgb(token).reduce(toHexString, '#')}`; } function hwb2hex(token) { return `${hwb2rgb(token).reduce(toHexString, '#')}`; } function cmyk2hex(token) { return `#${cmyk2rgb(token).reduce(toHexString, '')}`; } function oklab2hex(token) { return `${oklab2rgb(token).reduce(toHexString, '#')}`; } function oklch2hex(token) { return `${oklch2rgb(token).reduce(toHexString, '#')}`; } function lab2hex(token) { return `${lab2rgb(token).reduce(toHexString, '#')}`; } function lch2hex(token) { return `${lch2rgb(token).reduce(toHexString, '#')}`; } function srgb2hexvalues(r, g, b, alpha) { return [r, g, b].concat(alpha == null || alpha == 1 ? [] : [alpha]).reduce((acc, value) => acc + minmax(Math.round(255 * value), 0, 255).toString(16).padStart(2, '0'), '#'); } function getComponents(token) { if (token.kin == 'hex' || token.kin == 'lit') { const value = expandHexValue(token.kin == 'lit' ? COLORS_NAMES[token.val.toLowerCase()] : token.val); // @ts-ignore return value.slice(1).match(/([a-fA-F0-9]{2})/g).map((t) => { return { typ: exports.EnumToken.Number, val: parseInt(t, 16).toString() }; }); } return token.chi .filter((t) => ![exports.EnumToken.LiteralTokenType, exports.EnumToken.CommentTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.WhitespaceTokenType].includes(t.typ)); } function XYZ_to_lin_sRGB(x, y, z) { // convert XYZ to linear-light sRGB const M = [ [12831 / 3959, -329 / 214, -1974 / 3959], [-851781 / 878810, 1648619 / 878810, 36519 / 878810], [705 / 12673, -2585 / 12673, 705 / 667], ]; const XYZ = [x, y, z]; // convert to XYZ return multiplyMatrices(M, XYZ).map((v) => v); } function XYZ_D50_to_D65(x, y, z) { // Bradford chromatic adaptation from D50 to D65 const M = [ [0.9554734527042182, -0.023098536874261423, 0.0632593086610217], [-0.028369706963208136, 1.0099954580058226, 0.021041398966943008], [0.012314001688319899, -0.020507696433477912, 1.3303659366080753] ]; const XYZ = [x, y, z]; return multiplyMatrices(M, XYZ); //.map((v: number) => v); } function srgb2xyz(r, g, b, alpha) { [r, g, b] = srgb2lsrgbvalues(r, g, b); const rgb = [ 0.436065742824811 * r + 0.3851514688337912 * g + 0.14307845442264197 * b, 0.22249319175623702 * r + 0.7168870538238823 * g + 0.06061979053616537 * b, 0.013923904500943465 * r + 0.09708128566574634 * g + 0.7140993584005155 * b ]; if (alpha != null && alpha != 1) { rgb.push(alpha); } return rgb; } function hex2lch(token) { // @ts-ignore return lab2lchvalues(...hex2lab(token)); } function rgb2lch(token) { // @ts-ignore return lab2lchvalues(...rgb2lab(token)); } function hsl2lch(token) { // @ts-ignore return lab2lchvalues(...hsl2lab(token)); } function hwb2lch(token) { // @ts-ignore return lab2lchvalues(...hwb2lab(token)); } function lab2lch(token) { // @ts-ignore return lab2lchvalues(...getLABComponents(token)); } function srgb2lch(r, g, blue, alpha) { // @ts-ignore return lab2lchvalues(...srgb2lab(r, g, blue, alpha)); } function oklab2lch(token) { // @ts-ignore return lab2lchvalues(...oklab2lab(token)); } function oklch2lch(token) { // @ts-ignore return lab2lchvalues(...oklch2lab(token)); } function lab2lchvalues(l, a, b, alpha = null) { let c = Math.sqrt(a * a + b * b); let h = Math.atan2(b, a) * 180 / Math.PI; if (h < 0) { h += 360; } if (c < .0001) { c = h = 0; } return alpha == null ? [l, c, h] : [l, c, h, alpha]; } function xyz2lchvalues(x, y, z, alpha) { // @ts-ignore( const lch = lab2lchvalues(...xyz2lab(x, y, z)); return alpha == null || alpha == 1 ? lch : lch.concat(alpha); } function getLCHComponents(token) { const components = getComponents(token); // @ts-ignore let t = components[0]; // @ts-ignore const l = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? 100 : 1); // @ts-ignore t = components[1]; // @ts-ignore const c = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? 150 : 1); // @ts-ignore t = components[2]; // @ts-ignore const h = getAngle(t) * 360; // @ts-ignore t = components[3]; // @ts-ignore const alpha = t == null ? 1 : getNumber(t); return alpha == null ? [l, c, h] : [l, c, h, alpha]; } function hex2oklch(token) { // @ts-ignore return lab2lchvalues(...hex2oklab(token)); } function rgb2oklch(token) { // @ts-ignore return lab2lchvalues(...rgb2oklab(token)); } function hsl2oklch(token) { // @ts-ignore return lab2lchvalues(...hsl2oklab(token)); } function hwb2oklch(token) { // @ts-ignore return lab2lchvalues(...hwb2oklab(token)); } function lab2oklch(token) { // @ts-ignore return lab2lchvalues(...lab2oklab(token)); } function lch2oklch(token) { // @ts-ignore return lab2lchvalues(...lch2oklab(token)); } function oklab2oklch(token) { // @ts-ignore return lab2lchvalues(...getOKLABComponents(token)); } function srgb2oklch(r, g, blue, alpha) { // @ts-ignore return lab2lchvalues(...srgb2oklab(r, g, blue, alpha)); } function getOKLCHComponents(token) { const components = getComponents(token); // @ts-ignore let t = components[0]; // @ts-ignore const l = getNumber(t); // @ts-ignore t = components[1]; // @ts-ignore const c = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? .4 : 1); // @ts-ignore t = components[2]; // @ts-ignore const h = getAngle(t) * 360; // @ts-ignore t = components[3]; // @ts-ignore const alpha = t == null || (t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') ? 1 : getNumber(t); return [l, c, h, alpha]; } function hex2oklab(token) { // @ts-ignore return srgb2oklab(...hex2srgb(token)); } function rgb2oklab(token) { // @ts-ignore return srgb2oklab(...rgb2srgb(token)); } function hsl2oklab(token) { // @ts-ignore return srgb2oklab(...hsl2srgb(token)); } function hwb2oklab(token) { // @ts-ignore return srgb2oklab(...hwb2srgb(token)); } function lab2oklab(token) { // @ts-ignore return srgb2oklab(...lab2srgb(token)); } function lch2oklab(token) { // @ts-ignore return srgb2oklab(...lch2srgb(token)); } function oklch2oklab(token) { // @ts-ignore return lch2labvalues(...getOKLCHComponents(token)); } function srgb2oklab(r, g, blue, alpha) { [r, g, blue] = srgb2lsrgbvalues(r, g, blue); let L = Math.cbrt(0.41222147079999993 * r + 0.5363325363 * g + 0.0514459929 * blue); let M = Math.cbrt(0.2119034981999999 * r + 0.6806995450999999 * g + 0.1073969566 * blue); let S = Math.cbrt(0.08830246189999998 * r + 0.2817188376 * g + 0.6299787005000002 * blue); const l = 0.2104542553 * L + 0.793617785 * M - 0.0040720468 * S; const a = r == g && g == blue ? 0 : 1.9779984951 * L - 2.428592205 * M + 0.4505937099 * S; const b = r == g && g == blue ? 0 : 0.0259040371 * L + 0.7827717662 * M - 0.808675766 * S; return alpha == null ? [l, a, b] : [l, a, b, alpha]; } function getOKLABComponents(token) { const components = getComponents(token); // @ts-ignore let t = components[0]; // @ts-ignore const l = getNumber(t); // @ts-ignore t = components[1]; // @ts-ignore const a = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? .4 : 1); // @ts-ignore t = components[2]; // @ts-ignore const b = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? .4 : 1); // @ts-ignore t = components[3]; // @ts-ignore const alpha = t == null || (t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') ? 1 : getNumber(t); const rgb = [l, a, b]; if (alpha != 1 && alpha != null) { rgb.push(alpha); } return rgb; } function OKLab_to_XYZ(l, a, b, alpha = null) { // Given OKLab, convert to XYZ relative to D65 const LMStoXYZ = [ [1.2268798758459243, -0.5578149944602171, 0.2813910456659647], [-0.0405757452148008, 1.1122868032803170, -0.0717110580655164], [-0.0763729366746601, -0.4214933324022432, 1.5869240198367816] ]; const OKLabtoLMS = [ [1.0000000000000000, 0.3963377773761749, 0.2158037573099136], [1.0000000000000000, -0.1055613458156586, -0.0638541728258133], [1.0000000000000000, -0.0894841775298119, -1.2914855480194092] ]; const LMSnl = multiplyMatrices(OKLabtoLMS, [l, a, b]); const xyz = multiplyMatrices(LMStoXYZ, LMSnl.map((c) => c ** 3)); if (alpha != null) { xyz.push(alpha); } return xyz; } // from https://www.w3.org/TR/css-color-4/#color-conversion-code function OKLab_to_sRGB(l, a, b) { let L = Math.pow(l * 0.99999999845051981432 + 0.39633779217376785678 * a + 0.21580375806075880339 * b, 3); let M = Math.pow(l * 1.0000000088817607767 - 0.1055613423236563494 * a - 0.063854174771705903402 * b, 3); let S = Math.pow(l * 1.0000000546724109177 - 0.089484182094965759684 * a - 1.2914855378640917399 * b, 3); return lsrgb2srgbvalues( /* r: */ 4.076741661347994 * L - 3.307711590408193 * M + 0.230969928729428 * S, /* g: */ -1.2684380040921763 * L + 2.6097574006633715 * M - 0.3413193963102197 * S, /* b: */ -0.004196086541837188 * L - 0.7034186144594493 * M + 1.7076147009309444 * S); } /* */ function xyzd502lch(x, y, z, alpha) { // @ts-ignore const [l, a, b] = xyz2lab(...XYZ_D50_to_D65(x, y, z)); // L in range [0,100]. For use in CSS, add a percent return lab2lchvalues(l, a, b, alpha); } function XYZ_D65_to_D50(x, y, z) { // Bradford chromatic adaptation from D65 to D50 // The matrix below is the result of three operations: // - convert from XYZ to retinal cone domain // - scale components from one reference white to another // - convert back to XYZ // see https://github.com/LeaVerou/color.js/pull/354/files var M = [ [1.0479297925449969, 0.022946870601609652, -0.05019226628920524], [0.02962780877005599, 0.9904344267538799, -0.017073799063418826], [-0.009243040646204504, 0.015055191490298152, 0.7518742814281371] ]; return multiplyMatrices(M, [x, y, z]); } function xyzd502srgb(x, y, z) { // @ts-ignore return lsrgb2srgbvalues( /* r: */ x * 3.1341359569958707 - y * 1.6173863321612538 - 0.4906619460083532 * z, /* g: */ x * -0.978795502912089 + y * 1.916254567259524 + 0.03344273116131949 * z, /* b: */ x * 0.07195537988411677 - y * 0.2289768264158322 + 1.405386058324125 * z); } // L: 0% = 0.0, 100% = 100.0 // for a and b: -100% = -125, 100% = 125 function hex2lab(token) { // @ts-ignore return srgb2lab(...hex2srgb(token)); } function rgb2lab(token) { // @ts-ignore return srgb2lab(...rgb2srgb(token)); } function hsl2lab(token) { // @ts-ignore return srgb2lab(...hsl2srgb(token)); } function hwb2lab(token) { // @ts-ignore return srgb2lab(...hwb2srgb(token)); } function lch2lab(token) { // @ts-ignore return lch2labvalues(...getLCHComponents(token)); } function oklab2lab(token) { // @ts-ignore return xyz2lab(...OKLab_to_XYZ(...getOKLABComponents(token))); } function oklch2lab(token) { // @ts-ignore return srgb2lab(...oklch2srgb(token)); } function srgb2lab(r, g, b, a) { // @ts-ignore */ const result = xyz2lab(...srgb2xyz(r, g, b)); // Fixes achromatic RGB colors having a _slight_ chroma due to floating-point errors // and approximated computations in sRGB <-> CIELab. // See: https://github.com/d3/d3-color/pull/46 if (r === b && b === g) { result[1] = result[2] = 0; } if (a != null) { result.push(a); } return result; } function xyz2lab(x, y, z, a = null) { // Assuming XYZ is relative to D50, convert to CIE Lab // from CIE standard, which now defines these as a rational fraction // var e = 216/24389; // 6^3/29^3 // var k = 24389/27; // 29^3/3^3 // compute xyz, which is XYZ scaled relative to reference white const xyz = [x, y, z].map((value, i) => value / D50[i]); // now compute f const f = xyz.map((value) => value > e ? Math.cbrt(value) : (k * value + 16) / 116); const result = [ (116 * f[1]) - 16, // L 500 * (f[0] - f[1]), // a 200 * (f[1] - f[2]) // b ]; // L in range [0,100]. For use in CSS, add a percent if (a != null && a != 1) { result.push(a); } return result; } function lch2labvalues(l, c, h, a = null) { // l, c * Math.cos(360 * h * Math.PI / 180), c * Math.sin(360 * h * Math.PI / 180 const result = [l, c * Math.cos(h * Math.PI / 180), c * Math.sin(h * Math.PI / 180)]; if (a != null) { result.push(a); } return result; } function getLABComponents(token) { const components = getComponents(token); // @ts-ignore let t = components[0]; // @ts-ignore const l = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? 100 : 1); // @ts-ignore t = components[1]; // @ts-ignore const a = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? 125 : 1); // @ts-ignore t = components[2]; // @ts-ignore const b = getNumber(t) * (t.typ == exports.EnumToken.PercentageTokenType ? 125 : 1); // @ts-ignore t = components[3]; // @ts-ignore const alpha = t == null ? 1 : getNumber(t); const result = [l, a, b]; if (alpha != null && alpha != 1) { result.push(alpha); } return result; } // from https://www.w3.org/TR/css-color-4/#color-conversion-code // D50 LAB function Lab_to_sRGB(l, a, b) { // @ts-ignore return xyzd502srgb(...Lab_to_XYZ(l, a, b)); } // from https://www.w3.org/TR/css-color-4/#color-conversion-code function Lab_to_XYZ(l, a, b) { // Convert Lab to D50-adapted XYZ // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html const k = 24389 / 27; // 29^3/3^3 const e = 216 / 24389; // 6^3/29^3 const f = []; // compute f, starting with the luminance-related term f[1] = (l + 16) / 116; f[0] = a / 500 + f[1]; f[2] = f[1] - b / 200; // compute xyz const xyz = [ Math.pow(f[0], 3) > e ? Math.pow(f[0], 3) : (116 * f[0] - 16) / k, l > k * e ? Math.pow((l + 16) / 116, 3) : l / k, Math.pow(f[2], 3) > e ? Math.pow(f[2], 3) : (116 * f[2] - 16) / k ]; // Compute XYZ by scaling xyz by reference white return xyz.map((value, i) => value * D50[i]); } // from https://www.w3.org/TR/css-color-4/#color-conversion-code // srgb-linear -> srgb // 0 <= r, g, b <= 1 function srgbvalues(token) { switch (token.kin) { case 'lit': case 'hex': return hex2srgb(token); case 'rgb': case 'rgba': return rgb2srgb(token); case 'hsl': case 'hsla': return hsl2srgb(token); case 'hwb': return hwb2srgb(token); case 'lab': return lab2srgb(token); case 'lch': return lch2srgb(token); case 'oklab': return oklab2srgb(token); case 'oklch': return oklch2srgb(token); case 'color': return color2srgbvalues(token); } return null; } function rgb2srgb(token) { return getComponents(token).map((t, index) => index == 3 ? ((t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') ? 1 : getNumber(t)) : (t.typ == exports.EnumToken.PercentageTokenType ? 255 : 1) * getNumber(t) / 255); } function hex2srgb(token) { const value = expandHexValue(token.kin == 'lit' ? COLORS_NAMES[token.val.toLowerCase()] : token.val); const rgb = []; for (let i = 1; i < value.length; i += 2) { rgb.push(parseInt(value.slice(i, i + 2), 16) / 255); } return rgb; } function xyz2srgb(x, y, z) { // @ts-ignore return lsrgb2srgbvalues(...XYZ_to_lin_sRGB(x, y, z)); } function hwb2srgb(token) { const { h: hue, s: white, l: black, a: alpha } = hslvalues(token); const rgb = hsl2srgbvalues(hue, 1, .5); for (let i = 0; i < 3; i++) { rgb[i] *= (1 - white - black); rgb[i] = rgb[i] + white; } if (alpha != null && alpha != 1) { rgb.push(alpha); } return rgb; } function hsl2srgb(token) { let { h, s, l, a } = hslvalues(token); return hsl2srgbvalues(h, s, l, a); } function cmyk2srgb(token) { const components = getComponents(token); // @ts-ignore let t = components[0]; // @ts-ignore const c = getNumber(t); // @ts-ignore t = components[1]; // @ts-ignore const m = getNumber(t); // @ts-ignore t = components[2]; // @ts-ignore const y = getNumber(t); // @ts-ignore t = components[3]; // @ts-ignore const k = getNumber(t); const rgb = [ 1 - Math.min(1, c * (1 - k) + k), 1 - Math.min(1, m * (1 - k) + k), 1 - Math.min(1, y * (1 - k) + k) ]; // @ts-ignore if (token.chi.length >= 9) { // @ts-ignore t = token.chi[8]; // @ts-ignore rgb.push(getNumber(t)); } return rgb; } function oklab2srgb(token) { const [l, a, b, alpha] = getOKLABComponents(token); const rgb = OKLab_to_sRGB(l, a, b); if (alpha != null && alpha != 1) { rgb.push(alpha); } return rgb; } function oklch2srgb(token) { const [l, c, h, alpha] = getOKLCHComponents(token); // @ts-ignore const rgb = OKLab_to_sRGB(...lch2labvalues(l, c, h)); if (alpha != 1) { rgb.push(alpha); } return rgb; } function hslvalues(token) { const components = getComponents(token); let t; // @ts-ignore let h = getAngle(components[0]); // @ts-ignore t = components[1]; // @ts-ignore let s = getNumber(t); // @ts-ignore t = components[2]; // @ts-ignore let l = getNumber(t); let a = null; if (token.chi?.length == 4) { // @ts-ignore t = token.chi[3]; // @ts-ignore a = getNumber(t); } return a == null ? { h, s, l } : { h, s, l, a }; } function hsl2srgbvalues(h, s, l, a = null) { let v = l <= .5 ? l * (1.0 + s) : l + s - l * s; let r = l; let g = l; let b = l; if (v > 0) { let m = l + l - v; let sv = (v - m) / v; h *= 6.0; let sextant = Math.floor(h); let fract = h - sextant; let vsf = v * sv * fract; let mid1 = m + vsf; let mid2 = v - vsf; switch (sextant) { case 0: r = v; g = mid1; b = m; break; case 1: r = mid2; g = v; b = m; break; case 2: r = m; g = v; b = mid1; break; case 3: r = m; g = mid2; b = v; break; case 4: r = mid1; g = m; b = v; break; case 5: r = v; g = m; b = mid2; break; } } const values = [r, g, b]; if (a != null && a != 1) { values.push(a); } return values; } function lab2srgb(token) { const [l, a, b, alpha] = getLABComponents(token); const rgb = Lab_to_sRGB(l, a, b); if (alpha != null && alpha != 1) { rgb.push(alpha); } return rgb; } function lch2srgb(token) { // @ts-ignore const [l, a, b, alpha] = lch2labvalues(...getLCHComponents(token)); // https://www.w3.org/TR/css-color-4/#lab-to-lch const rgb = Lab_to_sRGB(l, a, b); if (alpha != 1) { rgb.push(alpha); } return rgb; } // sRGB -> lRGB function srgb2lsrgbvalues(r, g, b, a = null) { // convert an array of linear-light sRGB values in the range 0.0-1.0 // to gamma corrected form // https://en.wikipedia.org/wiki/SRGB // Extended transfer function: // For negative values, linear portion extends on reflection // of axis, then uses reflected pow below that const rgb = [r, g, b].map((val) => { const abs = Math.abs(val); if (abs <= 0.04045) { return val / 12.92; } return (Math.sign(val) || 1) * Math.pow((abs + 0.055) / 1.055, 2.4); }); if (a != 1 && a != null) { rgb.push(a); } return rgb; } function lsrgb2srgbvalues(r, g, b, alpha) { // convert an array of linear-light sRGB values in the range 0.0-1.0 // to gamma corrected form // https://en.wikipedia.org/wiki/SRGB // Extended transfer function: // For negative values, linear portion extends on reflection // of axis, then uses reflected pow below that const rgb = [r, g, b].map((val) => { let abs = Math.abs(val); if (Math.abs(val) > 0.0031308) { return (Math.sign(val) || 1) * (1.055 * Math.pow(abs, 1 / 2.4) - 0.055); } return 12.92 * val; }); if (alpha != 1 && alpha != null) { rgb.push(alpha); } return rgb; } function srgb2rgb(value) { return minmax(Math.round(value * 255), 0, 255); } function hex2rgb(token) { const value = expandHexValue(token.kin == 'lit' ? COLORS_NAMES[token.val.toLowerCase()] : token.val); const rgb = []; for (let i = 1; i < value.length; i += 2) { rgb.push(parseInt(value.slice(i, i + 2), 16)); } return rgb; } function hwb2rgb(token) { return hwb2srgb(token).map(srgb2rgb); } function hsl2rgb(token) { let { h, s, l, a } = hslvalues(token); return hsl2srgbvalues(h, s, l, a).map((t) => minmax(Math.round(t * 255), 0, 255)); } function cmyk2rgb(token) { return cmyk2srgb(token).map(srgb2rgb); } function oklab2rgb(token) { return oklab2srgb(token).map(srgb2rgb); } function oklch2rgb(token) { return oklch2srgb(token).map(srgb2rgb); } function lab2rgb(token) { return lab2srgb(token).map(srgb2rgb); } function lch2rgb(token) { return lch2srgb(token).map(srgb2rgb); } function hwb2hsv(h, w, b, a) { // @ts-ignore return [h, 1 - w / (1 - b), 1 - b, a]; } // https://gist.github.com/defims/0ca2ef8832833186ed396a2f8a204117#file-annotated-js function hsl2hsv(h, s, l, a = null) { s *= l < .5 ? l : 1 - l; const result = [ //Range should be between 0 - 1 h, //Hue stays the same 2 * s / (l + s), //Saturation l + s //Value ]; if (a != null) { result.push(a); } return result; } function hex2hsl(token) { // @ts-ignore return rgb2hslvalues(...hex2rgb(token)); } function rgb2hsl(token) { const chi = getComponents(token); // @ts-ignore let t = chi[0]; // @ts-ignore let r = getNumber(t); // @ts-ignore t = chi[1]; // @ts-ignore let g = getNumber(t); // @ts-ignore t = chi[2]; // @ts-ignore let b = getNumber(t); // @ts-ignore t = chi[3]; // @ts-ignore let a = null; if (t != null && !(t.typ == exports.EnumToken.IdenTokenType && t.val == 'none')) { // @ts-ignore a = getNumber(t) / 255; } const values = [r, g, b]; if (a != null && a != 1) { values.push(a); } // @ts-ignore return rgb2hslvalues(...values); } // https://gist.github.com/defims/0ca2ef8832833186ed396a2f8a204117#file-annotated-js function hsv2hsl(h, s, v, a) { const result = [ //[hue, saturation, lightness] //Range should be between 0 - 1 h, //Hue stays the same //Saturation is very different between the two color spaces //If (2-sat)*val < 1 set it to sat*val/((2-sat)*val) //Otherwise sat*val/(2-(2-sat)*val) //Conditional is not operating with hue, it is reassigned! s * v / ((h = (2 - s) * v) < 1 ? h : 2 - h), h / 2, //Lightness is (2-sat)*val/2 ]; if (a != null) { result.push(a); } return result; } function hwb2hsl(token) { // @ts-ignore return hsv2hsl(...hwb2hsv(...Object.values(hslvalues(token)))); } function lab2hsl(token) { // @ts-ignore return rgb2hslvalues(...lab2rgb(token)); } function lch2hsl(token) { // @ts-ignore return rgb2hslvalues(...lch2rgb(token)); } function oklab2hsl(token) { // @ts-ignore return rgb2hslvalues(...oklab2rgb(token)); } function oklch2hsl(token) { // @ts-ignore return rgb2hslvalues(...oklch2rgb(token)); } function rgb2hslvalues(r, g, b, a = null) { return srgb2hsl(r / 255, g / 255, b / 255, a); } function srgb2hsl(r, g, b, a = null) { let max = Math.max(r, g, b); let min = Math.min(r, g, b); let h = 0; let s = 0; let l = (max + min) / 2; if (max != min) { let d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } const hsl = [h, s, l]; if (a != null && a < 1) { // @ts-ignore return hsl.concat([a]); } // @ts-ignore return hsl; } function rgb2hwb(token) { // @ts-ignore return srgb2hwb(...getComponents(token).map((t, index) => { if (index == 3 && t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') { return 1; } return getNumber(t) / 255;