Skip to content

Commit 7d541d7

Browse files
committed
Merge pull request #12 from suitcss/postcss
Switch to PostCSS
2 parents 22e1371 + 3ccbb24 commit 7d541d7

24 files changed

+427
-147
lines changed

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
language: node_js
2+
sudo: false
23
node_js:
3-
- "0.10"
4+
- "0.12"

README.md

Lines changed: 92 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,17 @@
55
[SUIT CSS](https://github.com/suitcss/suit) preprocessor.
66

77
Provides a CLI and Node.js interface for a preprocessor that combines
8-
[rework-suit](https://github.com/suitcss/rework-suit) with
9-
[autoprefixer](https://github.com/ai/autoprefixer).
8+
various [PostCSS](https://github.com/postcss/postcss) plugins.
9+
10+
Compiles CSS packages with:
11+
12+
* [postcss-import](https://github.com/postcss/postcss-import)
13+
* [postcss-custom-properties](https://github.com/postcss/postcss-custom-media)
14+
* [postcss-calc](https://github.com/postcss/postcss-calc)
15+
* [postcss-custom-media](https://github.com/postcss/postcss-custom-media)
16+
* [autoprefixer](https://github.com/postcss/autoprefixer)
17+
18+
In addition each imported file is linted with [postcss-bem-linter](https://github.com/postcss/postcss-bem-linter).
1019

1120
## Installation
1221

@@ -22,49 +31,114 @@ suitcss input.css output.css
2231

2332
## API
2433

25-
#### Command Line
34+
### Command Line
2635

2736
```
2837
Usage: suitcss [<input>] [<output>]
2938
3039
Options:
3140
32-
-c, --compress compress output
33-
-h, --help output usage information
34-
-i, --import-root [path] the root directory for imported css files
35-
-v, --verbose log verbose output for debugging
36-
-V, --version output the version number
37-
-w, --watch watch the input file for changes
41+
-h, --help output usage information
42+
-V, --version output the version number
43+
-m, --minify minify output with cssnano
44+
-i, --import-root [path] the root directory for imported css files
45+
-c, --config [path] a custom PostCSS config file
46+
-v, --verbose log verbose output for debugging
47+
-w, --watch watch the input file and any imports for changes
3848
3949
Examples:
4050
4151
# pass an input and output file:
4252
$ suitcss input.css output.css
4353
54+
# configure the import root directory:
55+
$ suitcss --import-root src/css input.css output.css
56+
4457
# watch the input file for changes:
4558
$ suitcss --watch input.css output.css
4659
60+
# configure postcss plugins with a config file:
61+
$ suitcss --config config.js input.css output.css
62+
4763
# unix-style piping to stdin and stdout:
4864
$ cat input.css | suitcss | grep background-color
4965
```
5066

51-
#### Node.js
67+
### Configuration
68+
69+
Creating a configuration file allows options to be passed to the individual PostCSS plugins. It can be passed to the `suitcss` CLI via the `-c` flag and can be either JavaScript or JSON
70+
71+
```js
72+
module.exports = {
73+
root: 'path/to/css',
74+
autoprefixer: { browsers: ['> 1%', 'IE 7'], cascade: false },
75+
'postcss-calc': { preserve: true }
76+
}
77+
```
78+
79+
```js
80+
{
81+
"root": "path/to/css",
82+
"autoprefixer": { "browsers": ["> 1%", "IE 7"], "cascade": false },
83+
"postcss-calc": { "preserve": true }
84+
}
85+
```
86+
87+
Options are merged recursively with the defaults. For example, adding new plugins to the `use` array will result in them being merged alongside the existing ones.
88+
89+
#### Adding additional plugins
90+
91+
By default the preprocessor uses all necessary plugins to build SUIT components. However additional plugins can be installed into a project and then added to the `use` array.
92+
93+
This **will not** work with the preprocessor installed globally. Instead rely on the convenience of `npm run <script>`
94+
95+
```js
96+
module.exports = {
97+
use: [
98+
'postcss-property-lookup'
99+
]
100+
};
101+
```
102+
103+
```js
104+
{
105+
"name": "my-pkg",
106+
"version": "0.1.0",
107+
"dependencies": {
108+
"postcss-property-lookup": "^1.1.3",
109+
"suitcss-preprocessor": "^0.5.0"
110+
},
111+
"scripts": {
112+
"preprocess": "suitcss -c myconfig.js index.css build/built.css"
113+
}
114+
}
115+
```
116+
117+
```
118+
npm run preprocess
119+
```
120+
121+
### Node.js
122+
123+
Returns a [PostCSS promise](https://github.com/postcss/postcss/blob/master/docs/api.md#lazyresult-class)
52124

53125
```js
54126
var preprocessor = require('suitcss-preprocessor');
55127
var fs = require('fs');
56128

57129
var css = fs.readFileSync('src/components/index.css', 'utf8');
58130

59-
var bundle = preprocessor(css, {
60-
alias: {
61-
'components': 'src/components'
62-
},
63-
source: 'src/components/index.css',
64-
sourcemap: true
131+
preprocessor(css, {
132+
root: 'path/to/css',
133+
minify: true,
134+
config: {
135+
use: ['postcss-property-lookup'],
136+
autoprefixer: { browsers: ['> 1%', 'IE 7'], cascade: false },
137+
'postcss-calc': { preserve: true }
138+
}
139+
}).then(function(result) {
140+
fs.writeFileSync('build/bundle.css', result.css);
65141
});
66-
67-
fs.writeFileSync('build/bundle.css', bundle);
68142
```
69143

70144
## Acknowledgements

bin/suitcss

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
#!/usr/bin/env node
22

3-
var fs = require('fs');
3+
var fs = require('fs-extra');
44
var exists = fs.existsSync;
55
var logger = require('./logger');
66
var suitcss = require('..');
77
var path = require('path');
88
var resolve = path.resolve;
99
var program = require('commander');
1010
var read = require('read-file-stdin');
11-
var watch = require('node-watch');
12-
var write = require('write-file-stdout');
11+
var chokidar = require('chokidar');
12+
var writeFileSync = fs.outputFileSync;
1313

1414
/**
1515
* Usage.
@@ -18,10 +18,11 @@ var write = require('write-file-stdout');
1818
program
1919
.version(require('../package.json').version)
2020
.usage('[<input>] [<output>]')
21-
.option('-c, --compress', 'compress output')
21+
.option('-m, --minify', 'minify output with cssnano')
2222
.option('-i, --import-root [path]', 'the root directory for imported css files', '')
23+
.option('-c, --config [path]', 'a custom PostCSS config file', '')
2324
.option('-v, --verbose', 'log verbose output for debugging')
24-
.option('-w, --watch', 'watch the input file for changes');
25+
.option('-w, --watch', 'watch the input file and any imports for changes');
2526

2627
/**
2728
* Examples.
@@ -39,6 +40,9 @@ program.on('--help', function () {
3940
console.log(' # watch the input file for changes:');
4041
console.log(' $ suitcss --watch input.css output.css');
4142
console.log();
43+
console.log(' # configure postcss plugins with a config file:');
44+
console.log(' $ suitcss --config config.js input.css output.css');
45+
console.log();
4246
console.log(' # unix-style piping to stdin and stdout:');
4347
console.log(' $ cat input.css | suitcss | grep background-color');
4448
console.log();
@@ -56,7 +60,7 @@ program.parse(process.argv);
5660

5761
var input = program.args[0] ? resolve(program.args[0]) : null;
5862
var output = program.args[1] ? resolve(program.args[1]) : null;
59-
var importRoot = program.importRoot;
63+
var config = program.config ? require(resolve(program.config)) : null;
6064
var verbose = program.verbose;
6165
var regen = program.watch && input && output;
6266

@@ -73,12 +77,25 @@ if (input && !exists(input)) logger.fatal('not found', input);
7377
run();
7478

7579
/**
76-
* Watch?
80+
* Watch
7781
*/
7882

83+
var currentWatchedFiles;
7984
if (regen) {
80-
watch(input, run);
81-
if (verbose) logger.log('watch', input);
85+
var watcher = chokidar.watch(input);
86+
watcher.on('change', run);
87+
watcher.on('change', function(file) {
88+
if (verbose) logger.log(path.basename(file) + ' changed');
89+
});
90+
watcher.on('ready', function() {
91+
if (verbose) logger.log('Watching ' + path.basename(input));
92+
});
93+
94+
global.watchCSS = function(imported) {
95+
watcher.unwatch(currentWatchedFiles);
96+
watcher.add(imported);
97+
currentWatchedFiles = imported;
98+
};
8299
}
83100

84101
/**
@@ -90,14 +107,19 @@ function run () {
90107
if (err) logger.throw(err);
91108
var css = buffer.toString();
92109

93-
try {
94-
css = suitcss(css, { compress: program.compress, dir: importRoot, source: input });
95-
} catch (e) {
96-
e.css = css;
97-
logger.throw(e);
98-
}
99-
100-
write(output, css + '\n');
110+
suitcss(css, {
111+
minify: program.minify,
112+
root: program.importRoot,
113+
config: config
114+
}).then(function(result) {
115+
if (output) {
116+
writeFileSync(output, result.css + '\n');
117+
} else {
118+
console.log(result.css);
119+
}
101120
if (verbose && output) logger.log('write', output);
121+
}).catch(function(e) {
122+
logger.throw(e);
123+
});
102124
});
103125
}

lib/index.js

Lines changed: 83 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,60 @@
11
/**
22
* Module dependencies
33
*/
4-
4+
var assign = require('object-assign-deep');
5+
var without = require('lodash/array/without');
6+
var last = require('lodash/array/last');
57
var autoprefixer = require('autoprefixer');
6-
var rework = require('rework');
7-
var suit = require('rework-suit');
8+
var bemLinter = require('postcss-bem-linter');
9+
var postcss = require('postcss');
10+
var cssnano = require('cssnano');
11+
var reporter = require('postcss-reporter');
812

913
/**
1014
* Module export
1115
*/
1216

1317
module.exports = preprocessor;
1418

19+
var defaults = {
20+
minify: undefined,
21+
use: [
22+
'postcss-import',
23+
'postcss-custom-properties',
24+
'postcss-calc',
25+
'postcss-custom-media',
26+
'autoprefixer',
27+
'postcss-reporter'
28+
],
29+
'postcss-import': {
30+
transform: function (css, filename) {
31+
return postcss([bemLinter, reporter]).process(css, {from: filename}).css;
32+
},
33+
root: undefined,
34+
onImport: function(imported) {
35+
// Update the watch task with the list of imported files
36+
if (typeof global.watchCSS === 'function') {
37+
global.watchCSS(imported);
38+
}
39+
}
40+
},
41+
'postcss-reporter': {
42+
clearMessages: true
43+
},
44+
// http://cssnano.co/optimisations/
45+
cssnano: {
46+
calc: false,
47+
autoprefixer: false,
48+
mergeRules: false,
49+
// Disable unsafe optimisations
50+
zindex: false,
51+
discardUnused: false,
52+
reduceIdents: false,
53+
mergeIdents: false
54+
}
55+
};
56+
57+
1558
/**
1659
* Process CSS
1760
*
@@ -24,21 +67,46 @@ function preprocessor(css, options) {
2467
throw new Error('suitcss-preprocessor: did not receive a String');
2568
}
2669

70+
options = mergeOptions(options);
71+
72+
var plugins = options.use.map(function (p) {
73+
var plugin = require(p);
74+
settings = options[p];
75+
76+
return settings ? plugin(settings) : plugin;
77+
});
78+
79+
var processor = postcss(plugins);
80+
81+
if (options.minify) {
82+
processor.use(cssnano(options.cssnano));
83+
}
84+
85+
return processor.process(css);
86+
}
87+
88+
89+
/**
90+
* Merge options with defaults and set root
91+
*
92+
* @param {Object} options
93+
*/
94+
95+
function mergeOptions(options) {
2796
options = options || {};
97+
options.config = options.config || {};
2898

29-
var browserConfig = options.browsers || [
30-
'Explorer >= 9',
31-
'last 2 Chrome versions',
32-
'last 2 Firefox versions',
33-
'last 2 Safari versions',
34-
'last 2 iOS versions',
35-
'Android 4'
36-
];
99+
var merged = assign({}, defaults, options.config);
37100

38-
css = rework(css, options).use(suit(options)).toString(options);
101+
merged.minify = options.minify;
102+
merged['postcss-import'].root = options.root;
39103

40-
// vendor prefixes
41-
css = autoprefixer(browserConfig).process(css).css;
104+
// Ensure postcss-reporter is always the final plugin
105+
if (last(merged.use) !== 'postcss-reporter') {
106+
var plugins = without(merged.use, 'postcss-reporter');
107+
plugins.push('postcss-reporter');
108+
merged.use = plugins;
109+
}
42110

43-
return css;
111+
return merged;
44112
}

0 commit comments

Comments
 (0)