diff --git a/README.md b/README.md index eebf01c..ad1dc2c 100644 --- a/README.md +++ b/README.md @@ -355,6 +355,7 @@ Possible values: - `false`: Removes `--var` declarations and replaces `var()` with their resolved/computed values. - `true`: Keeps `var()` declarations in the output and has the computed value as a fallback declaration. Also keeps computed `--var` declarations. - `'computed'`: Keeps computed `--var` declarations in the output. Handy to make them available to your JavaScript. + - `(declaration) => boolean|'computed'` : Handles preservation behavior based on the respective declaration. ### `variables` (default: `{}`) diff --git a/index.js b/index.js index abcfe8d..70c8282 100644 --- a/index.js +++ b/index.js @@ -183,12 +183,18 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) { }); }); + let preserveDecl; + if (typeof opts.preserve === "function") { + preserveDecl = opts.preserve(decl); + } else { + preserveDecl = opts.preserve; + } // Remove the variable declaration because they are pretty much useless after we resolve them - if(!opts.preserve) { + if(!preserveDecl) { decl.remove(); } // Or we can also just show the computed value used for that variable - else if(opts.preserve === 'computed') { + else if(preserveDecl === 'computed') { decl.value = valueResults.value; } // Otherwise just keep them as var declarations diff --git a/lib/resolve-decl.js b/lib/resolve-decl.js index 214f570..e469849 100644 --- a/lib/resolve-decl.js +++ b/lib/resolve-decl.js @@ -72,7 +72,7 @@ function eachMapItemDependencyOfDecl(variablesUsedList, map, decl, cb) { // Resolve the decl with the computed value // Also add in any media queries that change the value as necessary function resolveDecl(decl, map, /*optional*/shouldPreserve, /*optional*/preserveAtRulesOrder, /*optional*/logResolveValueResult) { - shouldPreserve = shouldPreserve || false; + shouldPreserve = (typeof shouldPreserve === "function" ? shouldPreserve(decl) : shouldPreserve) || false; preserveAtRulesOrder = preserveAtRulesOrder || false; // Make it chainable @@ -101,7 +101,13 @@ function resolveDecl(decl, map, /*optional*/shouldPreserve, /*optional*/preserve // Add the declaration to our new rule ruleClone.append(declClone); - if(shouldPreserve === true) { + let preserveVariable; + if(typeof shouldPreserve === "function") { + preserveVariable = shouldPreserve(decl); + } else { + preserveVariable = shouldPreserve; + } + if(preserveVariable === true) { declClone.cloneAfter(); } diff --git a/test/fixtures/preserve-variables-conditionally.css b/test/fixtures/preserve-variables-conditionally.css new file mode 100644 index 0000000..2e2f203 --- /dev/null +++ b/test/fixtures/preserve-variables-conditionally.css @@ -0,0 +1,21 @@ +:root { + --color-one: #0000ff; + --color-two: #00ff00; + --color-three: var(--color-two); +} + +.before { + prop: before; + color: var(--color-one); +} + +.after { + color: var(--color-two); + prop: after; +} + +.before-and-after { + prop: before; + color: var(--missing, #ff0000); + otherprop: after; +} \ No newline at end of file diff --git a/test/fixtures/preserve-variables-conditionally.expected.css b/test/fixtures/preserve-variables-conditionally.expected.css new file mode 100644 index 0000000..c9108ff --- /dev/null +++ b/test/fixtures/preserve-variables-conditionally.expected.css @@ -0,0 +1,22 @@ +:root { + --color-two: #00ff00; + --color-three: var(--color-two); +} + +.before { + prop: before; + color: #0000ff; +} + +.after { + color: #00ff00; + color: var(--color-two); + prop: after; +} + +.before-and-after { + prop: before; + color: #ff0000; + color: var(--missing, #ff0000); + otherprop: after; +} \ No newline at end of file diff --git a/test/test.js b/test/test.js index b0867b0..7432752 100644 --- a/test/test.js +++ b/test/test.js @@ -227,6 +227,19 @@ describe('postcss-css-variables', function() { 'preserve-computed', { preserve: 'computed' } ); + + test( + 'preserves variables when `preserve` function applies', + 'preserve-variables-conditionally', + { + preserve: function (declaration) { + return !( + declaration.value.includes("--color-one") + || declaration.prop.includes("--color-one") + ) + } + } + ); });