diff --git a/packages/core/integration-tests/test/integration/postcss-modules-config-invalid/.postcssrc b/packages/core/integration-tests/test/integration/postcss-modules-config-invalid/.postcssrc new file mode 100644 index 00000000000..8fa6c61ff95 --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-modules-config-invalid/.postcssrc @@ -0,0 +1,7 @@ +{ + "plugins": { + "postcss-import": {}, + "postcss-url": {} + "postcss-custom-properties": {} + } +} diff --git a/packages/core/integration-tests/test/integration/postcss-modules-config-invalid/src/index.css b/packages/core/integration-tests/test/integration/postcss-modules-config-invalid/src/index.css new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/core/integration-tests/test/postcss.js b/packages/core/integration-tests/test/postcss.js index 07ebf71e3c4..a0dde2a4695 100644 --- a/packages/core/integration-tests/test/postcss.js +++ b/packages/core/integration-tests/test/postcss.js @@ -672,4 +672,50 @@ describe('postcss', () => { }, ); }); + + it('should throw an error with code frame when .postcssrc is invalid', async function () { + let configFilePath = path.join( + __dirname, + '/integration/postcss-modules-config-invalid/.postcssrc', + ); + let code = await inputFS.readFile(configFilePath, 'utf8'); + await assert.rejects( + () => + bundle( + path.join( + __dirname, + '/integration/postcss-modules-config-invalid/src/index.css', + ), + ), + { + name: 'BuildError', + diagnostics: [ + { + codeFrames: [ + { + code, + filePath: configFilePath, + language: 'json5', + codeHighlights: [ + { + end: { + column: 5, + line: 5, + }, + start: { + column: 5, + line: 5, + }, + message: `JSON5: invalid character '\\"' at 5:5`, + }, + ], + }, + ], + message: 'Failed to parse .postcssrc', + origin: '@parcel/utils', + }, + ], + }, + ); + }); }); diff --git a/packages/core/utils/src/config.js b/packages/core/utils/src/config.js index 33df8e8c8e4..3c0d7e73158 100644 --- a/packages/core/utils/src/config.js +++ b/packages/core/utils/src/config.js @@ -2,6 +2,7 @@ import type {ConfigResult, File, FilePath} from '@parcel/types'; import type {FileSystem} from '@parcel/fs'; +import ThrowableDiagnostic from '@parcel/diagnostic'; import path from 'path'; import clone from 'clone'; import {parse as json5} from 'json5'; @@ -88,7 +89,39 @@ export async function loadConfig( config = configContent; } else { let parse = opts?.parser ?? getParser(extname); - config = parse(configContent); + try { + config = parse(configContent); + } catch (e) { + if (extname !== '' && extname !== 'json') { + throw e; + } + + let pos = { + line: e.lineNumber, + column: e.columnNumber, + }; + + throw new ThrowableDiagnostic({ + diagnostic: { + message: `Failed to parse ${path.basename(configFile)}`, + origin: '@parcel/utils', + codeFrames: [ + { + language: 'json5', + filePath: configFile, + code: configContent, + codeHighlights: [ + { + start: pos, + end: pos, + message: e.message, + }, + ], + }, + ], + }, + }); + } } let output = {