chushihua
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Geoffroy Warin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
# Friendly-errors-webpack-plugin
|
||||
|
||||
[](https://www.npmjs.com/package/friendly-errors-webpack-plugin)
|
||||
[](https://travis-ci.org/geowarin/friendly-errors-webpack-plugin)
|
||||
[](https://ci.appveyor.com/project/geowarin/friendly-errors-webpack-plugin/branch/master)
|
||||
|
||||
Friendly-errors-webpack-plugin recognizes certain classes of webpack
|
||||
errors and cleans, aggregates and prioritizes them to provide a better
|
||||
Developer Experience.
|
||||
|
||||
It is easy to add types of errors so if you would like to see more
|
||||
errors get handled, please open a [PR](https://help.github.com/articles/creating-a-pull-request/)!
|
||||
|
||||
## Getting started
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
npm install friendly-errors-webpack-plugin --save-dev
|
||||
```
|
||||
|
||||
### Basic usage
|
||||
|
||||
Simply add `FriendlyErrorsWebpackPlugin` to the plugin section in your Webpack config.
|
||||
|
||||
```javascript
|
||||
var FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
|
||||
|
||||
var webpackConfig = {
|
||||
// ...
|
||||
plugins: [
|
||||
new FriendlyErrorsWebpackPlugin(),
|
||||
],
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Turn off errors
|
||||
|
||||
You need to turn off all error logging by setting your webpack config quiet option to true.
|
||||
|
||||
```javascript
|
||||
app.use(require('webpack-dev-middleware')(compiler, {
|
||||
quiet: true,
|
||||
publicPath: config.output.publicPath,
|
||||
}));
|
||||
```
|
||||
|
||||
If you use the webpack-dev-server, there is a setting in webpack's ```devServer``` options:
|
||||
|
||||
```javascript
|
||||
// webpack config root
|
||||
{
|
||||
// ...
|
||||
devServer: {
|
||||
// ...
|
||||
quiet: true,
|
||||
// ...
|
||||
},
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
If you use webpack-hot-middleware, that is done by setting the log option to `false`. You can do something sort of like this, depending upon your setup:
|
||||
|
||||
```javascript
|
||||
app.use(require('webpack-hot-middleware')(compiler, {
|
||||
log: false
|
||||
}));
|
||||
```
|
||||
|
||||
_Thanks to [webpack-dashboard](https://github.com/FormidableLabs/webpack-dashboard) for this piece of info._
|
||||
|
||||
## Demo
|
||||
|
||||
### Build success
|
||||
|
||||

|
||||
|
||||
### eslint-loader errors
|
||||
|
||||

|
||||
|
||||
### babel-loader syntax errors
|
||||
|
||||

|
||||
|
||||
### Module not found
|
||||
|
||||

|
||||
|
||||
## Options
|
||||
|
||||
You can pass options to the plugin:
|
||||
|
||||
```js
|
||||
new FriendlyErrorsPlugin({
|
||||
compilationSuccessInfo: {
|
||||
messages: ['You application is running here http://localhost:3000'],
|
||||
notes: ['Some additionnal notes to be displayed unpon successful compilation']
|
||||
},
|
||||
onErrors: function (severity, errors) {
|
||||
// You can listen to errors transformed and prioritized by the plugin
|
||||
// severity can be 'error' or 'warning'
|
||||
},
|
||||
// should the console be cleared between each compilation?
|
||||
// default is true
|
||||
clearConsole: true,
|
||||
|
||||
// add formatters and transformers (see below)
|
||||
additionalFormatters: [],
|
||||
additionalTransformers: []
|
||||
})
|
||||
```
|
||||
|
||||
## Adding desktop notifications
|
||||
|
||||
The plugin has no native support for desktop notifications but it is easy
|
||||
to add them thanks to [node-notifier](https://www.npmjs.com/package/node-notifier) for instance.
|
||||
|
||||
```js
|
||||
var NotifierPlugin = require('friendly-errors-webpack-plugin');
|
||||
var notifier = require('node-notifier');
|
||||
var ICON = path.join(__dirname, 'icon.png');
|
||||
|
||||
new NotifierPlugin({
|
||||
onErrors: (severity, errors) => {
|
||||
if (severity !== 'error') {
|
||||
return;
|
||||
}
|
||||
const error = errors[0];
|
||||
notifier.notify({
|
||||
title: "Webpack error",
|
||||
message: severity + ': ' + error.name,
|
||||
subtitle: error.file || '',
|
||||
icon: ICON
|
||||
});
|
||||
}
|
||||
})
|
||||
]
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Transformers and formatters
|
||||
|
||||
Webpack's errors processing, is done in four phases:
|
||||
|
||||
1. Extract relevant info from webpack errors. This is done by the plugin [here](https://github.com/geowarin/friendly-errors-webpack-plugin/blob/master/src/core/extractWebpackError.js)
|
||||
2. Apply transformers to all errors to identify and annotate well know errors and give them a priority
|
||||
3. Get only top priority error or top priority warnings if no errors are thrown
|
||||
4. Apply formatters to all annotated errors
|
||||
|
||||
You can add transformers and formatters. Please see [transformErrors](https://github.com/geowarin/friendly-errors-webpack-plugin/blob/master/src/core/transformErrors.js),
|
||||
and [formatErrors](https://github.com/geowarin/friendly-errors-webpack-plugin/blob/master/src/core/formatErrors.js)
|
||||
in the source code and take a look a the [default transformers](https://github.com/geowarin/friendly-errors-webpack-plugin/tree/master/src/transformers)
|
||||
and the [default formatters](https://github.com/geowarin/friendly-errors-webpack-plugin/tree/master/src/formatters).
|
||||
|
||||
## TODO
|
||||
|
||||
- [x] Make it compatible with node 4
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
|
||||
const FriendlyErrorsWebpackPlugin = require('./src/friendly-errors-plugin');
|
||||
|
||||
module.exports = FriendlyErrorsWebpackPlugin;
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
'use strict';
|
||||
var escapeStringRegexp = require('escape-string-regexp');
|
||||
var ansiStyles = require('ansi-styles');
|
||||
var stripAnsi = require('strip-ansi');
|
||||
var hasAnsi = require('has-ansi');
|
||||
var supportsColor = require('supports-color');
|
||||
var defineProps = Object.defineProperties;
|
||||
var isSimpleWindowsTerm = process.platform === 'win32' && !/^xterm/i.test(process.env.TERM);
|
||||
|
||||
function Chalk(options) {
|
||||
// detect mode if not set manually
|
||||
this.enabled = !options || options.enabled === undefined ? supportsColor : options.enabled;
|
||||
}
|
||||
|
||||
// use bright blue on Windows as the normal blue color is illegible
|
||||
if (isSimpleWindowsTerm) {
|
||||
ansiStyles.blue.open = '\u001b[94m';
|
||||
}
|
||||
|
||||
var styles = (function () {
|
||||
var ret = {};
|
||||
|
||||
Object.keys(ansiStyles).forEach(function (key) {
|
||||
ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g');
|
||||
|
||||
ret[key] = {
|
||||
get: function () {
|
||||
return build.call(this, this._styles.concat(key));
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return ret;
|
||||
})();
|
||||
|
||||
var proto = defineProps(function chalk() {}, styles);
|
||||
|
||||
function build(_styles) {
|
||||
var builder = function () {
|
||||
return applyStyle.apply(builder, arguments);
|
||||
};
|
||||
|
||||
builder._styles = _styles;
|
||||
builder.enabled = this.enabled;
|
||||
// __proto__ is used because we must return a function, but there is
|
||||
// no way to create a function with a different prototype.
|
||||
/* eslint-disable no-proto */
|
||||
builder.__proto__ = proto;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
function applyStyle() {
|
||||
// support varags, but simply cast to string in case there's only one arg
|
||||
var args = arguments;
|
||||
var argsLen = args.length;
|
||||
var str = argsLen !== 0 && String(arguments[0]);
|
||||
|
||||
if (argsLen > 1) {
|
||||
// don't slice `arguments`, it prevents v8 optimizations
|
||||
for (var a = 1; a < argsLen; a++) {
|
||||
str += ' ' + args[a];
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.enabled || !str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
var nestedStyles = this._styles;
|
||||
var i = nestedStyles.length;
|
||||
|
||||
// Turns out that on Windows dimmed gray text becomes invisible in cmd.exe,
|
||||
// see https://github.com/chalk/chalk/issues/58
|
||||
// If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop.
|
||||
var originalDim = ansiStyles.dim.open;
|
||||
if (isSimpleWindowsTerm && (nestedStyles.indexOf('gray') !== -1 || nestedStyles.indexOf('grey') !== -1)) {
|
||||
ansiStyles.dim.open = '';
|
||||
}
|
||||
|
||||
while (i--) {
|
||||
var code = ansiStyles[nestedStyles[i]];
|
||||
|
||||
// Replace any instances already present with a re-opening code
|
||||
// otherwise only the part of the string until said closing code
|
||||
// will be colored, and the rest will simply be 'plain'.
|
||||
str = code.open + str.replace(code.closeRe, code.open) + code.close;
|
||||
}
|
||||
|
||||
// Reset the original 'dim' if we changed it to work around the Windows dimmed gray issue.
|
||||
ansiStyles.dim.open = originalDim;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function init() {
|
||||
var ret = {};
|
||||
|
||||
Object.keys(styles).forEach(function (name) {
|
||||
ret[name] = {
|
||||
get: function () {
|
||||
return build.call(this, [name]);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
defineProps(Chalk.prototype, init());
|
||||
|
||||
module.exports = new Chalk();
|
||||
module.exports.styles = ansiStyles;
|
||||
module.exports.hasColor = hasAnsi;
|
||||
module.exports.stripColor = stripAnsi;
|
||||
module.exports.supportsColor = supportsColor;
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "chalk",
|
||||
"version": "1.1.3",
|
||||
"description": "Terminal string styling done right. Much color.",
|
||||
"license": "MIT",
|
||||
"repository": "chalk/chalk",
|
||||
"maintainers": [
|
||||
"Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)",
|
||||
"Joshua Appelman <jappelman@xebia.com> (jbnicolai.com)",
|
||||
"JD Ballard <i.am.qix@gmail.com> (github.com/qix-)"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && mocha",
|
||||
"bench": "matcha benchmark.js",
|
||||
"coverage": "nyc npm test && nyc report",
|
||||
"coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"color",
|
||||
"colour",
|
||||
"colors",
|
||||
"terminal",
|
||||
"console",
|
||||
"cli",
|
||||
"string",
|
||||
"str",
|
||||
"ansi",
|
||||
"style",
|
||||
"styles",
|
||||
"tty",
|
||||
"formatting",
|
||||
"rgb",
|
||||
"256",
|
||||
"shell",
|
||||
"xterm",
|
||||
"log",
|
||||
"logging",
|
||||
"command-line",
|
||||
"text"
|
||||
],
|
||||
"dependencies": {
|
||||
"ansi-styles": "^2.2.1",
|
||||
"escape-string-regexp": "^1.0.2",
|
||||
"has-ansi": "^2.0.0",
|
||||
"strip-ansi": "^3.0.0",
|
||||
"supports-color": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"coveralls": "^2.11.2",
|
||||
"matcha": "^0.6.0",
|
||||
"mocha": "*",
|
||||
"nyc": "^3.0.0",
|
||||
"require-uncached": "^1.0.2",
|
||||
"resolve-from": "^1.0.0",
|
||||
"semver": "^4.3.3",
|
||||
"xo": "*"
|
||||
},
|
||||
"xo": {
|
||||
"envs": [
|
||||
"node",
|
||||
"mocha"
|
||||
]
|
||||
}
|
||||
}
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<br>
|
||||
<img width="360" src="https://cdn.rawgit.com/chalk/chalk/19935d6484811c5e468817f846b7b3d417d7bf4a/logo.svg" alt="chalk">
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
> Terminal string styling done right
|
||||
|
||||
[](https://travis-ci.org/chalk/chalk)
|
||||
[](https://coveralls.io/r/chalk/chalk?branch=master)
|
||||
[](https://www.youtube.com/watch?v=9auOCbH5Ns4)
|
||||
|
||||
|
||||
[colors.js](https://github.com/Marak/colors.js) used to be the most popular string styling module, but it has serious deficiencies like extending `String.prototype` which causes all kinds of [problems](https://github.com/yeoman/yo/issues/68). Although there are other ones, they either do too much or not enough.
|
||||
|
||||
**Chalk is a clean and focused alternative.**
|
||||
|
||||

|
||||
|
||||
|
||||
## Why
|
||||
|
||||
- Highly performant
|
||||
- Doesn't extend `String.prototype`
|
||||
- Expressive API
|
||||
- Ability to nest styles
|
||||
- Clean and focused
|
||||
- Auto-detects color support
|
||||
- Actively maintained
|
||||
- [Used by ~4500 modules](https://www.npmjs.com/browse/depended/chalk) as of July 15, 2015
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save chalk
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Chalk comes with an easy to use composable API where you just chain and nest the styles you want.
|
||||
|
||||
```js
|
||||
var chalk = require('chalk');
|
||||
|
||||
// style a string
|
||||
chalk.blue('Hello world!');
|
||||
|
||||
// combine styled and normal strings
|
||||
chalk.blue('Hello') + 'World' + chalk.red('!');
|
||||
|
||||
// compose multiple styles using the chainable API
|
||||
chalk.blue.bgRed.bold('Hello world!');
|
||||
|
||||
// pass in multiple arguments
|
||||
chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz');
|
||||
|
||||
// nest styles
|
||||
chalk.red('Hello', chalk.underline.bgBlue('world') + '!');
|
||||
|
||||
// nest styles of the same type even (color, underline, background)
|
||||
chalk.green(
|
||||
'I am a green line ' +
|
||||
chalk.blue.underline.bold('with a blue substring') +
|
||||
' that becomes green again!'
|
||||
);
|
||||
```
|
||||
|
||||
Easily define your own themes.
|
||||
|
||||
```js
|
||||
var chalk = require('chalk');
|
||||
var error = chalk.bold.red;
|
||||
console.log(error('Error!'));
|
||||
```
|
||||
|
||||
Take advantage of console.log [string substitution](http://nodejs.org/docs/latest/api/console.html#console_console_log_data).
|
||||
|
||||
```js
|
||||
var name = 'Sindre';
|
||||
console.log(chalk.green('Hello %s'), name);
|
||||
//=> Hello Sindre
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### chalk.`<style>[.<style>...](string, [string...])`
|
||||
|
||||
Example: `chalk.red.bold.underline('Hello', 'world');`
|
||||
|
||||
Chain [styles](#styles) and call the last one as a method with a string argument. Order doesn't matter, and later styles take precedent in case of a conflict. This simply means that `Chalk.red.yellow.green` is equivalent to `Chalk.green`.
|
||||
|
||||
Multiple arguments will be separated by space.
|
||||
|
||||
### chalk.enabled
|
||||
|
||||
Color support is automatically detected, but you can override it by setting the `enabled` property. You should however only do this in your own code as it applies globally to all chalk consumers.
|
||||
|
||||
If you need to change this in a reusable module create a new instance:
|
||||
|
||||
```js
|
||||
var ctx = new chalk.constructor({enabled: false});
|
||||
```
|
||||
|
||||
### chalk.supportsColor
|
||||
|
||||
Detect whether the terminal [supports color](https://github.com/chalk/supports-color). Used internally and handled for you, but exposed for convenience.
|
||||
|
||||
Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, add an environment variable `FORCE_COLOR` with any value to force color. Trumps `--no-color`.
|
||||
|
||||
### chalk.styles
|
||||
|
||||
Exposes the styles as [ANSI escape codes](https://github.com/chalk/ansi-styles).
|
||||
|
||||
Generally not useful, but you might need just the `.open` or `.close` escape code if you're mixing externally styled strings with your own.
|
||||
|
||||
```js
|
||||
var chalk = require('chalk');
|
||||
|
||||
console.log(chalk.styles.red);
|
||||
//=> {open: '\u001b[31m', close: '\u001b[39m'}
|
||||
|
||||
console.log(chalk.styles.red.open + 'Hello' + chalk.styles.red.close);
|
||||
```
|
||||
|
||||
### chalk.hasColor(string)
|
||||
|
||||
Check whether a string [has color](https://github.com/chalk/has-ansi).
|
||||
|
||||
### chalk.stripColor(string)
|
||||
|
||||
[Strip color](https://github.com/chalk/strip-ansi) from a string.
|
||||
|
||||
Can be useful in combination with `.supportsColor` to strip color on externally styled text when it's not supported.
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
var chalk = require('chalk');
|
||||
var styledString = getText();
|
||||
|
||||
if (!chalk.supportsColor) {
|
||||
styledString = chalk.stripColor(styledString);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Styles
|
||||
|
||||
### Modifiers
|
||||
|
||||
- `reset`
|
||||
- `bold`
|
||||
- `dim`
|
||||
- `italic` *(not widely supported)*
|
||||
- `underline`
|
||||
- `inverse`
|
||||
- `hidden`
|
||||
- `strikethrough` *(not widely supported)*
|
||||
|
||||
### Colors
|
||||
|
||||
- `black`
|
||||
- `red`
|
||||
- `green`
|
||||
- `yellow`
|
||||
- `blue` *(on Windows the bright version is used as normal blue is illegible)*
|
||||
- `magenta`
|
||||
- `cyan`
|
||||
- `white`
|
||||
- `gray`
|
||||
|
||||
### Background colors
|
||||
|
||||
- `bgBlack`
|
||||
- `bgRed`
|
||||
- `bgGreen`
|
||||
- `bgYellow`
|
||||
- `bgBlue`
|
||||
- `bgMagenta`
|
||||
- `bgCyan`
|
||||
- `bgWhite`
|
||||
|
||||
|
||||
## 256-colors
|
||||
|
||||
Chalk does not support anything other than the base eight colors, which guarantees it will work on all terminals and systems. Some terminals, specifically `xterm` compliant ones, will support the full range of 8-bit colors. For this the lower level [ansi-256-colors](https://github.com/jbnicolai/ansi-256-colors) package can be used.
|
||||
|
||||
|
||||
## Windows
|
||||
|
||||
If you're on Windows, do yourself a favor and use [`cmder`](http://bliker.github.io/cmder/) instead of `cmd.exe`.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [chalk-cli](https://github.com/chalk/chalk-cli) - CLI for this module
|
||||
- [ansi-styles](https://github.com/chalk/ansi-styles/) - ANSI escape codes for styling strings in the terminal
|
||||
- [supports-color](https://github.com/chalk/supports-color/) - Detect whether a terminal supports color
|
||||
- [strip-ansi](https://github.com/chalk/strip-ansi) - Strip ANSI escape codes
|
||||
- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes
|
||||
- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes
|
||||
- [wrap-ansi](https://github.com/chalk/wrap-ansi) - Wordwrap a string with ANSI escape codes
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](http://sindresorhus.com)
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "friendly-errors-webpack-plugin",
|
||||
"version": "1.7.0",
|
||||
"description": "Recognizes certain classes of webpack errors and cleans, aggregates and prioritizes them to provide a better Developer Experience",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "eslint --ignore-pattern test/* && jest"
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"friendly",
|
||||
"errors",
|
||||
"webpack",
|
||||
"plugin"
|
||||
],
|
||||
"author": "Geoffroy Warin",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/geowarin/friendly-errors-webpack-plugin.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/geowarin/friendly-errors-webpack-plugin/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"webpack": "^2.0.0 || ^3.0.0 || ^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.23.1",
|
||||
"babel-eslint": "^7.1.1",
|
||||
"babel-loader": "^6.3.0",
|
||||
"babel-plugin-transform-async-to-generator": "^6.22.0",
|
||||
"babel-preset-react": "^6.23.0",
|
||||
"eslint": "^3.16.1",
|
||||
"eslint-loader": "^1.6.1",
|
||||
"expect": "^1.20.2",
|
||||
"jest": "^18.1.0",
|
||||
"memory-fs": "^0.4.1",
|
||||
"webpack": "^2.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "^1.1.3",
|
||||
"error-stack-parser": "^2.0.0",
|
||||
"string-width": "^2.0.0"
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
'use strict';
|
||||
|
||||
const ErrorStackParser = require('error-stack-parser');
|
||||
const RequestShortener = require("webpack/lib/RequestShortener");
|
||||
|
||||
// TODO: allow the location to be customized in options
|
||||
const requestShortener = new RequestShortener(process.cwd());
|
||||
|
||||
/*
|
||||
This logic is mostly duplicated from webpack/lib/Stats.js#toJson()
|
||||
See: https://github.com/webpack/webpack/blob/2f618e733aab4755deb42e9d8e859609005607c0/lib/Stats.js#L89
|
||||
*/
|
||||
|
||||
function extractError (e) {
|
||||
return {
|
||||
message: e.message,
|
||||
file: getFile(e),
|
||||
origin: getOrigin(e),
|
||||
name: e.name,
|
||||
severity: 0,
|
||||
webpackError: e,
|
||||
originalStack: getOriginalErrorStack(e)
|
||||
};
|
||||
}
|
||||
|
||||
function getOriginalErrorStack(e) {
|
||||
while (e.error != null) {
|
||||
e = e.error;
|
||||
}
|
||||
if (e.stack) {
|
||||
return ErrorStackParser.parse(e);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function getFile (e) {
|
||||
if (e.file) {
|
||||
return e.file;
|
||||
} else if (e.module && e.module.readableIdentifier && typeof e.module.readableIdentifier === "function") {
|
||||
return e.module.readableIdentifier(requestShortener);
|
||||
}
|
||||
}
|
||||
|
||||
function getOrigin (e) {
|
||||
let origin = '';
|
||||
if (e.dependencies && e.origin) {
|
||||
origin += '\n @ ' + e.origin.readableIdentifier(requestShortener);
|
||||
e.dependencies.forEach(function (dep) {
|
||||
if (!dep.loc) return;
|
||||
if (typeof dep.loc === "string") return;
|
||||
if (!dep.loc.start) return;
|
||||
if (!dep.loc.end) return;
|
||||
origin += ' ' + dep.loc.start.line + ':' + dep.loc.start.column + '-' +
|
||||
(dep.loc.start.line !== dep.loc.end.line ? dep.loc.end.line + ':' : '') + dep.loc.end.column;
|
||||
});
|
||||
var current = e.origin;
|
||||
while (current.issuer && typeof current.issuer.readableIdentifier === 'function') {
|
||||
current = current.issuer;
|
||||
origin += '\n @ ' + current.readableIdentifier(requestShortener);
|
||||
}
|
||||
}
|
||||
return origin;
|
||||
}
|
||||
|
||||
module.exports = extractError;
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Applies formatters to all AnnotatedErrors.
|
||||
*
|
||||
* A formatter has the following signature: FormattedError => Array<String>.
|
||||
* It takes a formatted error produced by a transformer and returns a list
|
||||
* of log statements to print.
|
||||
*
|
||||
*/
|
||||
function formatErrors(errors, formatters, errorType) {
|
||||
const format = (formatter) => formatter(errors, errorType) || [];
|
||||
const flatten = (accum, curr) => accum.concat(curr);
|
||||
|
||||
return formatters.map(format).reduce(flatten, [])
|
||||
}
|
||||
|
||||
module.exports = formatErrors;
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
'use strict';
|
||||
|
||||
const extractError = require('./extractWebpackError');
|
||||
|
||||
/**
|
||||
* Applies all transformers to all errors and returns "annotated"
|
||||
* errors.
|
||||
*
|
||||
* Each transformer should have the following signature WebpackError => AnnotatedError
|
||||
*
|
||||
* A WebpackError has the following fields:
|
||||
* - message
|
||||
* - file
|
||||
* - origin
|
||||
* - name
|
||||
* - severity
|
||||
* - webpackError (original error)
|
||||
*
|
||||
* An AnnotatedError should be an extension (Object.assign) of the WebpackError
|
||||
* and add whatever information is convenient for formatting.
|
||||
* In particular, they should have a 'priority' field.
|
||||
*
|
||||
* The plugin will only display errors having maximum priority at the same time.
|
||||
*
|
||||
* If they don't have a 'type' field, the will be handled by the default formatter.
|
||||
*/
|
||||
function processErrors (errors, transformers) {
|
||||
const transform = (error, transformer) => transformer(error);
|
||||
const applyTransformations = (error) => transformers.reduce(transform, error);
|
||||
|
||||
return errors.map(extractError).map(applyTransformations);
|
||||
}
|
||||
|
||||
module.exports = processErrors;
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
const concat = require('../utils').concat;
|
||||
const formatTitle = require('../utils/colors').formatTitle;
|
||||
|
||||
function displayError(severity, error) {
|
||||
const baseError = formatTitle(severity, severity);
|
||||
|
||||
return concat(
|
||||
`${baseError} ${removeLoaders(error.file)}`,
|
||||
'',
|
||||
error.message,
|
||||
(error.origin ? error.origin : undefined),
|
||||
'',
|
||||
error.infos
|
||||
);
|
||||
}
|
||||
|
||||
function removeLoaders(file) {
|
||||
if (!file) {
|
||||
return "";
|
||||
}
|
||||
const split = file.split('!');
|
||||
const filePath = split[split.length - 1];
|
||||
return `in ${filePath}`;
|
||||
}
|
||||
|
||||
function isDefaultError(error) {
|
||||
return !error.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format errors without a type
|
||||
*/
|
||||
function format(errors, type) {
|
||||
return errors
|
||||
.filter(isDefaultError)
|
||||
.reduce((accum, error) => (
|
||||
accum.concat(displayError(type, error))
|
||||
), []);
|
||||
}
|
||||
|
||||
module.exports = format;
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const concat = require('../utils').concat;
|
||||
const chalk = require('chalk');
|
||||
|
||||
const infos = [
|
||||
'You may use special comments to disable some warnings.',
|
||||
'Use ' + chalk.yellow('// eslint-disable-next-line') + ' to ignore the next line.',
|
||||
'Use ' + chalk.yellow('/* eslint-disable */') + ' to ignore all warnings in a file.'
|
||||
];
|
||||
|
||||
function displayError(error) {
|
||||
return [error.message, '']
|
||||
}
|
||||
|
||||
function format(errors, type) {
|
||||
const lintErrors = errors.filter(e => e.type === 'lint-error');
|
||||
if (lintErrors.length > 0) {
|
||||
const flatten = (accum, curr) => accum.concat(curr);
|
||||
return concat(
|
||||
lintErrors
|
||||
.map(error => displayError(error))
|
||||
.reduce(flatten, []),
|
||||
infos
|
||||
)
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
module.exports = format;
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
'use strict';
|
||||
const concat = require('../utils').concat;
|
||||
|
||||
function isRelative (module) {
|
||||
return module.startsWith('./') || module.startsWith('../');
|
||||
}
|
||||
|
||||
function formatFileList (files) {
|
||||
const length = files.length;
|
||||
if (!length) return '';
|
||||
return ` in ${files[0]}${files[1] ? `, ${files[1]}` : ''}${length > 2 ? ` and ${length - 2} other${length === 3 ? '' : 's'}` : ''}`;
|
||||
}
|
||||
|
||||
function formatGroup (group) {
|
||||
const files = group.errors.map(e => e.file).filter(Boolean);
|
||||
return `* ${group.module}${formatFileList(files)}`;
|
||||
}
|
||||
|
||||
|
||||
function forgetToInstall (missingDependencies) {
|
||||
const moduleNames = missingDependencies.map(missingDependency => missingDependency.module);
|
||||
|
||||
if (missingDependencies.length === 1) {
|
||||
return `To install it, you can run: npm install --save ${moduleNames.join(' ')}`;
|
||||
}
|
||||
|
||||
return `To install them, you can run: npm install --save ${moduleNames.join(' ')}`;
|
||||
}
|
||||
|
||||
function dependenciesNotFound (dependencies) {
|
||||
if (dependencies.length === 0) return;
|
||||
|
||||
return concat(
|
||||
dependencies.length === 1 ? 'This dependency was not found:' : 'These dependencies were not found:',
|
||||
'',
|
||||
dependencies.map(formatGroup),
|
||||
'',
|
||||
forgetToInstall(dependencies)
|
||||
);
|
||||
}
|
||||
|
||||
function relativeModulesNotFound (modules) {
|
||||
if (modules.length === 0) return;
|
||||
|
||||
return concat(
|
||||
modules.length === 1 ? 'This relative module was not found:' : 'These relative modules were not found:',
|
||||
'',
|
||||
modules.map(formatGroup)
|
||||
);
|
||||
}
|
||||
|
||||
function groupModules (errors) {
|
||||
const missingModule = new Map();
|
||||
|
||||
errors.forEach((error) => {
|
||||
if (!missingModule.has(error.module)) {
|
||||
missingModule.set(error.module, [])
|
||||
}
|
||||
missingModule.get(error.module).push(error);
|
||||
});
|
||||
|
||||
return Array.from(missingModule.keys()).map(module => ({
|
||||
module: module,
|
||||
relative: isRelative(module),
|
||||
errors: missingModule.get(module),
|
||||
}));
|
||||
}
|
||||
|
||||
function formatErrors (errors) {
|
||||
if (errors.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const groups = groupModules(errors);
|
||||
|
||||
const dependencies = groups.filter(group => !group.relative);
|
||||
const relativeModules = groups.filter(group => group.relative);
|
||||
|
||||
return concat(
|
||||
dependenciesNotFound(dependencies),
|
||||
dependencies.length && relativeModules.length ? ['', ''] : null,
|
||||
relativeModulesNotFound(relativeModules)
|
||||
);
|
||||
}
|
||||
|
||||
function format (errors) {
|
||||
return formatErrors(errors.filter((e) => (
|
||||
e.type === 'module-not-found'
|
||||
)));
|
||||
}
|
||||
|
||||
module.exports = format;
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const chalk = require('chalk');
|
||||
const os = require('os');
|
||||
const transformErrors = require('./core/transformErrors');
|
||||
const formatErrors = require('./core/formatErrors');
|
||||
const output = require('./output');
|
||||
const utils = require('./utils');
|
||||
|
||||
const concat = utils.concat;
|
||||
const uniqueBy = utils.uniqueBy;
|
||||
|
||||
const defaultTransformers = [
|
||||
require('./transformers/babelSyntax'),
|
||||
require('./transformers/moduleNotFound'),
|
||||
require('./transformers/esLintError'),
|
||||
];
|
||||
|
||||
const defaultFormatters = [
|
||||
require('./formatters/moduleNotFound'),
|
||||
require('./formatters/eslintError'),
|
||||
require('./formatters/defaultError'),
|
||||
];
|
||||
|
||||
class FriendlyErrorsWebpackPlugin {
|
||||
|
||||
constructor(options) {
|
||||
options = options || {};
|
||||
this.compilationSuccessInfo = options.compilationSuccessInfo || {};
|
||||
this.onErrors = options.onErrors;
|
||||
this.shouldClearConsole = options.clearConsole == null ? true : Boolean(options.clearConsole);
|
||||
this.formatters = concat(defaultFormatters, options.additionalFormatters);
|
||||
this.transformers = concat(defaultTransformers, options.additionalTransformers);
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
|
||||
const doneFn = stats => {
|
||||
this.clearConsole();
|
||||
|
||||
const hasErrors = stats.hasErrors();
|
||||
const hasWarnings = stats.hasWarnings();
|
||||
|
||||
if (!hasErrors && !hasWarnings) {
|
||||
this.displaySuccess(stats);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasErrors) {
|
||||
this.displayErrors(extractErrorsFromStats(stats, 'errors'), 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasWarnings) {
|
||||
this.displayErrors(extractErrorsFromStats(stats, 'warnings'), 'warning');
|
||||
}
|
||||
};
|
||||
|
||||
const invalidFn = () => {
|
||||
this.clearConsole();
|
||||
output.title('info', 'WAIT', 'Compiling...');
|
||||
};
|
||||
|
||||
if (compiler.hooks) {
|
||||
const plugin = { name: 'FriendlyErrorsWebpackPlugin' };
|
||||
|
||||
compiler.hooks.done.tap(plugin, doneFn);
|
||||
compiler.hooks.invalid.tap(plugin, invalidFn);
|
||||
} else {
|
||||
compiler.plugin('done', doneFn);
|
||||
compiler.plugin('invalid', invalidFn);
|
||||
}
|
||||
}
|
||||
|
||||
clearConsole() {
|
||||
if (this.shouldClearConsole) {
|
||||
output.clearConsole();
|
||||
}
|
||||
}
|
||||
|
||||
displaySuccess(stats) {
|
||||
const time = getCompileTime(stats);
|
||||
output.title('success', 'DONE', 'Compiled successfully in ' + time + 'ms');
|
||||
|
||||
if (this.compilationSuccessInfo.messages) {
|
||||
this.compilationSuccessInfo.messages.forEach(message => output.info(message));
|
||||
}
|
||||
if (this.compilationSuccessInfo.notes) {
|
||||
output.log();
|
||||
this.compilationSuccessInfo.notes.forEach(note => output.note(note));
|
||||
}
|
||||
}
|
||||
|
||||
displayErrors(errors, severity) {
|
||||
const processedErrors = transformErrors(errors, this.transformers);
|
||||
|
||||
const topErrors = getMaxSeverityErrors(processedErrors);
|
||||
const nbErrors = topErrors.length;
|
||||
|
||||
const subtitle = severity === 'error' ?
|
||||
`Failed to compile with ${nbErrors} ${severity}s` :
|
||||
`Compiled with ${nbErrors} ${severity}s`;
|
||||
output.title(severity, severity.toUpperCase(), subtitle);
|
||||
|
||||
if (this.onErrors) {
|
||||
this.onErrors(severity, topErrors);
|
||||
}
|
||||
|
||||
formatErrors(topErrors, this.formatters, severity)
|
||||
.forEach(chunk => output.log(chunk));
|
||||
}
|
||||
}
|
||||
|
||||
function extractErrorsFromStats(stats, type) {
|
||||
if (isMultiStats(stats)) {
|
||||
const errors = stats.stats
|
||||
.reduce((errors, stats) => errors.concat(extractErrorsFromStats(stats, type)), []);
|
||||
// Dedupe to avoid showing the same error many times when multiple
|
||||
// compilers depend on the same module.
|
||||
return uniqueBy(errors, error => error.message);
|
||||
}
|
||||
return stats.compilation[type];
|
||||
}
|
||||
|
||||
function getCompileTime(stats) {
|
||||
if (isMultiStats(stats)) {
|
||||
// Webpack multi compilations run in parallel so using the longest duration.
|
||||
// https://webpack.github.io/docs/configuration.html#multiple-configurations
|
||||
return stats.stats
|
||||
.reduce((time, stats) => Math.max(time, getCompileTime(stats)), 0);
|
||||
}
|
||||
return stats.endTime - stats.startTime;
|
||||
}
|
||||
|
||||
function isMultiStats(stats) {
|
||||
return stats.stats;
|
||||
}
|
||||
|
||||
function getMaxSeverityErrors(errors) {
|
||||
const maxSeverity = getMaxInt(errors, 'severity');
|
||||
return errors.filter(e => e.severity === maxSeverity);
|
||||
}
|
||||
|
||||
function getMaxInt(collection, propertyName) {
|
||||
return collection.reduce((res, curr) => {
|
||||
return curr[propertyName] > res ? curr[propertyName] : res;
|
||||
}, 0)
|
||||
}
|
||||
|
||||
module.exports = FriendlyErrorsWebpackPlugin;
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
'use strict';
|
||||
|
||||
const colors = require('./utils/colors');
|
||||
const chalk = require('chalk');
|
||||
const stringWidth = require('string-width');
|
||||
const readline = require('readline');
|
||||
|
||||
class Debugger {
|
||||
|
||||
constructor () {
|
||||
this.enabled = true;
|
||||
this.capturing = false;
|
||||
this.capturedMessages = [];
|
||||
}
|
||||
|
||||
enable () {
|
||||
this.enabled = true;
|
||||
}
|
||||
|
||||
capture () {
|
||||
this.enabled = true;
|
||||
this.capturing = true;
|
||||
}
|
||||
|
||||
endCapture () {
|
||||
this.enabled = false;
|
||||
this.capturing = false;
|
||||
this.capturedMessages = [];
|
||||
}
|
||||
|
||||
log () {
|
||||
if (this.enabled) {
|
||||
this.captureConsole(Array.from(arguments), console.log);
|
||||
}
|
||||
}
|
||||
|
||||
info (message) {
|
||||
if (this.enabled) {
|
||||
const titleFormatted = colors.formatTitle('info', 'I');
|
||||
this.log(titleFormatted, message);
|
||||
}
|
||||
}
|
||||
|
||||
note (message) {
|
||||
if (this.enabled) {
|
||||
const titleFormatted = colors.formatTitle('note', 'N');
|
||||
this.log(titleFormatted, message);
|
||||
}
|
||||
}
|
||||
|
||||
title (severity, title, subtitle) {
|
||||
if (this.enabled) {
|
||||
const date = new Date();
|
||||
const dateString = chalk.grey(date.toLocaleTimeString());
|
||||
const titleFormatted = colors.formatTitle(severity, title);
|
||||
const subTitleFormatted = colors.formatText(severity, subtitle);
|
||||
const message = `${titleFormatted} ${subTitleFormatted}`
|
||||
|
||||
// In test environment we don't include timestamp
|
||||
if(process.env.NODE_ENV === 'test') {
|
||||
this.log(message);
|
||||
this.log();
|
||||
return;
|
||||
}
|
||||
|
||||
// Make timestamp appear at the end of the line
|
||||
let logSpace = process.stdout.columns - stringWidth(message) - stringWidth(dateString)
|
||||
if (logSpace <= 0) {
|
||||
logSpace = 10
|
||||
}
|
||||
|
||||
this.log(`${message}${' '.repeat(logSpace)}${dateString}`);
|
||||
this.log();
|
||||
}
|
||||
}
|
||||
|
||||
clearConsole () {
|
||||
if (!this.capturing && this.enabled && process.stdout.isTTY) {
|
||||
// Fill screen with blank lines. Then move to 0 (beginning of visible part) and clear it
|
||||
const blank = '\n'.repeat(process.stdout.rows)
|
||||
console.log(blank)
|
||||
readline.cursorTo(process.stdout, 0, 0)
|
||||
readline.clearScreenDown(process.stdout)
|
||||
}
|
||||
}
|
||||
|
||||
captureLogs (fun) {
|
||||
try {
|
||||
this.capture();
|
||||
fun.call();
|
||||
return this.capturedMessages;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
} finally {
|
||||
this.endCapture();
|
||||
}
|
||||
}
|
||||
|
||||
captureConsole (args, method) {
|
||||
if (this.capturing) {
|
||||
this.capturedMessages.push(chalk.stripColor(args.join(' ')).trim());
|
||||
} else {
|
||||
method.apply(console, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function capitalizeFirstLetter (string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
module.exports = new Debugger();
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* This will be removed in next versions as it is not handled in the babel-loader
|
||||
* See: https://github.com/geowarin/friendly-errors-webpack-plugin/issues/2
|
||||
*/
|
||||
function cleanStackTrace(message) {
|
||||
return message
|
||||
.replace(/^\s*at\s.*:\d+:\d+[\s\)]*\n/gm, ''); // at ... ...:x:y
|
||||
}
|
||||
|
||||
function cleanMessage(message) {
|
||||
return message
|
||||
// match until the last semicolon followed by a space
|
||||
// this should match
|
||||
// linux => "(SyntaxError: )Unexpected token (5:11)"
|
||||
// windows => "(SyntaxError: C:/projects/index.js: )Unexpected token (5:11)"
|
||||
.replace(/^Module build failed.*:\s/, 'Syntax Error: ');
|
||||
}
|
||||
|
||||
function isBabelSyntaxError(e) {
|
||||
return e.name === 'ModuleBuildError' &&
|
||||
e.message.indexOf('SyntaxError') >= 0;
|
||||
}
|
||||
|
||||
function transform(error) {
|
||||
if (isBabelSyntaxError(error)) {
|
||||
return Object.assign({}, error, {
|
||||
message: cleanStackTrace(cleanMessage(error.message) + '\n'),
|
||||
severity: 1000,
|
||||
name: 'Syntax Error',
|
||||
});
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
module.exports = transform;
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
function isEslintError (e) {
|
||||
return e.originalStack
|
||||
.some(stackframe => stackframe.fileName && stackframe.fileName.indexOf('eslint-loader') > 0);
|
||||
}
|
||||
|
||||
function transform(error) {
|
||||
if (isEslintError(error)) {
|
||||
return Object.assign({}, error, {
|
||||
name: 'Lint error',
|
||||
type: 'lint-error',
|
||||
});
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
module.exports = transform;
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
const TYPE = 'module-not-found';
|
||||
|
||||
function isModuleNotFoundError (e) {
|
||||
const webpackError = e.webpackError || {};
|
||||
return webpackError.dependencies
|
||||
&& webpackError.dependencies.length > 0
|
||||
&& e.name === 'ModuleNotFoundError'
|
||||
&& e.message.indexOf('Module not found') === 0;
|
||||
}
|
||||
|
||||
function transform(error) {
|
||||
const webpackError = error.webpackError;
|
||||
if (isModuleNotFoundError(error)) {
|
||||
const module = webpackError.dependencies[0].request;
|
||||
return Object.assign({}, error, {
|
||||
message: `Module not found ${module}`,
|
||||
type: TYPE,
|
||||
severity: 900,
|
||||
module,
|
||||
name: 'Module not found'
|
||||
});
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
module.exports = transform;
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
const chalk = require('chalk');
|
||||
|
||||
function formatTitle(severity, message) {
|
||||
return chalk[bgColor(severity)].black('', message, '');
|
||||
}
|
||||
|
||||
function formatText(severity, message) {
|
||||
return chalk[textColor(severity)](message);
|
||||
}
|
||||
|
||||
function bgColor(severity) {
|
||||
const color = textColor(severity);
|
||||
return 'bg'+ capitalizeFirstLetter(color)
|
||||
}
|
||||
|
||||
function textColor(serverity) {
|
||||
switch (serverity.toLowerCase()) {
|
||||
case 'success': return 'green';
|
||||
case 'info': return 'blue';
|
||||
case 'note': return 'white';
|
||||
case 'warning': return 'yellow';
|
||||
case 'error': return 'red';
|
||||
default: return 'red';
|
||||
}
|
||||
}
|
||||
|
||||
function capitalizeFirstLetter(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
bgColor: bgColor,
|
||||
textColor: textColor,
|
||||
formatTitle: formatTitle,
|
||||
formatText: formatText
|
||||
};
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Concat and flattens non-null values.
|
||||
* Ex: concat(1, undefined, 2, [3, 4]) = [1, 2, 3, 4]
|
||||
*/
|
||||
function concat() {
|
||||
const args = Array.from(arguments).filter(e => e != null);
|
||||
const baseArray = Array.isArray(args[0]) ? args[0] : [args[0]];
|
||||
return Array.prototype.concat.apply(baseArray, args.slice(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dedupes array based on criterion returned from iteratee function.
|
||||
* Ex: uniqueBy(
|
||||
* [{ id: 1 }, { id: 1 }, { id: 2 }],
|
||||
* val => val.id
|
||||
* ) = [{ id: 1 }, { id: 2 }]
|
||||
*/
|
||||
function uniqueBy(arr, fun) {
|
||||
const seen = {};
|
||||
return arr.filter(el => {
|
||||
const e = fun(el);
|
||||
return !(e in seen) && (seen[e] = 1);
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
concat: concat,
|
||||
uniqueBy: uniqueBy
|
||||
};
|
||||
Reference in New Issue
Block a user