Skip to content

Commit 3905396

Browse files
authored
Merge pull request postcss#109 from michael-ciniawsky/fixes
Better Error handling
2 parents d12a122 + b180d76 commit 3905396

File tree

4 files changed

+60
-47
lines changed

4 files changed

+60
-47
lines changed

README.md

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,18 @@ cat input.css | postcss [OPTIONS] > output.css
4040
|Name|Type|Default|Description|
4141
|:---|:--:|:-----:|:----------|
4242
|`-d, --dir`|`{String}`|`undefined`|Output Directory|
43+
|`-x, --ext`|`{String}`|`extname(output)`|Output File Extension|
4344
|`-o, --output`|`{String}`|`undefined`|Output File|
44-
|`-r, --replace`|`{String}`|`undefined`|Input <=> Output|
45-
|`-x, --extension`|`{String}`|`extname(output)`|Output File Extension|
45+
|`-r, --replace`|`{String}`|`undefined`|Replace Input <=> Output|
4646
|`-p, --parser`|`{String}`|`undefined`|Custom PostCSS Parser|
4747
|`-s, --syntax`|`{String}`|`undefined`|Custom PostCSS Syntax|
4848
|`-s, --stringifier`|`{String}`|`undefined`|Custom PostCSS Stringifier|
49-
|`-w, --watch`|`{Boolean}`|`false`|Watch files for changes and recompile as needed
50-
|`-u, --use`|`{Array}`|`[]`|List of PostCSS Plugins|
51-
|`-m, --map`|`{Boolean}`|`{ inline: true }`|External Sourcemap|
49+
|`-w, --watch`|`{Boolean}`|`false`|Enable Watch Mode|
50+
|`-u, --use`|`{Array}`|`[]`|PostCSS Plugins|
51+
|`-m, --map`|`{Boolean}`|`{ inline: true }`|External Sourcemaps|
5252
|`--no-map`|`{Boolean}`|`false`|Disable Sourcemaps|
53-
|`-e, --env`|`{String}`|`process.env.NODE_ENV`|Shortcut for setting `$NODE_ENV`|
54-
|`-c, --config`|`{String}`|`dirname(file)`|Path to `postcss.config.js`|
53+
|`-e, --env`|`{String}`|`process.env.NODE_ENV`|Sets `$NODE_ENV`|
54+
|`-c, --config`|`{String}`|`dirname(file)`|PostCSS Config Path `postcss.config.js`|
5555
|`-h, --help`|`{Boolean}`|`false`|CLI Help|
5656
|`-v, --version`|`{Boolean}`|`false`|CLI Version|
5757

@@ -63,7 +63,6 @@ cat input.css | postcss [OPTIONS] > output.css
6363
If you need to pass options to your plugins, or have a long plugin chain, you'll want to use a configuration file.
6464

6565
**postcss.config.js**
66-
6766
```js
6867
module.exports = {
6968
parser: 'sugarss',
@@ -85,7 +84,6 @@ For more advanced usage it's recommend to to use a function in `postcss.config.j
8584
|`options`|`{Object}`|`map, parser, syntax, stringifier`|PostCSS Options|
8685

8786
**postcss.config.js**
88-
8987
```js
9088
module.exports = (ctx) => ({
9189
map: ctx.options.map,
@@ -105,7 +103,6 @@ postcss input.sss -p sugarss -o output.css -m
105103
```
106104

107105
**postcss.config.js**
108-
109106
```js
110107
module.exports = (ctx) => ({
111108
map: ctx.options.map,

index.js

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
const fs = require('fs-promise')
44
const path = require('path')
55

6+
const ora = require('ora')
67
const stdin = require('get-stdin')
78
const chalk = require('chalk')
8-
const ora = require('ora')
99
const globber = require('globby')
1010
const chokidar = require('chokidar')
1111

@@ -134,6 +134,8 @@ let output = argv.output
134134

135135
if (argv.map) argv.map = { inline: false }
136136

137+
const spinner = ora()
138+
137139
let config = {
138140
options: {
139141
map: argv.map !== undefined ? argv.map : { inline: true },
@@ -146,7 +148,7 @@ let config = {
146148
try {
147149
return require(plugin)()
148150
} catch (e) {
149-
error(`PluginError: Cannot find module '${plugin}'`)
151+
error(`Plugin Error: Cannot find module '${plugin}'`)
150152
}
151153
})
152154
: []
@@ -159,23 +161,21 @@ Promise.resolve()
159161
.then(() => {
160162
if (input && input.length) return globber(input)
161163

162-
console.warn(chalk.bold.yellow('Warning: No files passed, reading from stdin\n'))
163-
164-
if (argv.replace || argv.dir) error('Cannot use --dir or --replace when reading from stdin')
164+
if (argv.replace || argv.dir) error('Input Error: Cannot use --dir or --replace when reading from stdin')
165165

166166
if (argv.watch) {
167-
error('Cannot run in watch mode when reading from stdin')
167+
error('Input Error: Cannot run in watch mode when reading from stdin')
168168
}
169169

170170
return ['stdin']
171171
})
172172
.then((i) => {
173173
if (!i || !i.length) {
174-
error('You must pass a valid list of files to parse')
174+
error('Input Error: You must pass a valid list of files to parse')
175175
}
176176

177177
if (i.length > 1 && !argv.dir && !argv.replace) {
178-
error('Must use --dir or --replace with multiple input files')
178+
error('Input Error: Must use --dir or --replace with multiple input files')
179179
}
180180

181181
input = i
@@ -227,8 +227,8 @@ function files (files) {
227227
if (file === 'stdin') {
228228
return stdin()
229229
.then((content) => {
230-
if (!content) return error('Error: Did not receive any stdin')
231-
css(content, 'stdin')
230+
if (!content) return error('Input Error: Did not receive any STDIN')
231+
return css(content, 'stdin')
232232
})
233233
}
234234

@@ -254,7 +254,8 @@ function css (css, file) {
254254

255255
const time = process.hrtime()
256256

257-
const spinner = ora(`Processing ${file}`).start()
257+
spinner.text = `Processing ${file}`
258+
spinner.start()
258259

259260
return rc(ctx, argv.config)
260261
.then(() => {
@@ -276,10 +277,9 @@ function css (css, file) {
276277
options.to = path.resolve(options.to)
277278
}
278279

279-
// Can't use external sourcemaps when writing to stdout:
280280
if (!options.to && config.options.map && !config.options.map.inline) {
281281
spinner.fail()
282-
error('Cannot output external sourcemaps when writing to stdout')
282+
error('Output Error: Cannot output external sourcemaps when writing to STDOUT')
283283
}
284284

285285
return postcss(config.plugins)
@@ -302,7 +302,13 @@ function css (css, file) {
302302
)
303303
)
304304
}
305-
} else process.stdout.write(result.css, 'utf8')
305+
} else {
306+
spinner.text = chalk.bold.green(
307+
`Finished ${file} (${Math.round(process.hrtime(time)[1] / 1e6)}ms)`
308+
)
309+
spinner.succeed()
310+
return process.stdout.write(result.css, 'utf8')
311+
}
306312

307313
return Promise.all(tasks)
308314
.then(() => {
@@ -317,8 +323,7 @@ function css (css, file) {
317323
return result
318324
})
319325
})
320-
}).catch(err => {
321-
// Fail spinner and send error up the promise chain
326+
}).catch((err) => {
322327
spinner.fail()
323328
throw err
324329
})
@@ -342,21 +347,26 @@ function dependencies (results) {
342347

343348
function error (err) {
344349
if (typeof err === 'string') {
345-
// Manual error
346-
console.error(chalk.bold.red(err))
350+
spinner.fail(chalk.bold.red(err))
347351
} else if (err.name === 'CssSyntaxError') {
348-
// CSS Syntax Error
349-
console.error(chalk.bold.red(`${err.file}`))
350-
err.message = err.message
351-
.substr(err.file.length + 1)
352-
.replace(/:\s/, '] ')
352+
console.error('\n')
353+
354+
spinner.text = spinner.text.replace('Processing ', '')
355+
spinner.fail(chalk.bold.red(`Syntax Error: ${spinner.text}`))
356+
357+
if (err.file) {
358+
err.message = err.message.substr(err.file.length + 1)
359+
} else {
360+
err.message = err.message.replace('<css input>:', '')
361+
}
362+
363+
err.message = err.message.replace(/:\s/, '] ')
364+
353365
console.error('\n', chalk.bold.red(`[${err.message}`))
354-
console.error('\n', err.showSourceCode(), '\n')
355-
// If watch mode, don't exit the process:
366+
console.error('\n', err.showSourceCode(), '\n\n')
367+
356368
if (argv.watch) return
357369
} else {
358-
// JS Error
359-
// Don't use chalk here; we want a JS stack trace:
360370
console.error(err)
361371
}
362372
process.exit(1)

package.json

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
"version": "3.0.0-beta",
44
"description": "CLI for PostCSS",
55
"main": "index.js",
6-
"engines": { "node": ">=4" },
6+
"engines": {
7+
"node": ">=4"
8+
},
79
"bin": {
810
"postcss": "./bin/postcss"
911
},
@@ -20,20 +22,24 @@
2022
"get-stdin": "^5.0.1",
2123
"globby": "^6.1.0",
2224
"ora": "^1.1.0",
23-
"postcss": "^5.2.11",
25+
"postcss": "^5.2.16",
2426
"postcss-load-config": "^1.1.0",
2527
"postcss-reporter": "^3.0.0",
26-
"yargs": "^6.6.0"
28+
"yargs": "^7.0.2"
2729
},
2830
"devDependencies": {
29-
"ava": "^0.18.1",
30-
"coveralls": "^2.11.15",
31+
"ava": "^0.18.2",
32+
"coveralls": "^2.12.0",
3133
"nyc": "^10.1.2",
3234
"postcss-import": "^9.1.0",
33-
"standard": "^8.6.0",
35+
"standard": "^9.0.1",
3436
"sugarss": "^0.2.0",
3537
"uuid": "^3.0.1"
3638
},
39+
"files": [
40+
"bin",
41+
"index.js"
42+
],
3743
"keywords": [
3844
"cli",
3945
"postcss",

test/error.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,23 @@ test('multiple input files && --output', (t) => {
1212
)
1313
.then(({ err, code }) => {
1414
t.is(code, 1, 'expected non-zero error code')
15-
t.regex(err, /Must use --dir or --replace/)
15+
t.regex(err, /Input Error: Must use --dir or --replace/)
1616
})
1717
})
1818

1919
test('multiple input files && writing to stdout', (t) => {
2020
return cli(['test/fixtures/*.css'])
2121
.then(({ err, code }) => {
2222
t.is(code, 1, 'expected non-zero error code')
23-
t.regex(err, /Must use --dir or --replace/)
23+
t.regex(err, /Input Error: Must use --dir or --replace/)
2424
})
2525
})
2626

2727
test('--map && writing to stdout', (t) => {
2828
return cli(['test/fixtures/a.css', '--map'])
2929
.then(({ err, code }) => {
3030
t.is(code, 1, 'expected non-zero error code')
31-
t.regex(err, /Cannot output external sourcemaps when writing to stdout/)
31+
t.regex(err, /Output Error: Cannot output external sourcemaps when writing to STDOUT/)
3232
})
3333
})
3434

@@ -56,7 +56,7 @@ test('PluginError', (t) => {
5656
)
5757
.then(({ err, code }) => {
5858
t.is(code, 1, 'expected non-zero error code')
59-
t.regex(err, /PluginError: Cannot find module 'postcss-plugin'/)
59+
t.regex(err, /Plugin Error: Cannot find module 'postcss-plugin'/)
6060
})
6161
})
6262

0 commit comments

Comments
 (0)