From 6e9b5ab9d0aa820249beb0275fb15ad3e2814f73 Mon Sep 17 00:00:00 2001 From: Peter Galiba Date: Mon, 9 Dec 2019 10:43:35 +0000 Subject: [PATCH 1/3] Fix algorithm to find balanced var() pairs --- lib/resolve-value.js | 43 ++++++++++++++++++- test/fixtures/fallback-with-parenthesis.css | 6 +++ .../fallback-with-parenthesis.expected.css | 3 ++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/fallback-with-parenthesis.css create mode 100644 test/fixtures/fallback-with-parenthesis.expected.css diff --git a/lib/resolve-value.js b/lib/resolve-value.js index 1954758..b6c59da 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 (/(?:^|\s)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 From 769ce4baffc82de9a82215627f57d8330f8436b9 Mon Sep 17 00:00:00 2001 From: Peter Galiba Date: Mon, 9 Dec 2019 10:53:41 +0000 Subject: [PATCH 2/3] Add missing test for fallback --- test/test.js | 1 + 1 file changed, 1 insertion(+) 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'); From 0e907191340b857026264de3ae387a56c70c0e71 Mon Sep 17 00:00:00 2001 From: Peter Galiba Date: Mon, 9 Dec 2019 11:14:39 +0000 Subject: [PATCH 3/3] Less restricitive check for what can be before var( --- lib/resolve-value.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/resolve-value.js b/lib/resolve-value.js index b6c59da..60b6789 100644 --- a/lib/resolve-value.js +++ b/lib/resolve-value.js @@ -20,7 +20,7 @@ function balancedVar(value) { var match = balanced('(', ')', value) if (match) { // Check if it was prepended with var - if (/(?:^|\s)var$/.test(match.pre)) { + if (/(?:^|[^\w-])var$/.test(match.pre)) { // Remove the var from the end of pre return { pre: match.pre.slice(0, -3),