From 0dc0d2b535aad84ca61e26c0092c9d2b26d7baf3 Mon Sep 17 00:00:00 2001 From: Siddharth Doshi Date: Fri, 12 May 2017 21:32:42 +0530 Subject: [PATCH] Add custom eslint formatter --- .../react-dev-utils/formatWebpackMessages.js | 49 --------------- packages/react-scripts/config/formatter.js | 63 +++++++++++++++++++ .../config/webpack.config.dev.js | 2 + 3 files changed, 65 insertions(+), 49 deletions(-) create mode 100644 packages/react-scripts/config/formatter.js diff --git a/packages/react-dev-utils/formatWebpackMessages.js b/packages/react-dev-utils/formatWebpackMessages.js index ad12e0ac931..6ed6bd090d3 100644 --- a/packages/react-dev-utils/formatWebpackMessages.js +++ b/packages/react-dev-utils/formatWebpackMessages.js @@ -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 diff --git a/packages/react-scripts/config/formatter.js b/packages/react-scripts/config/formatter.js new file mode 100644 index 00000000000..dde9527d59b --- /dev/null +++ b/packages/react-scripts/config/formatter.js @@ -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; diff --git a/packages/react-scripts/config/webpack.config.dev.js b/packages/react-scripts/config/webpack.config.dev.js index e7ab84a2ee1..80728726d52 100644 --- a/packages/react-scripts/config/webpack.config.dev.js +++ b/packages/react-scripts/config/webpack.config.dev.js @@ -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('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. @@ -123,6 +124,7 @@ module.exports = { // @remove-on-eject-begin // Point ESLint to our predefined config. options: { + formatter, baseConfig: { extends: ['react-app'], },