Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,13 @@ Can be a simple key-value pair or an object with a `value` property and an optio

The object keys are automatically prefixed with `--` (according to CSS custom property syntax) if you do not provide it.

### `preserveInjectedVariables` (default: `true`)

Whether to preserve the custom property declarations inserted via the `variables` option from final output.

A typical use case is [CSS Modules](https://github.com/css-modules/css-modules), where you would want to avoid
repeating custom property definitions in every module passed through this plugin. Setting this option to `false`
prevents JS-injected variables from appearing in output CSS.

```js
var postcss = require('postcss');
Expand Down
19 changes: 18 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ var defaults = {
// Define variables via JS
// Simple key-value pair
// or an object with a `value` property and an optional `isImportant` bool property
variables: {}
variables: {},
// Preserve variables injected via JS with the `variables` option above
// before serializing to CSS (`false` will remove these variables from output)
preserveInjectedVariables: true
};

module.exports = postcss.plugin('postcss-css-variables', function(options) {
Expand All @@ -82,6 +85,10 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
// We use this because we don't want to modify the AST when we still need to reference these later on
var nodesToRemoveAtEnd = [];

// Keep track of the injected from `opts.variables` to remove at the end
// if user passes `opts.preserveInjectedVariables = false`
var injectedDeclsToRemoveAtEnd = [];

// Map of variable names to a list of declarations
var map = {};

Expand All @@ -106,6 +113,11 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
});
variableRootRule.append(varDecl);

// Collect JS-injected variables for removal if `opts.preserveInjectedVariables = false`
if (!opts.preserveInjectedVariables) {
injectedDeclsToRemoveAtEnd.push(varDecl);
}

// Add the entry to the map
prevVariableMap[variableName] = (prevVariableMap[variableName] || []).concat({
decl: varDecl,
Expand Down Expand Up @@ -249,6 +261,11 @@ module.exports = postcss.plugin('postcss-css-variables', function(options) {
// We clean up at the end because we don't want to modify the AST when we still need to reference these later on
nodesToRemoveAtEnd.forEach(cleanUpNode);

// Clean up JS-injected variables marked for removal
injectedDeclsToRemoveAtEnd.forEach(function(injectedDecl) {
injectedDecl.remove();
});


//console.log('map', map);

Expand Down
5 changes: 5 additions & 0 deletions test/fixtures/js-defined-preserve-injected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.box1 {
width: var(--js-defined1);
height: var(--js-defined2);
background: var(--js-defined-no-prefix);
}
8 changes: 8 additions & 0 deletions test/fixtures/js-defined-preserve-injected.expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.box1 {
width: 75px;
width: var(--js-defined1);
height: 80px;
height: var(--js-defined2);
background: #ff0000;
background: var(--js-defined-no-prefix);
}
5 changes: 5 additions & 0 deletions test/fixtures/js-defined-preserve.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.box1 {
width: var(--js-defined1);
height: var(--js-defined2);
background: var(--js-defined-no-prefix);
}
18 changes: 18 additions & 0 deletions test/fixtures/js-defined-preserve.expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
:root {
--js-defined-no-prefix: #ff0000;
}
:root {
--js-defined2: 80px;
}
:root {
--js-defined1: 75px;
}

.box1 {
width: 75px;
width: var(--js-defined1);
height: 80px;
height: var(--js-defined2);
background: #ff0000;
background: var(--js-defined-no-prefix);
}
33 changes: 24 additions & 9 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ var cssvariables = require('../');

var CleanCSS = require('clean-css');

var MOCK_JS_VARIABLES = {
'--js-defined1': '75px',
'--js-defined2': {
value: '80px'
},
// Should be automatically prefixed with `--`
'js-defined-no-prefix': '#ff0000'
};

var testPlugin = function(filePath, expectedFilePath, options) {
options = options || {};
Expand Down Expand Up @@ -146,20 +154,27 @@ describe('postcss-css-variables', function() {
test(
'should work with JS defined variables',
'js-defined',
{ variables: MOCK_JS_VARIABLES }
);
test(
'should preserve -- declarations and var() values with `options.variables` AND `options.preserve`',
'js-defined-preserve',
{
variables: MOCK_JS_VARIABLES,
preserve: true
}
);
test(
'should preserve var() values and clean injected declarations with `options.variables` AND `options.preserve` AND `options.preserveInjectedVariables: false`',
'js-defined-preserve-injected',
{
variables: {
'--js-defined1': '75px',
'--js-defined2': {
value: '80px'
},
// Should be automatically prefixed with `--`
'js-defined-no-prefix': '#ff0000'
}
variables: MOCK_JS_VARIABLES,
preserve: true,
preserveInjectedVariables: false,
}
);
});


describe('with `options.preserve`', function() {
test(
'preserves variables when `preserve` is `true`',
Expand Down