Skip to content
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

Add custom eslint formatter #2138

Merged
merged 5 commits into from
May 14, 2017
Merged
Show file tree
Hide file tree
Changes from 3 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
36 changes: 36 additions & 0 deletions packages/react-dev-utils/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,42 @@ compiler.plugin('done', function(stats) {
});
```

#### `formatter(results: Object): string`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make it eslintFormatter instead?


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe "This is our custom ESLint formatter that integrates well with Create React App console output. You can remove it and use the default one instead."

This is our custom ESLint formatter that integrates well with Create React App console output. You can remove it and use the default one instead

```js
const formatter = require('react-dev-utils/formatter');
const webpack = require('webpack');

// Eslint loader in your webpack config
module: {
Copy link
Contributor

@gaearon gaearon May 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not very clear this is Webpack config. I'd prefer that we show a specific ESLint rule alone, with a comment like

// ESLint loader in your webpack config:
// ...

strictExportPresence: true,
rules: [
{ parser: { requireEnsure: false } },
{
test: /\.(js|jsx)$/,
enforce: 'pre',
use: [
{
// Point ESLint to our predefined config.
options: {
formatter,
baseConfig: {
extends: ['react-app'],
},
ignore: false,
useEslintrc: false,
},
loader: 'eslint-loader',
},
],
include: paths.appSrc,
}
]
}
```

#### `getProcessForPort(port: number): string`

Finds the currently running process on `port`.
Expand Down
49 changes: 0 additions & 49 deletions packages/react-dev-utils/formatWebpackMessages.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,55 +85,6 @@ function formatMessage(message, isError) {
);
}

// TODO: Ideally we should write a custom ESLint formatter instead.

// If the second line already includes a filename, and it's a warning,
// this is likely coming from ESLint. Skip it because Webpack also prints it.
// Let's omit that in this case.
var BEGIN_ESLINT_FILENAME = String.fromCharCode(27) + '[4m';
// Also filter out ESLint summaries for each file
var BEGIN_ESLINT_WARNING_SUMMARY = String.fromCharCode(27) +
'[33m' +
String.fromCharCode(27) +
'[1m' +
String.fromCharCode(10006);
var BEGIN_ESLINT_ERROR_SUMMARY = String.fromCharCode(27) +
'[31m' +
String.fromCharCode(27) +
'[1m' +
String.fromCharCode(10006);
// ESLint puts separators like this between groups. We don't need them:
var ESLINT_EMPTY_SEPARATOR = String.fromCharCode(27) +
'[22m' +
String.fromCharCode(27) +
'[39m';
// Go!
lines = lines.filter(function(line) {
if (line === ESLINT_EMPTY_SEPARATOR) {
return false;
}
if (
line.indexOf(BEGIN_ESLINT_FILENAME) === 0 ||
line.indexOf(BEGIN_ESLINT_WARNING_SUMMARY) === 0 ||
line.indexOf(BEGIN_ESLINT_ERROR_SUMMARY) === 0
) {
return false;
}
return true;
});

var ESLINT_WARNING_LABEL = String.fromCharCode(27) +
'[33m' +
'warning' +
String.fromCharCode(27) +
'[39m';
// If there were errors, omit any warnings.
if (isError) {
lines = lines.filter(function(line) {
return line.indexOf(ESLINT_WARNING_LABEL) === -1;
});
}

// Prepend filename with an explanation.
lines[0] =
// Underline
Expand Down
63 changes: 63 additions & 0 deletions packages/react-dev-utils/formatter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
'use strict';

const chalk = require('chalk');
const table = require('text-table');

function isError(message) {
if (message.fatal || message.severity === 2) {
return true;
}
return false;
}

function formatter(results) {
let output = '\n';

results.forEach(result => {
let messages = result.messages;
if (messages.length === 0) {
return '';
}

let thereAreErrors = false;
messages = messages.map(message => {
let messageType;
if (isError(message)) {
messageType = 'error';
thereAreErrors = true;
} else {
messageType = 'warn';
}
let line = message.line || 0;
let column = message.column || 0;
let position = chalk.dim(`${line}:${column}`);
return [
'',
position,
messageType,
message.message.replace(/\.$/, ''),
chalk.dim(message.ruleId || ''),
];
});
// if there are error messages, we want to show only errors
if (thereAreErrors) {
messages = messages.filter(m => m[2] === 'error');
}
// add color to messageTypes
messages = messages.map(m => {
m[2] = m[2] === 'error' ? chalk.red(m[2]) : chalk.yellow(m[2]);
return m;
});
let outputTable = table(messages, {
align: ['l', 'l', 'l'],
stringLength(str) {
return chalk.stripColor(str).length;
},
});
output += `${outputTable}\n\n`;
});

return output;
}

module.exports = formatter;
1 change: 1 addition & 0 deletions packages/react-dev-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"node": ">=6"
},
"files": [
"formatter.js",
"ansiHTML.js",
"checkRequiredFiles.js",
"clearConsole.js",
Expand Down
2 changes: 2 additions & 0 deletions packages/react-scripts/config/webpack.config.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const getClientEnvironment = require('./env');
const paths = require('./paths');
const formatter = require('react-dev-utils/formatter');

// Webpack uses `publicPath` to determine where the app is being served from.
// In development, we always serve from the root. This makes config easier.
Expand Down Expand Up @@ -123,6 +124,7 @@ module.exports = {
// @remove-on-eject-begin
// Point ESLint to our predefined config.
options: {
formatter,
baseConfig: {
extends: ['react-app'],
},
Expand Down