Skip to content

remove webpack option #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 5, 2017
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
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ coverage
.nyc_output
.travis.yml
yarn.lock
wallaby.js
17 changes: 6 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,32 +44,27 @@ By default, the css standard plugin pack includes:
Any of these plugins can be customized by passing the [options](#options) described below. You can also add additional postCSS plugins (like the popular [`lost`](https://github.com/peterramsing/lost) grid, for example) on top of this package:

```js
// app.js
const cssStandards = require('spike-css-standards')
const lost = require('lost')

// ...
postcss: (ctx) => {
const css = cssStandards({ webpack: ctx })
css.plugins.push(lost())
return css
},
// ...
const css = cssStandards()
css.plugins.push(lost())
```

### Options

| Name | Description | Default |
| ---- | ----------- | ------- |
| **root** | Root used to resolve `path`(s) from | If `webpack` option is provided, `options.context` |
| **path** | A path to a folder or an array of paths, telling postcss-import where to look for sss or css files to `@import`. | If `webpack` option is provided, `loaderContext.resourcePath` |
| **webpack** | Shortcut for webpack users to set the `root` and `path` options more easily. Pass webpack loader context. | |
| **root** | Root used to resolve `path`(s) from | |
| **path** | A path to a folder or an array of paths, telling postcss-import where to look for sss or css files to `@import`. | |
| **browsers** | Browser support provided to [autoprefixer](http://cssnext.io/usage/#browsers) | `> 1%, last 2 versions, Firefox ESR` |
| **features** | Enable or disable [cssnext features](http://cssnext.io/usage/#features) | |
| **warnForDuplicates** | Enable or disable [cssnext duplicate warnings](http://cssnext.io/usage/#warnforduplicates) | `true` |
| **rucksack** | Options passed directly to [rucksack](http://simplaio.github.io/rucksack/docs/#options) | |
| **parser** | custom css parser if desired. pass `false` to use the default css parser | `sugarss` |
| **minify** | Minifies the css output by removing excess spaces and line breaks | `false` |
| **appendPlugins** | Adds a single plugin or array of plugins after all the defaults | |
| **prependPlugins** | Adds a single plugin or array of plugins before all the defaults | |

### License & Contributing

Expand Down
45 changes: 35 additions & 10 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,61 @@ let postcssImport = require('postcss-import')
let cssnext = require('postcss-cssnext')
let rucksack = require('rucksack-css')

/**
* Primary export, formats options and returns an object with intelligent
* defaults.
* @param {Object} [options={}] - options object
* @param {Function} [options.parser=sugarss] - if false, is set to undefined
* @param {Array|String} options.path - passed to import plugin
* @param {String} options.root - passed to import plugin
* @param {Array} options.browsers - passed to cssnext plugin
* @param {Object} options.features - passed to cssnext plugin
* @param {Boolean} options.warnForDuplicates - passed to cssnext plugin
* @param {Object} options.rucksack - passed to rucksack plugin
* @param {Boolean} options.minify - whether or not to add the minify plugin
* @return {Object} valid postcss options object
*/
module.exports = (options = {}) => {
// sugarss by default unless false or custom parser
let parser = options.parser || sugarss
if (options.parser === false) parser = undefined
options.path = options.path ? Array.prototype.concat(options.path) : []

// define root/path defaults if the webpack object is provided
if (options.webpack) {
options.root = options.webpack.options.context
options.path.push(options.webpack.resourcePath)
}

// standard options merge
const importOpt = selectiveMerge(options, ['root', 'path'])
const cssnextOpt = selectiveMerge(options, ['browsers', 'features', 'warnForDuplicates'])
const importOpt = selectKeys(options, ['root', 'path'])
const cssnextOpt = selectKeys(options, ['browsers', 'features', 'warnForDuplicates'])

// define normal plugin list
// define default plugin list
const plugins = [
postcssImport(importOpt),
cssnext(cssnextOpt),
rucksack(options.rucksack)
]

// append and prepend plugins if needed
if (options.appendPlugins) {
plugins.push(...Array.prototype.concat(options.appendPlugins))
}

if (options.prependPlugins) {
plugins.unshift(...Array.prototype.concat(options.prependPlugins))
}

// add cssnano if minify config present
if (options.minify) plugins.push(require('cssnano')())

return {parser, plugins}
}

function selectiveMerge (opts, optNames) {
/**
* Given an options object and an array of key names, return an object filtered
* to contain only the keys in the optNames array, if they exist on the options
* object.
* @param {Object} opts - full options object
* @param {Array} optNames - keys to filter
* @return {Object} object filtered for the specific keys
*/
function selectKeys (opts, optNames) {
return optNames.reduce((m, opt) => {
if (typeof opts[opt] !== 'undefined') { m[opt] = opts[opt] }; return m
}, {})
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "spike-css-standards",
"description": "standard plugin pack for postcss",
"version": "0.2.0",
"version": "0.3.0-1",
"author": "Jeff Escalante",
"ava": {
"verbose": "true"
Expand Down
85 changes: 54 additions & 31 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,67 @@
const rewire = require('rewire')
const cssStandardsRewired = rewire('..')
const cssStandards = require('..')
const cssStandardsRewired = rewire('../lib')
const cssStandards = require('../lib')
const test = require('ava')

test('basic', (t) => {
cssStandardsRewired.__set__('postcssImport', (opts) => {
t.truthy(opts.root === 'test')
t.truthy(opts.path[0] === 'test/test1')
t.truthy(opts.path[1] === 'test/test2')
t.truthy(opts.path[2] === 'test') // webpack.resourcePath
})
test('passes parser opt correctly', (t) => {
const out = cssStandards({ parser: 'test' })
const out2 = cssStandards({ parser: false })
t.is(out.parser, 'test')
t.is(out2.parser, undefined)
})

cssStandardsRewired.__set__('cssnext', (opts) => {
t.truthy(opts.features === 'test')
t.truthy(opts.browsers === 'test')
t.truthy(opts.warnForDuplicates === 'test')
test('passes import opts correctly', (t) => {
const undo = cssStandardsRewired.__set__('postcssImport', (opts) => {
t.is(opts.root, 'test')
t.is(opts.path[0], 'test')
})
cssStandardsRewired({ root: 'test', path: 'test' })
undo()
})

cssStandardsRewired.__set__('rucksack', (opts) => {
t.truthy(opts === 'test')
test('passes cssnext opts correctly', (t) => {
const undo = cssStandardsRewired.__set__('cssnext', (opts) => {
t.is(opts.browsers, 'test')
t.is(opts.features, 'test')
t.is(opts.warnForDuplicates, 'test')
})

const out1 = cssStandardsRewired({
parser: false,
webpack: {
resourcePath: 'test',
options: { context: 'test' }
},
path: ['test/test1', 'test/test2'],
features: 'test',
cssStandardsRewired({
browsers: 'test',
warnForDuplicates: 'test',
rucksack: 'test'
features: 'test',
warnForDuplicates: 'test'
})
undo()
})

test('passes rucksack opts correctly', (t) => {
const undo = cssStandardsRewired.__set__('rucksack', (opts) => {
t.is(opts, 'test')
})
cssStandardsRewired({ rucksack: 'test' })
undo()
})

t.truthy(out1.plugins.length === 3)
t.falsy(out1.parser)
test('default plugins working', (t) => {
const out = cssStandards()
t.is(out.plugins.length, 3)
})

const out2 = cssStandards({ minify: true })
test('minify option working', (t) => {
const out = cssStandards({ minify: true })
t.is(out.plugins.length, 4)
t.is(out.plugins[out.plugins.length - 1].postcssPlugin, 'cssnano')
})

test('appendPlugins option', (t) => {
const out = cssStandards({ appendPlugins: ['test'] })
const out2 = cssStandards({ appendPlugins: 'test' })
t.truthy(out.plugins[out.plugins.length - 1] === 'test')
t.truthy(out2.plugins[out.plugins.length - 1] === 'test')
})

t.truthy(out2.parser)
t.truthy(out2.plugins.length === 4)
test('prependPlugins option', (t) => {
const out = cssStandards({ prependPlugins: ['test'] })
const out2 = cssStandards({ prependPlugins: 'test' })
t.truthy(out.plugins[0] === 'test')
t.truthy(out2.plugins[0] === 'test')
})
Loading