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 Jun 14, 2021
1 parent edff656 commit 3cb4847
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 37 deletions.
148 changes: 112 additions & 36 deletions lib/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ exports.parseInteger = function parseInteger(val) {
if (numberRegEx.test(val)) {
return String(parseInt(val, 10));
}
return null;
return exports.parseCustomVariable(val);
};

exports.parseNumber = function parseNumber(val) {
Expand All @@ -92,7 +92,7 @@ exports.parseNumber = function parseNumber(val) {
if (numberRegEx.test(val)) {
return String(parseFloat(val));
}
return null;
return exports.parseCustomVariable(val);
};

exports.parseLength = function parseLength(val, resolve = false) {
Expand Down Expand Up @@ -140,7 +140,7 @@ exports.parseLength = function parseLength(val, resolve = false) {
}
return number + unit;
}
return null;
return exports.parseCustomVariable(val);
};

exports.parsePercentage = function parsePercentage(val, resolve = false) {
Expand All @@ -157,7 +157,7 @@ exports.parsePercentage = function parsePercentage(val, resolve = false) {
if (percentageRegEx.test(val)) {
return val;
}
return null;
return exports.parseCustomVariable(val);
};

exports.parseLengthOrPercentage = function parseLengthOrPercentage(val, resolve) {
Expand Down Expand Up @@ -189,7 +189,7 @@ exports.parseAngle = function parseAngle(val, resolve = false) {
}
return number + unit;
}
return null;
return exports.parseCustomVariable(val);
};

exports.parseTime = function parseTime(val, resolve = false) {
Expand All @@ -210,10 +210,15 @@ exports.parseTime = function parseTime(val, resolve = false) {
}
return number + unit;
}
return null;
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 null;
Expand Down Expand Up @@ -347,49 +352,56 @@ exports.parseKeyword = function parseKeyword(
if (valid.includes(lowerCaseValue)) {
return lowerCaseValue;
}
return null;
return exports.parseCustomVariable(val);
};

exports.parseCustomIdentifier = function parseCustomIdentifier(val) {
if (identRegEx.test(val) && !exports.parseKeyword(val) && val !== 'default') {
return val;
}
return null;
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) {
var res = urlRegEx.exec(val);
// does it match the regex?
if (!res) {
return null;
}
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 null;
}
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 null;
}
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 null;
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 null;
case '\\':
i++;
break;
}
}
}

return 'url(' + str + ')';
return 'url(' + str + ')';
}
return exports.parseCustomVariable(val);
};

exports.parseString = function parseString(val) {
Expand All @@ -412,10 +424,15 @@ exports.parseString = function parseString(val) {
}
return val;
}
return null;
return exports.parseCustomVariable(val);
};

exports.parseColor = function parseColor(val) {
const variable = exports.parseCustomVariable(val);
if (variable) {
return variable;
}

var red,
green,
blue,
Expand Down Expand Up @@ -527,6 +544,65 @@ exports.parseColor = function parseColor(val) {
return exports.parseKeyword(val, namedColors);
};

exports.parseCustomVariable = function parseCustomVariable(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 null;
}

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 null;
}

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 === null) {
return null;
}
}
parsedArgs.push(arg);
}

return `${before}var(${parsedArgs.join(', ')}${after}`;
};

/**
* utility to translate from border-width to borderWidth
*
Expand Down
1 change: 0 additions & 1 deletion scripts/download_latest_properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ const request = https.request(url, response => {
// Filter out all properties newer than Working Draft
status !== 'ED' &&
status !== 'FPWD' &&
// TODO: --* css Needs additional logic to this module, so filter it out for now
property !== '--*' &&
// Properties are often in multiple specifications
!properties.includes(property)
Expand Down

0 comments on commit 3cb4847

Please sign in to comment.