Skip to content

Commit

Permalink
Add option to specify default plugin options (closes #11) (#21)
Browse files Browse the repository at this point in the history
* Add option to specify default plugin options (closes #11)

* Fix Object.assign in Node <= 0.12

* Rename `defaultPluginOptions` to the less verbose `options`

* Use object spread over assign polyfill
  • Loading branch information
rexxars authored and ben-eb committed Aug 27, 2016
1 parent 74d8f52 commit d639f61
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 4 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,25 @@ plugin, for instance.
postcss([ use({ resolveFromFile: true, modules: '*' }) ]);
```

##### options

Type: `object` (default: `{}`)

Default options for plugins, keyed by plugin name. If both the default and the specified options are objects, they are merged. Otherwise, the options specified in the CSS are used.

```js
postcss([
use({
modules: '*',
options: {
autoprefixer: {
browsers: ['> 1%', 'IE 7']
}
}
})
]);
```

## Usage

See the [PostCSS documentation](https://github.com/postcss/postcss#usage) for
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"repository": "postcss/postcss-use",
"dependencies": {
"balanced-match": "^0.4.1",
"lodash.isplainobject": "^4.0.6",
"postcss": "^5.0.21",
"resolve-from": "^2.0.0"
},
Expand Down
10 changes: 10 additions & 0 deletions src/__tests__/fixtures/arrayOptions.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@use postcss-nobg(["background-repeat"]);

.foo {
background-image: url(/foo.jpg);
}

.bar {
background: #bf1942;
background-repeat: no-repeat;
}
21 changes: 18 additions & 3 deletions src/__tests__/fixtures/node_modules/postcss-nobg/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions src/__tests__/fixtures/options.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@use postcss-nobg(onlyImages: false);

.foo {
background-image: url(/foo.jpg);
}

.bar {
background: #bf1942;
}
49 changes: 49 additions & 0 deletions src/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,52 @@ test('should not resolve plugins relative to CSS file by default', t => {
t.deepEqual(err.message, `Cannot find module 'postcss-nobg'`);
});
});

test('should be able to specify default options for plugins', t => {
const inputFile = path.join(__dirname, 'fixtures', 'test.css');
const outputFile = path.join(__dirname, 'fixtures', 'test.out.css');
const inputCss = fs.readFileSync(inputFile);
const options = {
nobg: {onlyImages: true},
};
return postcss(plugin({modules: '*', resolveFromFile: true, options})).process(inputCss, {
from: inputFile,
to: outputFile,
}).then(({css}) => {
const normalized = css.replace(/\s+/g, ' ').trim();
t.deepEqual(normalized, '.foo {background: blue;color: red;}', 'should remove only background image decls');
});
});

test('should be able to override default options', t => {
const inputFile = path.join(__dirname, 'fixtures', 'options.css');
const outputFile = path.join(__dirname, 'fixtures', 'options.out.css');
const inputCss = fs.readFileSync(inputFile);
const options = {
nobg: {onlyImages: true},
};
return postcss(plugin({modules: '*', resolveFromFile: true, options})).process(inputCss, {
from: inputFile,
to: outputFile,
}).then(({css}) => {
const normalized = css.replace(/\s+/g, ' ').trim();
t.deepEqual(normalized, '.foo { } .bar { }', 'should remove only background image decls');
});
});

test('should use specified options if specified options is not an object', t => {
const inputFile = path.join(__dirname, 'fixtures', 'arrayOptions.css');
const outputFile = path.join(__dirname, 'fixtures', 'arrayOptions.out.css');
const inputCss = fs.readFileSync(inputFile);
const options = {
nobg: {onlyImages: true},
};
return postcss(plugin({modules: '*', resolveFromFile: true, options})).process(inputCss, {
from: inputFile,
to: outputFile,
}).then(({css}) => {
const normalized = css.replace(/\s+/g, ' ').trim();
const expected = '.foo { background-image: url(/foo.jpg); } .bar { background: #bf1942; }';
t.deepEqual(normalized, expected, 'should remove only background-repeat decls');
});
});
16 changes: 15 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import path from 'path';
import postcss from 'postcss';
import balanced from 'balanced-match';
import resolveFrom from 'resolve-from';
import isPlainObject from 'lodash.isplainobject';

const NAME = 'postcss-use';

Expand Down Expand Up @@ -31,6 +32,16 @@ function pluginOptsFromRule (rule) {
return options;
}

function mergePluginOptions (plugin, defaultOpts, specifiedOpts) {
// Don't merge anything but objects
if (!isPlainObject(specifiedOpts) || !isPlainObject(defaultOpts)) {
return specifiedOpts;
}

// If both the default and specified options are plain objects, we can merge them
return {...defaultOpts, ...specifiedOpts};
}

export default postcss.plugin(NAME, (opts = {}) => {
return (css, result) => {
if (!opts.modules) {
Expand Down Expand Up @@ -88,7 +99,10 @@ export default postcss.plugin(NAME, (opts = {}) => {
throw new Error(`Cannot find module '${plugin}'`);
}

let instance = require(pluginPath)(pluginOpts);
let optsName = plugin.replace(/^postcss-/, '');
let defaultOpts = (opts.options && opts.options[optsName]) || {};
let mergedOptions = mergePluginOptions(optsName, defaultOpts, pluginOpts);
let instance = require(pluginPath)(mergedOptions);
if (instance.plugins) {
instance.plugins.forEach((p) => {
result.processor.plugins.push(p);
Expand Down

0 comments on commit d639f61

Please sign in to comment.