diff --git a/lib/resolve-value.js b/lib/resolve-value.js index 1954758..60b6789 100644 --- a/lib/resolve-value.js +++ b/lib/resolve-value.js @@ -14,6 +14,45 @@ function toString(value) { return String(value); } +// Check for balanced `var(` and `)` pairs inside `value`, and return the 3 fragments: +// `body` (inside), `pre` (before), `post` (after) of the found wrapper +function balancedVar(value) { + var match = balanced('(', ')', value) + if (match) { + // Check if it was prepended with var + if (/(?:^|[^\w-])var$/.test(match.pre)) { + // Remove the var from the end of pre + return { + pre: match.pre.slice(0, -3), + body: match.body, + post: match.post + } + } else { + // Check inside body + var bodyMatch = balancedVar(match.body) + if (bodyMatch) { + // Reconstruct pre and post + return { + pre: match.pre + '(' + bodyMatch.pre, + body: bodyMatch.body, + post: bodyMatch.post + ')' + match.post + } + } else { + // Check inside post + var postMatch = balancedVar(match.post) + if (postMatch) { + // Reconstruct pre + return { + pre: match.pre + '(' + match.body + ')' + postMatch.pre, + body: postMatch.body, + post: postMatch.post + } + } + } + } + } +} + // Pass in a value string to parse/resolve and a map of available values // and we can figure out the final value // @@ -34,7 +73,7 @@ var resolveValue = function(decl, map, /*optional*/ignorePseudoScope, /*internal // Create a temporary variable, storing resultantValue variable value var remainingVariableValue = resultantValue; // Use balanced lib to find var() declarations and store variable names - while ((matchingVarDecl = balanced('var(', ')', remainingVariableValue))) { + while ((matchingVarDecl = balancedVar(remainingVariableValue))) { // Split at the comma to find variable name and fallback value // There may be other commas in the values so this isn't necessarily just 2 pieces var variableFallbackSplitPieces = matchingVarDecl.body.split(','); @@ -61,7 +100,7 @@ var resolveValue = function(decl, map, /*optional*/ignorePseudoScope, /*internal // var() = var( [, ]? ) // matches `name[, fallback]`, captures "name" and "fallback" // See: http://dev.w3.org/csswg/css-variables/#funcdef-var - while ((matchingVarDecl = balanced('var(', ')', resultantValue))) { + while ((matchingVarDecl = balancedVar(resultantValue))) { var matchingVarDeclMapItem = undefined; // Split at the comma to find variable name and fallback value diff --git a/test/fixtures/fallback-with-parenthesis.css b/test/fixtures/fallback-with-parenthesis.css new file mode 100644 index 0000000..661408d --- /dev/null +++ b/test/fixtures/fallback-with-parenthesis.css @@ -0,0 +1,6 @@ +:root { + --box-shadow: 0px 2px 2px 0px #fff; +} +.box { + box-shadow: var(--box-shadow, 0px 2px 8px 0px rgba(0, 0, 0, 0.5)); +} \ No newline at end of file diff --git a/test/fixtures/fallback-with-parenthesis.expected.css b/test/fixtures/fallback-with-parenthesis.expected.css new file mode 100644 index 0000000..75680f0 --- /dev/null +++ b/test/fixtures/fallback-with-parenthesis.expected.css @@ -0,0 +1,3 @@ +.box { + box-shadow: 0px 2px 2px 0px #fff; +} \ No newline at end of file diff --git a/test/test.js b/test/test.js index b0867b0..1f91bfd 100644 --- a/test/test.js +++ b/test/test.js @@ -89,6 +89,7 @@ describe('postcss-css-variables', function() { test('should work with variables declared in root', 'root-variable'); + test('should work with variables with parenthesis in fallback', 'fallback-with-parenthesis'); test('should work with locally scoped variable in a non-root rule', 'local-variable-non-root');