From c8ea6fd0a443078ec1d222ec7e4f02ccd758db44 Mon Sep 17 00:00:00 2001 From: John Reilly Date: Sat, 23 Feb 2019 09:02:57 +0000 Subject: [PATCH 1/4] reattempt changes --- packages/react-dev-utils/README.md | 5 +- .../react-dev-utils/WebpackDevServerUtils.js | 4 +- .../react-dev-utils/formatWebpackMessages.js | 20 ++-- .../react-dev-utils/typescriptFormatter.js | 107 ++++++++++-------- .../react-dev-utils/webpackHotDevClient.js | 22 ++-- packages/react-scripts/scripts/start.js | 2 + 6 files changed, 95 insertions(+), 65 deletions(-) diff --git a/packages/react-dev-utils/README.md b/packages/react-dev-utils/README.md index 9d43182d05e..0e4dfb277a7 100644 --- a/packages/react-dev-utils/README.md +++ b/packages/react-dev-utils/README.md @@ -220,7 +220,7 @@ measureFileSizesBeforeBuild(buildFolder).then(previousFileSizes => { }); ``` -#### `formatWebpackMessages({errors: Array, warnings: Array}): {errors: Array, warnings: Array}` +#### `formatWebpackMessages({errors: Array, warnings: Array}): {errors: Array, warnings: Array}, filePathToExclude: string)` Extracts and prettifies warning and error messages from webpack [stats](https://github.com/webpack/docs/wiki/node.js-api#stats) object. @@ -332,7 +332,8 @@ Creates a Webpack compiler instance for WebpackDevServer with built-in helpful m The `args` object accepts a number of properties: - **appName** `string`: The name that will be printed to the terminal. -- **config** `Object`: The webpack configuration options to be provided to the webpack constructor. +- **appPath** `string`: The path to the application. Used to make error / warning paths pithier. +- **config** `Object`: The webpack configuration options to be provided to the webpack constructor. - **devSocket** `Object`: Required if `useTypeScript` is `true`. This object should include `errors` and `warnings` which are functions accepting an array of errors or warnings emitted by the type checking. This is useful when running `fork-ts-checker-webpack-plugin` with `async: true` to report errors that are emitted after the webpack build is complete. - **urls** `Object`: To provide the `urls` argument, use `prepareUrls()` described below. - **useYarn** `boolean`: If `true`, yarn instructions will be emitted in the terminal instead of npm. diff --git a/packages/react-dev-utils/WebpackDevServerUtils.js b/packages/react-dev-utils/WebpackDevServerUtils.js index 1d7021e037c..154333a0ff9 100644 --- a/packages/react-dev-utils/WebpackDevServerUtils.js +++ b/packages/react-dev-utils/WebpackDevServerUtils.js @@ -103,6 +103,7 @@ function printInstructions(appName, urls, useYarn) { function createCompiler({ appName, + appPath, config, devSocket, urls, @@ -209,7 +210,8 @@ function createCompiler({ } } - const messages = formatWebpackMessages(statsData); + const filePathToExclude = appPath.replace(/\\/g, '/'); + const messages = formatWebpackMessages(statsData, filePathToExclude); const isSuccessful = !messages.errors.length && !messages.warnings.length; if (isSuccessful) { console.log(chalk.green('Compiled successfully!')); diff --git a/packages/react-dev-utils/formatWebpackMessages.js b/packages/react-dev-utils/formatWebpackMessages.js index 4b0f44acb74..62df732ce66 100644 --- a/packages/react-dev-utils/formatWebpackMessages.js +++ b/packages/react-dev-utils/formatWebpackMessages.js @@ -16,7 +16,7 @@ function isLikelyASyntaxError(message) { // Cleans up webpack error messages. // eslint-disable-next-line no-unused-vars -function formatMessage(message, isError) { +function formatMessage(message, filePathToExclude) { let lines = message.split('\n'); // Strip Webpack-added headers off errors/warnings @@ -65,7 +65,9 @@ function formatMessage(message, isError) { lines.splice(1, 1); } // Clean up file name - lines[0] = lines[0].replace(/^(.*) \d+:\d+-\d+$/, '$1'); + lines[0] = lines[0] + .replace(/^(.*) \d+:\d+-\d+$/, '$1') + .replace(filePathToExclude, ''); // Cleans up verbose "module not found" messages for files and packages. if (lines[1] && lines[1].indexOf('Module not found: ') === 0) { @@ -109,13 +111,13 @@ function formatMessage(message, isError) { return message.trim(); } -function formatWebpackMessages(json) { - const formattedErrors = json.errors.map(function(message) { - return formatMessage(message, true); - }); - const formattedWarnings = json.warnings.map(function(message) { - return formatMessage(message, false); - }); +function formatWebpackMessages(json, filePathToExclude) { + const formattedErrors = json.errors.map(message => + formatMessage(message, filePathToExclude) + ); + const formattedWarnings = json.warnings.map(message => + formatMessage(message, filePathToExclude) + ); const result = { errors: formattedErrors, warnings: formattedWarnings }; if (result.errors.some(isLikelyASyntaxError)) { // If there are any syntax errors, show just them. diff --git a/packages/react-dev-utils/typescriptFormatter.js b/packages/react-dev-utils/typescriptFormatter.js index 3a33b37a427..4e6c7102ea9 100644 --- a/packages/react-dev-utils/typescriptFormatter.js +++ b/packages/react-dev-utils/typescriptFormatter.js @@ -12,51 +12,68 @@ const codeFrame = require('@babel/code-frame').codeFrameColumns; const chalk = require('chalk'); const fs = require('fs'); -function formatter(message, useColors) { - const hasGetters = typeof message.getFile === 'function'; - const colors = new chalk.constructor({ enabled: useColors }); - const messageColor = message.isWarningSeverity() ? colors.yellow : colors.red; - - let source; - - if (hasGetters) { - source = - message.getFile() && - fs.existsSync(message.getFile()) && - fs.readFileSync(message.getFile(), 'utf-8'); - } else { - source = - message.file && - fs.existsSync(message.file) && - fs.readFileSync(message.file, 'utf-8'); - } - - let frame = ''; - - if (source) { - frame = codeFrame( - source, - { start: { line: message.line, column: message.character } }, - { highlightCode: useColors } - ) - .split('\n') - .map(str => ' ' + str) - .join(os.EOL); - } - - const severity = hasGetters ? message.getSeverity() : message.severity; - const types = { diagnostic: 'TypeScript', lint: 'TSLint' }; - - return [ - messageColor.bold(`${types[message.type]} ${severity.toLowerCase()}: `) + +function makeFormatter(appPath) { + const pathToExclude = appPath + '/'; + return function formatter(message, useColors) { + const hasGetters = typeof message.getFile === 'function'; + const colors = new chalk.constructor({ enabled: useColors }); + const messageColor = message.isWarningSeverity() + ? colors.yellow + : colors.red; + const fileAndNumberColor = colors.bold.cyan; + + let source; + + if (hasGetters) { + source = + message.getFile() && + fs.existsSync(message.getFile()) && + fs.readFileSync(message.getFile(), 'utf-8'); + } else { + source = + message.file && + fs.existsSync(message.file) && + fs.readFileSync(message.file, 'utf-8'); + } + + let frame = ''; + + if (source) { + frame = codeFrame( + source, + { start: { line: message.line, column: message.character } }, + { highlightCode: useColors } + ) + .split('\n') + .map(str => ' ' + str) + .join(os.EOL); + } + + const severity = hasGetters ? message.getSeverity() : message.severity; + const types = { diagnostic: 'TypeScript', lint: 'TSLint' }; + + return [ + messageColor.bold( + `${types[message.type]} ${severity.toLowerCase()} in ` + ) + + fileAndNumberColor( + `${message + .getFile() + .replace( + pathToExclude, + '' + )}(${message.getLine()},${message.getCharacter()})` + ) + + messageColor(':'), (hasGetters ? message.getContent() : message.content) + - ' ' + - messageColor.underline( - (message.type === 'lint' ? 'Rule: ' : 'TS') + message.code - ), - '', - frame, - ].join(os.EOL); + ' ' + + messageColor.underline( + (message.type === 'lint' ? 'Rule: ' : 'TS') + message.code + ), + '', + frame, + ].join(os.EOL); + }; } -module.exports = formatter; +module.exports = makeFormatter; diff --git a/packages/react-dev-utils/webpackHotDevClient.js b/packages/react-dev-utils/webpackHotDevClient.js index 050ce2a6351..73304714e13 100644 --- a/packages/react-dev-utils/webpackHotDevClient.js +++ b/packages/react-dev-utils/webpackHotDevClient.js @@ -121,10 +121,13 @@ function handleWarnings(warnings) { function printWarnings() { // Print warnings to the console. - var formatted = formatWebpackMessages({ - warnings: warnings, - errors: [], - }); + var formatted = formatWebpackMessages( + { + warnings: warnings, + errors: [], + }, + process.cwd() + ); if (typeof console !== 'undefined' && typeof console.warn === 'function') { for (var i = 0; i < formatted.warnings.length; i++) { @@ -160,10 +163,13 @@ function handleErrors(errors) { hasCompileErrors = true; // "Massage" webpack messages. - var formatted = formatWebpackMessages({ - errors: errors, - warnings: [], - }); + var formatted = formatWebpackMessages( + { + errors: errors, + warnings: [], + }, + process.cwd() + ); // Only show the first error. ErrorOverlay.reportBuildError(formatted.errors[0]); diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index 35bce798ed3..a5c5f72ece8 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -102,9 +102,11 @@ checkBrowsers(paths.appPath, isInteractive) errors: errors => devServer.sockWrite(devServer.sockets, 'errors', errors), }; + const appPath = paths.appPath.replace(/\\/g, '/'); // Create a webpack compiler that is configured with custom messages. const compiler = createCompiler({ appName, + appPath, config, devSocket, urls, From 5b22720db7e775dbe992ca5d19b9881f3b7b2947 Mon Sep 17 00:00:00 2001 From: John Reilly Date: Sun, 24 Feb 2019 08:12:36 +0000 Subject: [PATCH 2/4] formatter fixes --- .../react-dev-utils/WebpackDevServerUtils.js | 3 +- .../react-dev-utils/typescriptFormatter.js | 74 ++++++++----------- .../react-scripts/config/webpack.config.js | 4 +- 3 files changed, 36 insertions(+), 45 deletions(-) diff --git a/packages/react-dev-utils/WebpackDevServerUtils.js b/packages/react-dev-utils/WebpackDevServerUtils.js index 154333a0ff9..f070cb23dc7 100644 --- a/packages/react-dev-utils/WebpackDevServerUtils.js +++ b/packages/react-dev-utils/WebpackDevServerUtils.js @@ -146,12 +146,13 @@ function createCompiler({ }); }); + const formatter = typescriptFormatter(appPath.replace(/\\/g, '/')); forkTsCheckerWebpackPlugin .getCompilerHooks(compiler) .receive.tap('afterTypeScriptCheck', (diagnostics, lints) => { const allMsgs = [...diagnostics, ...lints]; const format = message => - `${message.file}\n${typescriptFormatter(message, true)}`; + `${message.file}\n${formatter(message, true)}`; tsMessagesResolver({ errors: allMsgs.filter(msg => msg.severity === 'error').map(format), diff --git a/packages/react-dev-utils/typescriptFormatter.js b/packages/react-dev-utils/typescriptFormatter.js index 4e6c7102ea9..76f9d0c01c1 100644 --- a/packages/react-dev-utils/typescriptFormatter.js +++ b/packages/react-dev-utils/typescriptFormatter.js @@ -14,62 +14,50 @@ const fs = require('fs'); function makeFormatter(appPath) { const pathToExclude = appPath + '/'; + const types = { diagnostic: 'TypeScript', lint: 'TSLint' }; + return function formatter(message, useColors) { - const hasGetters = typeof message.getFile === 'function'; + const { type, severity, file, line, content, code, character } = + typeof message.getFile === 'function' + ? { + type: message.getType(), + severity: message.getSeverity(), + file: message.getFile(), + line: message.getLine(), + content: message.getContent(), + code: message.getCode(), + character: message.getCharacter(), + } + : message; + const colors = new chalk.constructor({ enabled: useColors }); const messageColor = message.isWarningSeverity() ? colors.yellow : colors.red; const fileAndNumberColor = colors.bold.cyan; - let source; - - if (hasGetters) { - source = - message.getFile() && - fs.existsSync(message.getFile()) && - fs.readFileSync(message.getFile(), 'utf-8'); - } else { - source = - message.file && - fs.existsSync(message.file) && - fs.readFileSync(message.file, 'utf-8'); - } - - let frame = ''; - - if (source) { - frame = codeFrame( - source, - { start: { line: message.line, column: message.character } }, - { highlightCode: useColors } - ) - .split('\n') - .map(str => ' ' + str) - .join(os.EOL); - } - - const severity = hasGetters ? message.getSeverity() : message.severity; - const types = { diagnostic: 'TypeScript', lint: 'TSLint' }; + const source = + file && fs.existsSync(file) && fs.readFileSync(file, 'utf-8'); + const frame = source + ? codeFrame( + source, + { start: { line: line, column: character } }, + { highlightCode: useColors } + ) + .split('\n') + .map(str => ' ' + str) + .join(os.EOL) + : ''; return [ - messageColor.bold( - `${types[message.type]} ${severity.toLowerCase()} in ` - ) + + messageColor.bold(`${types[type]} ${severity.toLowerCase()} in `) + fileAndNumberColor( - `${message - .getFile() - .replace( - pathToExclude, - '' - )}(${message.getLine()},${message.getCharacter()})` + `${file.replace(pathToExclude, '')}(${line},${character})` ) + messageColor(':'), - (hasGetters ? message.getContent() : message.content) + + content + ' ' + - messageColor.underline( - (message.type === 'lint' ? 'Rule: ' : 'TS') + message.code - ), + messageColor.underline((type === 'lint' ? 'Rule: ' : 'TS') + code), '', frame, ].join(os.EOL); diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index f6c0e7a237a..4f8435f7320 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -632,7 +632,9 @@ module.exports = function(webpackEnv) { watch: paths.appSrc, silent: true, // The formatter is invoked directly in WebpackDevServerUtils during development - formatter: isEnvProduction ? typescriptFormatter : undefined, + formatter: isEnvProduction + ? typescriptFormatter(paths.appPath.replace(/\\/g, '/')) + : undefined, }), ].filter(Boolean), // Some libraries import Node modules but don't use them in the browser. From c3b63ba98aca5db7ac7232f06eea5a086755de5a Mon Sep 17 00:00:00 2001 From: John Reilly Date: Sun, 24 Feb 2019 19:01:06 +0000 Subject: [PATCH 3/4] fix missing colon in path --- packages/react-dev-utils/WebpackDevServerUtils.js | 4 ++-- packages/react-dev-utils/formatWebpackMessages.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-dev-utils/WebpackDevServerUtils.js b/packages/react-dev-utils/WebpackDevServerUtils.js index f070cb23dc7..759bd57b980 100644 --- a/packages/react-dev-utils/WebpackDevServerUtils.js +++ b/packages/react-dev-utils/WebpackDevServerUtils.js @@ -230,14 +230,14 @@ function createCompiler({ messages.errors.length = 1; } console.log(chalk.red('Failed to compile.\n')); - console.log(messages.errors.join('\n\n')); + console.log(messages.errors.join('\n\n').replace('//', '')); return; } // Show warnings if no errors were found. if (messages.warnings.length) { console.log(chalk.yellow('Compiled with warnings.\n')); - console.log(messages.warnings.join('\n\n')); + console.log(messages.warnings.join('\n\n').replace('//', '')); // Teach some ESLint tricks. console.log( diff --git a/packages/react-dev-utils/formatWebpackMessages.js b/packages/react-dev-utils/formatWebpackMessages.js index 62df732ce66..63f842eb474 100644 --- a/packages/react-dev-utils/formatWebpackMessages.js +++ b/packages/react-dev-utils/formatWebpackMessages.js @@ -67,7 +67,7 @@ function formatMessage(message, filePathToExclude) { // Clean up file name lines[0] = lines[0] .replace(/^(.*) \d+:\d+-\d+$/, '$1') - .replace(filePathToExclude, ''); + .replace(filePathToExclude, '/'); // Cleans up verbose "module not found" messages for files and packages. if (lines[1] && lines[1].indexOf('Module not found: ') === 0) { From 32b13414ea32c7946594d3394a28fd2e9290005f Mon Sep 17 00:00:00 2001 From: John Reilly Date: Sun, 10 Mar 2019 09:22:30 +0000 Subject: [PATCH 4/4] revert path tweaking amends as per discussion with @ianschmitz --- packages/react-dev-utils/README.md | 3 +- .../react-dev-utils/WebpackDevServerUtils.js | 11 +-- .../react-dev-utils/formatWebpackMessages.js | 20 ++-- .../react-dev-utils/typescriptFormatter.js | 94 +++++++++---------- .../react-dev-utils/webpackHotDevClient.js | 22 ++--- .../react-scripts/config/webpack.config.js | 4 +- packages/react-scripts/scripts/start.js | 2 - 7 files changed, 66 insertions(+), 90 deletions(-) diff --git a/packages/react-dev-utils/README.md b/packages/react-dev-utils/README.md index 0e4dfb277a7..d89dc95f667 100644 --- a/packages/react-dev-utils/README.md +++ b/packages/react-dev-utils/README.md @@ -220,7 +220,7 @@ measureFileSizesBeforeBuild(buildFolder).then(previousFileSizes => { }); ``` -#### `formatWebpackMessages({errors: Array, warnings: Array}): {errors: Array, warnings: Array}, filePathToExclude: string)` +#### `formatWebpackMessages({errors: Array, warnings: Array}): {errors: Array, warnings: Array}` Extracts and prettifies warning and error messages from webpack [stats](https://github.com/webpack/docs/wiki/node.js-api#stats) object. @@ -332,7 +332,6 @@ Creates a Webpack compiler instance for WebpackDevServer with built-in helpful m The `args` object accepts a number of properties: - **appName** `string`: The name that will be printed to the terminal. -- **appPath** `string`: The path to the application. Used to make error / warning paths pithier. - **config** `Object`: The webpack configuration options to be provided to the webpack constructor. - **devSocket** `Object`: Required if `useTypeScript` is `true`. This object should include `errors` and `warnings` which are functions accepting an array of errors or warnings emitted by the type checking. This is useful when running `fork-ts-checker-webpack-plugin` with `async: true` to report errors that are emitted after the webpack build is complete. - **urls** `Object`: To provide the `urls` argument, use `prepareUrls()` described below. diff --git a/packages/react-dev-utils/WebpackDevServerUtils.js b/packages/react-dev-utils/WebpackDevServerUtils.js index 759bd57b980..1d7021e037c 100644 --- a/packages/react-dev-utils/WebpackDevServerUtils.js +++ b/packages/react-dev-utils/WebpackDevServerUtils.js @@ -103,7 +103,6 @@ function printInstructions(appName, urls, useYarn) { function createCompiler({ appName, - appPath, config, devSocket, urls, @@ -146,13 +145,12 @@ function createCompiler({ }); }); - const formatter = typescriptFormatter(appPath.replace(/\\/g, '/')); forkTsCheckerWebpackPlugin .getCompilerHooks(compiler) .receive.tap('afterTypeScriptCheck', (diagnostics, lints) => { const allMsgs = [...diagnostics, ...lints]; const format = message => - `${message.file}\n${formatter(message, true)}`; + `${message.file}\n${typescriptFormatter(message, true)}`; tsMessagesResolver({ errors: allMsgs.filter(msg => msg.severity === 'error').map(format), @@ -211,8 +209,7 @@ function createCompiler({ } } - const filePathToExclude = appPath.replace(/\\/g, '/'); - const messages = formatWebpackMessages(statsData, filePathToExclude); + const messages = formatWebpackMessages(statsData); const isSuccessful = !messages.errors.length && !messages.warnings.length; if (isSuccessful) { console.log(chalk.green('Compiled successfully!')); @@ -230,14 +227,14 @@ function createCompiler({ messages.errors.length = 1; } console.log(chalk.red('Failed to compile.\n')); - console.log(messages.errors.join('\n\n').replace('//', '')); + console.log(messages.errors.join('\n\n')); return; } // Show warnings if no errors were found. if (messages.warnings.length) { console.log(chalk.yellow('Compiled with warnings.\n')); - console.log(messages.warnings.join('\n\n').replace('//', '')); + console.log(messages.warnings.join('\n\n')); // Teach some ESLint tricks. console.log( diff --git a/packages/react-dev-utils/formatWebpackMessages.js b/packages/react-dev-utils/formatWebpackMessages.js index 63f842eb474..799c92be2c4 100644 --- a/packages/react-dev-utils/formatWebpackMessages.js +++ b/packages/react-dev-utils/formatWebpackMessages.js @@ -16,7 +16,7 @@ function isLikelyASyntaxError(message) { // Cleans up webpack error messages. // eslint-disable-next-line no-unused-vars -function formatMessage(message, filePathToExclude) { +function formatMessage(message) { let lines = message.split('\n'); // Strip Webpack-added headers off errors/warnings @@ -65,9 +65,7 @@ function formatMessage(message, filePathToExclude) { lines.splice(1, 1); } // Clean up file name - lines[0] = lines[0] - .replace(/^(.*) \d+:\d+-\d+$/, '$1') - .replace(filePathToExclude, '/'); + lines[0] = lines[0].replace(/^(.*) \d+:\d+-\d+$/, '$1'); // Cleans up verbose "module not found" messages for files and packages. if (lines[1] && lines[1].indexOf('Module not found: ') === 0) { @@ -111,13 +109,13 @@ function formatMessage(message, filePathToExclude) { return message.trim(); } -function formatWebpackMessages(json, filePathToExclude) { - const formattedErrors = json.errors.map(message => - formatMessage(message, filePathToExclude) - ); - const formattedWarnings = json.warnings.map(message => - formatMessage(message, filePathToExclude) - ); +function formatWebpackMessages(json) { + const formattedErrors = json.errors.map(function(message) { + return formatMessage(message, true); + }); + const formattedWarnings = json.warnings.map(function(message) { + return formatMessage(message, false); + }); const result = { errors: formattedErrors, warnings: formattedWarnings }; if (result.errors.some(isLikelyASyntaxError)) { // If there are any syntax errors, show just them. diff --git a/packages/react-dev-utils/typescriptFormatter.js b/packages/react-dev-utils/typescriptFormatter.js index 76f9d0c01c1..dc2f85d2e3e 100644 --- a/packages/react-dev-utils/typescriptFormatter.js +++ b/packages/react-dev-utils/typescriptFormatter.js @@ -12,56 +12,48 @@ const codeFrame = require('@babel/code-frame').codeFrameColumns; const chalk = require('chalk'); const fs = require('fs'); -function makeFormatter(appPath) { - const pathToExclude = appPath + '/'; - const types = { diagnostic: 'TypeScript', lint: 'TSLint' }; - - return function formatter(message, useColors) { - const { type, severity, file, line, content, code, character } = - typeof message.getFile === 'function' - ? { - type: message.getType(), - severity: message.getSeverity(), - file: message.getFile(), - line: message.getLine(), - content: message.getContent(), - code: message.getCode(), - character: message.getCharacter(), - } - : message; - - const colors = new chalk.constructor({ enabled: useColors }); - const messageColor = message.isWarningSeverity() - ? colors.yellow - : colors.red; - const fileAndNumberColor = colors.bold.cyan; - - const source = - file && fs.existsSync(file) && fs.readFileSync(file, 'utf-8'); - const frame = source - ? codeFrame( - source, - { start: { line: line, column: character } }, - { highlightCode: useColors } - ) - .split('\n') - .map(str => ' ' + str) - .join(os.EOL) - : ''; - - return [ - messageColor.bold(`${types[type]} ${severity.toLowerCase()} in `) + - fileAndNumberColor( - `${file.replace(pathToExclude, '')}(${line},${character})` - ) + - messageColor(':'), - content + - ' ' + - messageColor.underline((type === 'lint' ? 'Rule: ' : 'TS') + code), - '', - frame, - ].join(os.EOL); - }; +const types = { diagnostic: 'TypeScript', lint: 'TSLint' }; + +function formatter(message, useColors) { + const { type, severity, file, line, content, code, character } = + typeof message.getFile === 'function' + ? { + type: message.getType(), + severity: message.getSeverity(), + file: message.getFile(), + line: message.getLine(), + content: message.getContent(), + code: message.getCode(), + character: message.getCharacter(), + } + : message; + + const colors = new chalk.constructor({ enabled: useColors }); + const messageColor = message.isWarningSeverity() ? colors.yellow : colors.red; + const fileAndNumberColor = colors.bold.cyan; + + const source = file && fs.existsSync(file) && fs.readFileSync(file, 'utf-8'); + const frame = source + ? codeFrame( + source, + { start: { line: line, column: character } }, + { highlightCode: useColors } + ) + .split('\n') + .map(str => ' ' + str) + .join(os.EOL) + : ''; + + return [ + messageColor.bold(`${types[type]} ${severity.toLowerCase()} in `) + + fileAndNumberColor(`${file}(${line},${character})`) + + messageColor(':'), + content + + ' ' + + messageColor.underline((type === 'lint' ? 'Rule: ' : 'TS') + code), + '', + frame, + ].join(os.EOL); } -module.exports = makeFormatter; +module.exports = formatter; diff --git a/packages/react-dev-utils/webpackHotDevClient.js b/packages/react-dev-utils/webpackHotDevClient.js index 73304714e13..050ce2a6351 100644 --- a/packages/react-dev-utils/webpackHotDevClient.js +++ b/packages/react-dev-utils/webpackHotDevClient.js @@ -121,13 +121,10 @@ function handleWarnings(warnings) { function printWarnings() { // Print warnings to the console. - var formatted = formatWebpackMessages( - { - warnings: warnings, - errors: [], - }, - process.cwd() - ); + var formatted = formatWebpackMessages({ + warnings: warnings, + errors: [], + }); if (typeof console !== 'undefined' && typeof console.warn === 'function') { for (var i = 0; i < formatted.warnings.length; i++) { @@ -163,13 +160,10 @@ function handleErrors(errors) { hasCompileErrors = true; // "Massage" webpack messages. - var formatted = formatWebpackMessages( - { - errors: errors, - warnings: [], - }, - process.cwd() - ); + var formatted = formatWebpackMessages({ + errors: errors, + warnings: [], + }); // Only show the first error. ErrorOverlay.reportBuildError(formatted.errors[0]); diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 4f8435f7320..f6c0e7a237a 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -632,9 +632,7 @@ module.exports = function(webpackEnv) { watch: paths.appSrc, silent: true, // The formatter is invoked directly in WebpackDevServerUtils during development - formatter: isEnvProduction - ? typescriptFormatter(paths.appPath.replace(/\\/g, '/')) - : undefined, + formatter: isEnvProduction ? typescriptFormatter : undefined, }), ].filter(Boolean), // Some libraries import Node modules but don't use them in the browser. diff --git a/packages/react-scripts/scripts/start.js b/packages/react-scripts/scripts/start.js index a5c5f72ece8..35bce798ed3 100644 --- a/packages/react-scripts/scripts/start.js +++ b/packages/react-scripts/scripts/start.js @@ -102,11 +102,9 @@ checkBrowsers(paths.appPath, isInteractive) errors: errors => devServer.sockWrite(devServer.sockets, 'errors', errors), }; - const appPath = paths.appPath.replace(/\\/g, '/'); // Create a webpack compiler that is configured with custom messages. const compiler = createCompiler({ appName, - appPath, config, devSocket, urls,