{"version":3,"file":"util.js","sources":["../../../src/js/util.ts"],"sourcesContent":["/**\n * util\n */\n\nimport { TokenType, tokenize } from '@csstools/css-tokenizer';\nimport { CacheItem, createCacheKey, getCache, setCache } from './cache';\nimport { isString } from './common';\nimport { resolveColor } from './resolve';\nimport { Options } from './typedef';\n\n/* constants */\nimport { NAMED_COLORS } from './color';\nimport { SYN_COLOR_TYPE, SYN_MIX, VAL_SPEC } from './constant';\nconst {\n CloseParen: PAREN_CLOSE,\n Comma: COMMA,\n Comment: COMMENT,\n Delim: DELIM,\n EOF,\n Function: FUNC,\n Ident: IDENT,\n OpenParen: PAREN_OPEN,\n Whitespace: W_SPACE\n} = TokenType;\nconst NAMESPACE = 'util';\n\n/* numeric constants */\nconst DEC = 10;\nconst HEX = 16;\nconst DEG = 360;\nconst DEG_HALF = 180;\n\n/* regexp */\nconst REG_COLOR = new RegExp(`^(?:${SYN_COLOR_TYPE})$`);\nconst REG_FN_COLOR =\n /^(?:(?:ok)?l(?:ab|ch)|color(?:-mix)?|hsla?|hwb|rgba?|var)\\(/;\nconst REG_MIX = new RegExp(SYN_MIX);\n\n/**\n * split value\n * NOTE: comments are stripped, it can be preserved if, in the options param,\n * `delimiter` is either ',' or '/' and with `preserveComment` set to `true`\n * @param value - CSS value\n * @param [opt] - options\n * @returns array of values\n */\nexport const splitValue = (value: string, opt: Options = {}): string[] => {\n if (isString(value)) {\n value = value.trim();\n } else {\n throw new TypeError(`${value} is not a string.`);\n }\n const { delimiter = ' ', preserveComment = false } = opt;\n const cacheKey: string = createCacheKey(\n {\n namespace: NAMESPACE,\n name: 'splitValue',\n value\n },\n {\n delimiter,\n preserveComment\n }\n );\n const cachedResult = getCache(cacheKey);\n if (cachedResult instanceof CacheItem) {\n return cachedResult.item as string[];\n }\n let regDelimiter;\n if (delimiter === ',') {\n regDelimiter = /^,$/;\n } else if (delimiter === '/') {\n regDelimiter = /^\\/$/;\n } else {\n regDelimiter = /^\\s+$/;\n }\n const tokens = tokenize({ css: value });\n let nest = 0;\n let str = '';\n const res: string[] = [];\n while (tokens.length) {\n const [type, value] = tokens.shift() as [TokenType, string];\n switch (type) {\n case COMMA: {\n if (regDelimiter.test(value)) {\n if (nest === 0) {\n res.push(str.trim());\n str = '';\n } else {\n str += value;\n }\n } else {\n str += value;\n }\n break;\n }\n case DELIM: {\n if (regDelimiter.test(value)) {\n if (nest === 0) {\n res.push(str.trim());\n str = '';\n } else {\n str += value;\n }\n } else {\n str += value;\n }\n break;\n }\n case COMMENT: {\n if (preserveComment && (delimiter === ',' || delimiter === '/')) {\n str += value;\n }\n break;\n }\n case FUNC:\n case PAREN_OPEN: {\n str += value;\n nest++;\n break;\n }\n case PAREN_CLOSE: {\n str += value;\n nest--;\n break;\n }\n case W_SPACE: {\n if (regDelimiter.test(value)) {\n if (nest === 0) {\n if (str) {\n res.push(str.trim());\n str = '';\n }\n } else {\n str += ' ';\n }\n } else if (!str.endsWith(' ')) {\n str += ' ';\n }\n break;\n }\n default: {\n if (type === EOF) {\n res.push(str.trim());\n str = '';\n } else {\n str += value;\n }\n }\n }\n }\n setCache(cacheKey, res);\n return res;\n};\n\n/**\n * extract dashed-ident tokens\n * @param value - CSS value\n * @returns array of dashed-ident tokens\n */\nexport const extractDashedIdent = (value: string): string[] => {\n if (isString(value)) {\n value = value.trim();\n } else {\n throw new TypeError(`${value} is not a string.`);\n }\n const cacheKey: string = createCacheKey({\n namespace: NAMESPACE,\n name: 'extractDashedIdent',\n value\n });\n const cachedResult = getCache(cacheKey);\n if (cachedResult instanceof CacheItem) {\n return cachedResult.item as string[];\n }\n const tokens = tokenize({ css: value });\n const items = new Set();\n while (tokens.length) {\n const [type, value] = tokens.shift() as [TokenType, string];\n if (type === IDENT && value.startsWith('--')) {\n items.add(value);\n }\n }\n const res = [...items] as string[];\n setCache(cacheKey, res);\n return res;\n};\n\n/**\n * is color\n * @param value - CSS value\n * @param [opt] - options\n * @returns result\n */\nexport const isColor = (value: unknown, opt: Options = {}): boolean => {\n if (isString(value)) {\n value = value.toLowerCase().trim();\n if (value && isString(value)) {\n if (/^[a-z]+$/.test(value)) {\n if (\n /^(?:currentcolor|transparent)$/.test(value) ||\n Object.prototype.hasOwnProperty.call(NAMED_COLORS, value)\n ) {\n return true;\n }\n } else if (REG_COLOR.test(value) || REG_MIX.test(value)) {\n return true;\n } else if (REG_FN_COLOR.test(value)) {\n opt.nullable = true;\n if (!opt.format) {\n opt.format = VAL_SPEC;\n }\n const resolvedValue = resolveColor(value, opt);\n if (resolvedValue) {\n return true;\n }\n }\n }\n }\n return false;\n};\n\n/**\n * value to JSON string\n * @param value - CSS value\n * @param [func] - stringify function\n * @returns stringified value in JSON notation\n */\nexport const valueToJsonString = (\n value: unknown,\n func: boolean = false\n): string => {\n if (typeof value === 'undefined') {\n return '';\n }\n const res = JSON.stringify(value, (_key, val) => {\n let replacedValue;\n if (typeof val === 'undefined') {\n replacedValue = null;\n } else if (typeof val === 'function') {\n if (func) {\n replacedValue = val.toString().replace(/\\s/g, '').substring(0, HEX);\n } else {\n replacedValue = val.name;\n }\n } else if (val instanceof Map || val instanceof Set) {\n replacedValue = [...val];\n } else if (typeof val === 'bigint') {\n replacedValue = val.toString();\n } else {\n replacedValue = val;\n }\n return replacedValue;\n });\n return res;\n};\n\n/**\n * round to specified precision\n * @param value - numeric value\n * @param bit - minimum bits\n * @returns rounded value\n */\nexport const roundToPrecision = (value: number, bit: number = 0): number => {\n if (!Number.isFinite(value)) {\n throw new TypeError(`${value} is not a finite number.`);\n }\n if (!Number.isFinite(bit)) {\n throw new TypeError(`${bit} is not a finite number.`);\n } else if (bit < 0 || bit > HEX) {\n throw new RangeError(`${bit} is not between 0 and ${HEX}.`);\n }\n if (bit === 0) {\n return Math.round(value);\n }\n let val;\n if (bit === HEX) {\n val = value.toPrecision(6);\n } else if (bit < DEC) {\n val = value.toPrecision(4);\n } else {\n val = value.toPrecision(5);\n }\n return parseFloat(val);\n};\n\n/**\n * interpolate hue\n * @param hueA - hue value\n * @param hueB - hue value\n * @param arc - shorter | longer | increasing | decreasing\n * @returns result - [hueA, hueB]\n */\nexport const interpolateHue = (\n hueA: number,\n hueB: number,\n arc: string = 'shorter'\n): [number, number] => {\n if (!Number.isFinite(hueA)) {\n throw new TypeError(`${hueA} is not a finite number.`);\n }\n if (!Number.isFinite(hueB)) {\n throw new TypeError(`${hueB} is not a finite number.`);\n }\n switch (arc) {\n case 'decreasing': {\n if (hueB > hueA) {\n hueA += DEG;\n }\n break;\n }\n case 'increasing': {\n if (hueB < hueA) {\n hueB += DEG;\n }\n break;\n }\n case 'longer': {\n if (hueB > hueA && hueB < hueA + DEG_HALF) {\n hueA += DEG;\n } else if (hueB > hueA + DEG_HALF * -1 && hueB <= hueA) {\n hueB += DEG;\n }\n break;\n }\n case 'shorter':\n default: {\n if (hueB > hueA + DEG_HALF) {\n hueA += DEG;\n } else if (hueB < hueA + DEG_HALF * -1) {\n hueB += DEG;\n }\n }\n }\n return [hueA, hueB];\n};\n"],"names":["value"],"mappings":"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"}