Skip to content

Commit

Permalink
feat: custom var()
Browse files Browse the repository at this point in the history
Fixes jsdom#125
  • Loading branch information
cdoublev committed May 24, 2021
1 parent ead9844 commit fdfc90e
Showing 1 changed file with 119 additions and 27 deletions.
146 changes: 119 additions & 27 deletions lib/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit fdfc90e

Please sign in to comment.