formatWebpackMessage.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. const friendlySyntaxErrorLabel = 'Syntax error:';
  2. function isLikelyASyntaxError(message: string) {
  3. return message.indexOf(friendlySyntaxErrorLabel) !== -1;
  4. }
  5. type MessageType = string | Record<string, string>[] | Record<string, string>;
  6. function formatMessage(msg: MessageType) {
  7. let lines: string[] = [];
  8. if (typeof msg === 'string') {
  9. lines = msg.split('\n');
  10. } else if ('message' in msg) {
  11. lines = msg['message'].split('\n');
  12. } else if (Array.isArray(msg)) {
  13. msg.forEach(function(message) {
  14. if ('message' in message) {
  15. lines = message['message'].split('\n');
  16. }
  17. });
  18. }
  19. lines = lines.filter(line => !/Module [A-z ]+\(from/.test(line));
  20. lines = lines.map(function(line) {
  21. const parsingError = /Line (\d+):(?:(\d+):)?\s*Parsing error: (.+)$/.exec(
  22. line,
  23. );
  24. if (!parsingError) {
  25. return line;
  26. }
  27. const [, errorLine, errorColumn, errorMessage] = parsingError;
  28. // eslint-disable-next-line max-len
  29. return `${friendlySyntaxErrorLabel} ${errorMessage} (${errorLine}:${errorColumn})`;
  30. });
  31. let message = lines.join('\n');
  32. // Smoosh syntax errors (commonly found in CSS)
  33. message = message.replace(
  34. /SyntaxError\s+\((\d+):(\d+)\)\s*(.+?)\n/g,
  35. `${friendlySyntaxErrorLabel} $3 ($1:$2)\n`,
  36. );
  37. // Clean up export errors
  38. message = message.replace(
  39. /^.*export '(.+?)' was not found in '(.+?)'.*$/gm,
  40. 'Attempted import error: \'$1\' is not exported from \'$2\'.',
  41. );
  42. message = message.replace(
  43. /^.*export 'default' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm,
  44. 'Attempted import error: \'$2\' does not contain a default export (imported as \'$1\').',
  45. );
  46. message = message.replace(
  47. /^.*export '(.+?)' \(imported as '(.+?)'\) was not found in '(.+?)'.*$/gm,
  48. 'Attempted import error: \'$1\' is not exported from \'$3\' (imported as \'$2\').',
  49. );
  50. lines = message.split('\n');
  51. if (lines.length > 2 && lines[1].trim() === '') {
  52. lines.splice(1, 1);
  53. }
  54. lines[0] = lines[0].replace(/^(.*) \d+:\d+-\d+$/, '$1');
  55. if (lines[1] && lines[1].indexOf('Module not found: ') === 0) {
  56. lines = [
  57. lines[0],
  58. lines[1]
  59. .replace('Error: ', '')
  60. .replace('Module not found: Cannot find file:', 'Cannot find file:'),
  61. ];
  62. }
  63. if (lines[1] && lines[1].match(/Cannot find module.+sass/)) {
  64. lines[1] = 'To import Sass files, you first need to install sass.\n';
  65. lines[1]
  66. += 'Run `npm install sass` or `yarn add sass` inside your workspace.';
  67. }
  68. message = lines.join('\n');
  69. message = message.replace(
  70. /^\s*at\s((?!webpack:).)*:\d+:\d+[\s)]*(\n|$)/gm,
  71. '',
  72. ); // at ... ...:x:y
  73. message = message.replace(/^\s*at\s<anonymous>(\n|$)/gm, '');
  74. lines = message.split('\n');
  75. lines = lines.filter(function(line, index, arr) {
  76. return (
  77. index === 0 || line.trim() !== '' || line.trim() !== arr[index - 1].trim()
  78. );
  79. });
  80. message = lines.join('\n');
  81. return message.trim();
  82. }
  83. function formatWebpackMessages(json: {
  84. errors: MessageType[];
  85. warnings: MessageType[];
  86. }) {
  87. const formattedErrors = json.errors.map(formatMessage);
  88. const formattedWarnings = json.warnings.map(formatMessage);
  89. const result = {errors: formattedErrors, warnings: formattedWarnings};
  90. if (result.errors.some(isLikelyASyntaxError)) {
  91. result.errors = result.errors.filter(isLikelyASyntaxError);
  92. }
  93. return result;
  94. }
  95. export default formatWebpackMessages;