diff --git a/lib/parsers.js b/lib/parsers.js index 55f9c998..efc4aa09 100644 --- a/lib/parsers.js +++ b/lib/parsers.js @@ -101,6 +101,7 @@ exports.parseInteger = function parseInteger(val) { if (numberRegEx.test(val)) { return String(parseInt(val, 10)); } + return exports.parseCustomVariable(val); }; exports.parseNumber = function parseNumber(val) { @@ -114,6 +115,7 @@ exports.parseNumber = function parseNumber(val) { if (numberRegEx.test(val)) { return String(parseFloat(val)); } + return exports.parseCustomVariable(val); }; exports.parseLength = function parseLength(val, resolve = false) { @@ -164,6 +166,7 @@ exports.parseLength = function parseLength(val, resolve = false) { } return number + unit; } + return exports.parseCustomVariable(val); }; exports.parsePercentage = function parsePercentage(val, resolve = false) { @@ -183,6 +186,7 @@ exports.parsePercentage = function parsePercentage(val, resolve = false) { if (percentageRegEx.test(val)) { return val; } + return exports.parseCustomVariable(val); }; exports.parseLengthOrPercentage = function parseLengthOrPercentage(val, resolve) { @@ -217,6 +221,7 @@ exports.parseAngle = function parseAngle(val, resolve = false) { } return number + unit; } + return exports.parseCustomVariable(val); }; exports.parseTime = function parseTime(val, resolve = false) { @@ -240,9 +245,15 @@ exports.parseTime = function parseTime(val, resolve = false) { } return number + unit; } + return exports.parseCustomVariable(val); }; exports.parseCalc = function parseCalc(val, parseOperand = exports.parseNumber) { + const variable = exports.parseCustomVariable(val); + if (variable) { + return variable; + } + const res = calcRegEx.exec(val); if (!res) { return undefined; @@ -378,6 +389,7 @@ exports.parseKeyword = function parseKeyword(val, valid = []) { if (valid.includes(lowerCaseValue)) { return lowerCaseValue; } + return exports.parseCustomVariable(val); }; exports.parseCustomIdentifier = function parseCustomIdentifier(val) { @@ -387,6 +399,14 @@ exports.parseCustomIdentifier = function parseCustomIdentifier(val) { if (identRegEx.test(val) && !exports.parseKeyword(val) && val !== 'default') { return val; } + return exports.parseCustomVariable(val); +}; + +exports.parseDashedIdentifier = function parseDashedIdentifier(val) { + if (identRegEx.test(val) && val.startsWith('--')) { + return val; + } + return exports.parseCustomVariable(val); }; exports.parseUrl = function parseUrl(val) { @@ -395,36 +415,36 @@ exports.parseUrl = function parseUrl(val) { } var res = urlRegEx.exec(val); // does it match the regex? - if (!res) { - return undefined; - } - var str = res[1]; - // if it starts with single or double quotes, does it end with the same? - if ((str[0] === '"' || str[0] === "'") && str[0] !== str[str.length - 1]) { - return undefined; - } - if (str[0] === '"' || str[0] === "'") { - str = str.substr(1, str.length - 2); - } + if (res) { + var str = res[1]; + // if it starts with single or double quotes, does it end with the same? + if ((str[0] === '"' || str[0] === "'") && str[0] !== str[str.length - 1]) { + return undefined; + } + if (str[0] === '"' || str[0] === "'") { + str = str.substr(1, str.length - 2); + } - var i; - for (i = 0; i < str.length; i++) { - switch (str[i]) { - case '(': - case ')': - case ' ': - case '\t': - case '\n': - case "'": - case '"': - return undefined; - case '\\': - i++; - break; + var i; + for (i = 0; i < str.length; i++) { + switch (str[i]) { + case '(': + case ')': + case ' ': + case '\t': + case '\n': + case "'": + case '"': + return undefined; + case '\\': + i++; + break; + } } - } - return 'url(' + str + ')'; + return 'url(' + str + ')'; + } + return exports.parseCustomVariable(val); }; exports.parseString = function parseString(val) { @@ -450,12 +470,19 @@ exports.parseString = function parseString(val) { } return val; } + return exports.parseCustomVariable(val); }; exports.parseColor = function parseColor(val) { if (val === '') { return val; } + + const variable = exports.parseCustomVariable(val); + if (variable) { + return variable; + } + var red, green, blue, @@ -567,6 +594,71 @@ exports.parseColor = function parseColor(val) { return exports.parseKeyword(val, namedColors); }; +exports.parseCustomVariable = function parseCustomVariable(val) { + if (val === '') { + return val; + } + + let before = ''; + let call = ''; + let i = -1; + let char; + + while ((char = val[++i]) && call !== 'var(') { + if (/[var(]/i.test(char)) { + if ('var('.startsWith(call)) { + call += char.toLowerCase(); + } else { + before += call; + call = char; + } + } else { + before += call; + call = ''; + before += char; + } + } + + if (call !== 'var(') { + return undefined; + } + + let open = 1; + let j = i; + + while ((char = val[++j]) && open > 0) { + if (char === '(') { + open++; + } else if (char === ')') { + open--; + } + } + + const splitIndex = open ? j : j - 1; + const stringArgs = val.slice(i, splitIndex); + const after = val.slice(splitIndex) || ''; + const [args] = exports.splitTokens(stringArgs, /,/); + const property = exports.parseDashedIdentifier(args.shift()); + + if (!property) { + return undefined; + } + + const parsedArgs = [property]; + for (let i = 0; i < args.length; i++) { + let arg = args[i]; + if (arg.toLowerCase().startsWith('var(')) { + arg = parseCustomVariable(arg); + if (arg === undefined) { + return undefined; + } + } + parsedArgs.push(arg); + } + + return `${before}var(${parsedArgs.join(', ')}${after}`; +}; + /** * @param {string} val * @param {RegExp} separators