{"version":3,"file":"css-var.js","sources":["../../../src/js/css-var.ts"],"sourcesContent":["/**\n * css-var\n */\n\nimport { CSSToken, TokenType, tokenize } from '@csstools/css-tokenizer';\nimport {\n CacheItem,\n NullObject,\n createCacheKey,\n getCache,\n setCache\n} from './cache';\nimport { isString } from './common';\nimport { cssCalc } from './css-calc';\nimport { isColor } from './util';\nimport { Options } from './typedef';\n\n/* constants */\nimport { FN_VAR, SYN_FN_CALC, SYN_FN_VAR, VAL_SPEC } from './constant';\nconst {\n CloseParen: PAREN_CLOSE,\n Comment: COMMENT,\n EOF,\n Ident: IDENT,\n Whitespace: W_SPACE\n} = TokenType;\nconst NAMESPACE = 'css-var';\n\n/* regexp */\nconst REG_FN_CALC = new RegExp(SYN_FN_CALC);\nconst REG_FN_VAR = new RegExp(SYN_FN_VAR);\n\n/**\n * resolve custom property\n * @param tokens - CSS tokens\n * @param [opt] - options\n * @returns result - [tokens, resolvedValue]\n */\nexport function resolveCustomProperty(\n tokens: CSSToken[],\n opt: Options = {}\n): [CSSToken[], string] {\n if (!Array.isArray(tokens)) {\n throw new TypeError(`${tokens} is not an array.`);\n }\n const { customProperty = {} } = opt;\n const items: string[] = [];\n while (tokens.length) {\n const token = tokens.shift();\n if (!Array.isArray(token)) {\n throw new TypeError(`${token} is not an array.`);\n }\n const [type, value] = token as [TokenType, string];\n // end of var()\n if (type === PAREN_CLOSE) {\n break;\n }\n // nested var()\n if (value === FN_VAR) {\n const [restTokens, item] = resolveCustomProperty(tokens, opt);\n tokens = restTokens;\n if (item) {\n items.push(item);\n }\n } else if (type === IDENT) {\n if (value.startsWith('--')) {\n let item;\n if (Object.hasOwnProperty.call(customProperty, value)) {\n item = customProperty[value] as string;\n } else if (typeof customProperty.callback === 'function') {\n item = customProperty.callback(value);\n }\n if (item) {\n items.push(item);\n }\n } else if (value) {\n items.push(value);\n }\n }\n }\n let resolveAsColor = false;\n if (items.length > 1) {\n const lastValue = items[items.length - 1];\n resolveAsColor = isColor(lastValue);\n }\n let resolvedValue = '';\n for (let item of items) {\n item = item.trim();\n if (REG_FN_VAR.test(item)) {\n // recurse resolveVar()\n const resolvedItem = resolveVar(item, opt);\n if (isString(resolvedItem)) {\n if (resolveAsColor) {\n if (isColor(resolvedItem)) {\n resolvedValue = resolvedItem;\n }\n } else {\n resolvedValue = resolvedItem;\n }\n }\n } else if (REG_FN_CALC.test(item)) {\n item = cssCalc(item, opt);\n if (resolveAsColor) {\n if (isColor(item)) {\n resolvedValue = item;\n }\n } else {\n resolvedValue = item;\n }\n } else if (\n item &&\n !/^(?:inherit|initial|revert(?:-layer)?|unset)$/.test(item)\n ) {\n if (resolveAsColor) {\n if (isColor(item)) {\n resolvedValue = item;\n }\n } else {\n resolvedValue = item;\n }\n }\n if (resolvedValue) {\n break;\n }\n }\n return [tokens, resolvedValue];\n}\n\n/**\n * parse tokens\n * @param tokens - CSS tokens\n * @param [opt] - options\n * @returns parsed tokens\n */\nexport function parseTokens(\n tokens: CSSToken[],\n opt: Options = {}\n): string[] | NullObject {\n const res: string[] = [];\n while (tokens.length) {\n const token = tokens.shift();\n const [type = '', value = ''] = token as [TokenType, string];\n if (value === FN_VAR) {\n const [restTokens, resolvedValue] = resolveCustomProperty(tokens, opt);\n if (!resolvedValue) {\n return new NullObject();\n }\n tokens = restTokens;\n res.push(resolvedValue);\n } else {\n switch (type) {\n case PAREN_CLOSE: {\n if (res.length) {\n const lastValue = res[res.length - 1];\n if (lastValue === ' ') {\n res.splice(-1, 1, value);\n } else {\n res.push(value);\n }\n } else {\n res.push(value);\n }\n break;\n }\n case W_SPACE: {\n if (res.length) {\n const lastValue = res[res.length - 1];\n if (\n isString(lastValue) &&\n !lastValue.endsWith('(') &&\n lastValue !== ' '\n ) {\n res.push(value);\n }\n }\n break;\n }\n default: {\n if (type !== COMMENT && type !== EOF) {\n res.push(value);\n }\n }\n }\n }\n }\n return res;\n}\n\n/**\n * resolve CSS var()\n * @param value - CSS value including var()\n * @param [opt] - options\n * @returns resolved value\n */\nexport function resolveVar(\n value: string,\n opt: Options = {}\n): string | NullObject {\n const { format = '' } = opt;\n if (isString(value)) {\n if (!REG_FN_VAR.test(value) || format === VAL_SPEC) {\n return value;\n }\n value = value.trim();\n } else {\n throw new TypeError(`${value} is not a string.`);\n }\n const cacheKey: string = createCacheKey(\n {\n namespace: NAMESPACE,\n name: 'resolveVar',\n value\n },\n opt\n );\n const cachedResult = getCache(cacheKey);\n if (cachedResult instanceof CacheItem) {\n if (cachedResult.isNull) {\n return cachedResult as NullObject;\n }\n return cachedResult.item as string;\n }\n const tokens = tokenize({ css: value });\n const values = parseTokens(tokens, opt);\n if (Array.isArray(values)) {\n let color = values.join('');\n if (REG_FN_CALC.test(color)) {\n color = cssCalc(color, opt);\n }\n setCache(cacheKey, color);\n return color;\n } else {\n setCache(cacheKey, null);\n return new NullObject();\n }\n}\n\n/**\n * CSS var()\n * @param value - CSS value including var()\n * @param [opt] - options\n * @returns resolved value\n */\nexport const cssVar = (value: string, opt: Options = {}): string => {\n const resolvedValue = resolveVar(value, opt);\n if (isString(resolvedValue)) {\n return resolvedValue;\n }\n return '';\n};\n"],"names":[],"mappings":";;;;;;AAmBA,MAAM;AAAA,EACJ,YAAY;AAAA,EACZ,SAAS;AAAA,EACT;AAAA,EACA,OAAO;AAAA,EACP,YAAY;AACd,IAAI;AACJ,MAAM,YAAY;AAGlB,MAAM,cAAc,IAAI,OAAO,WAAW;AAC1C,MAAM,aAAa,IAAI,OAAO,UAAU;AAQjC,SAAS,sBACd,QACA,MAAe,IACO;AACtB,MAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,UAAM,IAAI,UAAU,GAAG,MAAM,mBAAmB;AAAA,EAAA;AAElD,QAAM,EAAE,iBAAiB,CAAC,EAAA,IAAM;AAChC,QAAM,QAAkB,CAAC;AACzB,SAAO,OAAO,QAAQ;AACd,UAAA,QAAQ,OAAO,MAAM;AAC3B,QAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,YAAM,IAAI,UAAU,GAAG,KAAK,mBAAmB;AAAA,IAAA;AAE3C,UAAA,CAAC,MAAM,KAAK,IAAI;AAEtB,QAAI,SAAS,aAAa;AACxB;AAAA,IAAA;AAGF,QAAI,UAAU,QAAQ;AACpB,YAAM,CAAC,YAAY,IAAI,IAAI,sBAAsB,QAAQ,GAAG;AACnD,eAAA;AACT,UAAI,MAAM;AACR,cAAM,KAAK,IAAI;AAAA,MAAA;AAAA,IACjB,WACS,SAAS,OAAO;AACrB,UAAA,MAAM,WAAW,IAAI,GAAG;AACtB,YAAA;AACJ,YAAI,OAAO,eAAe,KAAK,gBAAgB,KAAK,GAAG;AACrD,iBAAO,eAAe,KAAK;AAAA,QAClB,WAAA,OAAO,eAAe,aAAa,YAAY;AACjD,iBAAA,eAAe,SAAS,KAAK;AAAA,QAAA;AAEtC,YAAI,MAAM;AACR,gBAAM,KAAK,IAAI;AAAA,QAAA;AAAA,iBAER,OAAO;AAChB,cAAM,KAAK,KAAK;AAAA,MAAA;AAAA,IAClB;AAAA,EACF;AAEF,MAAI,iBAAiB;AACjB,MAAA,MAAM,SAAS,GAAG;AACpB,UAAM,YAAY,MAAM,MAAM,SAAS,CAAC;AACxC,qBAAiB,QAAQ,SAAS;AAAA,EAAA;AAEpC,MAAI,gBAAgB;AACpB,WAAS,QAAQ,OAAO;AACtB,WAAO,KAAK,KAAK;AACb,QAAA,WAAW,KAAK,IAAI,GAAG;AAEnB,YAAA,eAAe,WAAW,MAAM,GAAG;AACrC,UAAA,SAAS,YAAY,GAAG;AAC1B,YAAI,gBAAgB;AACd,cAAA,QAAQ,YAAY,GAAG;AACT,4BAAA;AAAA,UAAA;AAAA,QAClB,OACK;AACW,0BAAA;AAAA,QAAA;AAAA,MAClB;AAAA,IAEO,WAAA,YAAY,KAAK,IAAI,GAAG;AAC1B,aAAA,QAAQ,MAAM,GAAG;AACxB,UAAI,gBAAgB;AACd,YAAA,QAAQ,IAAI,GAAG;AACD,0BAAA;AAAA,QAAA;AAAA,MAClB,OACK;AACW,wBAAA;AAAA,MAAA;AAAA,eAGlB,QACA,CAAC,gDAAgD,KAAK,IAAI,GAC1D;AACA,UAAI,gBAAgB;AACd,YAAA,QAAQ,IAAI,GAAG;AACD,0BAAA;AAAA,QAAA;AAAA,MAClB,OACK;AACW,wBAAA;AAAA,MAAA;AAAA,IAClB;AAEF,QAAI,eAAe;AACjB;AAAA,IAAA;AAAA,EACF;AAEK,SAAA,CAAC,QAAQ,aAAa;AAC/B;AAQO,SAAS,YACd,QACA,MAAe,IACQ;AACvB,QAAM,MAAgB,CAAC;AACvB,SAAO,OAAO,QAAQ;AACd,UAAA,QAAQ,OAAO,MAAM;AAC3B,UAAM,CAAC,OAAO,IAAI,QAAQ,EAAE,IAAI;AAChC,QAAI,UAAU,QAAQ;AACpB,YAAM,CAAC,YAAY,aAAa,IAAI,sBAAsB,QAAQ,GAAG;AACrE,UAAI,CAAC,eAAe;AAClB,eAAO,IAAI,WAAW;AAAA,MAAA;AAEf,eAAA;AACT,UAAI,KAAK,aAAa;AAAA,IAAA,OACjB;AACL,cAAQ,MAAM;AAAA,QACZ,KAAK,aAAa;AAChB,cAAI,IAAI,QAAQ;AACd,kBAAM,YAAY,IAAI,IAAI,SAAS,CAAC;AACpC,gBAAI,cAAc,KAAK;AACjB,kBAAA,OAAO,IAAI,GAAG,KAAK;AAAA,YAAA,OAClB;AACL,kBAAI,KAAK,KAAK;AAAA,YAAA;AAAA,UAChB,OACK;AACL,gBAAI,KAAK,KAAK;AAAA,UAAA;AAEhB;AAAA,QAAA;AAAA,QAEF,KAAK,SAAS;AACZ,cAAI,IAAI,QAAQ;AACd,kBAAM,YAAY,IAAI,IAAI,SAAS,CAAC;AAElC,gBAAA,SAAS,SAAS,KAClB,CAAC,UAAU,SAAS,GAAG,KACvB,cAAc,KACd;AACA,kBAAI,KAAK,KAAK;AAAA,YAAA;AAAA,UAChB;AAEF;AAAA,QAAA;AAAA,QAEF,SAAS;AACH,cAAA,SAAS,WAAW,SAAS,KAAK;AACpC,gBAAI,KAAK,KAAK;AAAA,UAAA;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEK,SAAA;AACT;AAQO,SAAS,WACd,OACA,MAAe,IACM;AACf,QAAA,EAAE,SAAS,GAAA,IAAO;AACpB,MAAA,SAAS,KAAK,GAAG;AACnB,QAAI,CAAC,WAAW,KAAK,KAAK,KAAK,WAAW,UAAU;AAC3C,aAAA;AAAA,IAAA;AAET,YAAQ,MAAM,KAAK;AAAA,EAAA,OACd;AACL,UAAM,IAAI,UAAU,GAAG,KAAK,mBAAmB;AAAA,EAAA;AAEjD,QAAM,WAAmB;AAAA,IACvB;AAAA,MACE,WAAW;AAAA,MACX,MAAM;AAAA,MACN;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACM,QAAA,eAAe,SAAS,QAAQ;AACtC,MAAI,wBAAwB,WAAW;AACrC,QAAI,aAAa,QAAQ;AAChB,aAAA;AAAA,IAAA;AAET,WAAO,aAAa;AAAA,EAAA;AAEtB,QAAM,SAAS,SAAS,EAAE,KAAK,OAAO;AAChC,QAAA,SAAS,YAAY,QAAQ,GAAG;AAClC,MAAA,MAAM,QAAQ,MAAM,GAAG;AACrB,QAAA,QAAQ,OAAO,KAAK,EAAE;AACtB,QAAA,YAAY,KAAK,KAAK,GAAG;AACnB,cAAA,QAAQ,OAAO,GAAG;AAAA,IAAA;AAE5B,aAAS,UAAU,KAAK;AACjB,WAAA;AAAA,EAAA,OACF;AACL,aAAS,UAAU,IAAI;AACvB,WAAO,IAAI,WAAW;AAAA,EAAA;AAE1B;AAQO,MAAM,SAAS,CAAC,OAAe,MAAe,OAAe;AAC5D,QAAA,gBAAgB,WAAW,OAAO,GAAG;AACvC,MAAA,SAAS,aAAa,GAAG;AACpB,WAAA;AAAA,EAAA;AAEF,SAAA;AACT;"}