diff --git a/README.md b/README.md index 57b406bb..b4fc46eb 100644 --- a/README.md +++ b/README.md @@ -766,6 +766,9 @@ Style of exported classnames. By default, the exported JSON keys mirror the class names (i.e `asIs` value). +When `namedExport` is enabled, the `localsConvention` option is ignored. +Do not use these options together. + | Name | Type | Description | | :-------------------: | :--------: | :----------------------------------------------------------------------------------------------- | | **`'asIs'`** | `{String}` | Class names will be exported as is. | @@ -924,6 +927,9 @@ Default: `false` Enable/disable ES modules named export for css classes. Names of exported classes are converted to camelCase. +When `namedExport` is enabled, the `localsConvention` option is ignored. +Do not use these options together. + > i It is not allowed to use JavaScript reserved words in css class names **styles.css** diff --git a/src/index.js b/src/index.js index 37d489c7..76791d1a 100644 --- a/src/index.js +++ b/src/index.js @@ -42,6 +42,8 @@ export default function loader(content, map, meta) { const urlHandler = (url) => stringifyRequest(this, preRequester(options.importLoaders) + url); + const callback = this.async(); + const esModule = typeof options.esModule !== 'undefined' ? options.esModule : true; @@ -51,11 +53,27 @@ export default function loader(content, map, meta) { modulesOptions = getModulesOptions(options, this); if (modulesOptions.namedExport === true && esModule === false) { - this.emitError( + callback( new Error( '`Options.module.namedExport` cannot be used without `options.esModule`' ) ); + + return; + } + + if ( + modulesOptions.namedExport === true && + modulesOptions.localsConvention !== 'asIs' && + modulesOptions.localsConvention !== 'camelCaseOnly' + ) { + callback( + new Error( + 'When `namedExport` is enabled class names are always converted to camelCase. Remove the `localsConvention` option from the webpack.config or set it to `asIs` / `camelCaseOnly`' + ) + ); + + return; } plugins.push(...getModulesPlugins(modulesOptions, this)); @@ -128,8 +146,6 @@ export default function loader(content, map, meta) { } } - const callback = this.async(); - postcss(plugins) .process(content, { from: this.resourcePath, diff --git a/test/__snapshots__/esModule-option.test.js.snap b/test/__snapshots__/esModule-option.test.js.snap index d2b974dc..83babb08 100644 --- a/test/__snapshots__/esModule-option.test.js.snap +++ b/test/__snapshots__/esModule-option.test.js.snap @@ -11,11 +11,21 @@ exports[`"esModule" option should emit error when class has unsupported name: wa exports[`"esModule" option should emit error when namedExport true && esModule false: errors 1`] = ` Array [ - "ModuleError: Module Error (from \`replaced original path\`): -\`Options.module.namedExport\` cannot be used without \`options.esModule\`", + "ModuleBuildError: Module build failed (from \`replaced original path\`): +Error: \`Options.module.namedExport\` cannot be used without \`options.esModule\` + at Object.loader (/src/index.js:57:9)", ] `; +exports[`"esModule" option should emit error when namedExport true && localsConvention invalid: errors 1`] = ` +Array [ + "ModuleBuildError: Module build failed (from \`replaced original path\`): +Error: When \`namedExport\` is enabled class names are always converted to camelCase. Remove the \`localsConvention\` option from the webpack.config or set it to \`asIs\` / \`camelCaseOnly\`", +] +`; + +exports[`"esModule" option should emit error when namedExport true && localsConvention invalid: warnings 1`] = `Array []`; + exports[`"esModule" option should work js template with "namedExport" option: errors 1`] = `Array []`; exports[`"esModule" option should work js template with "namedExport" option: module 1`] = ` diff --git a/test/esModule-option.test.js b/test/esModule-option.test.js index 592fcab1..a5b07d14 100644 --- a/test/esModule-option.test.js +++ b/test/esModule-option.test.js @@ -321,4 +321,18 @@ describe('"esModule" option', () => { expect(getErrors(stats)).toMatchSnapshot('errors'); }); + + it('should emit error when namedExport true && localsConvention invalid', async () => { + const compiler = getCompiler('./es-module/named/broken/index.js', { + esModule: true, + modules: { + namedExport: true, + localsConvention: 'dashes', + }, + }); + const stats = await compile(compiler); + + expect(getWarnings(stats)).toMatchSnapshot('warnings'); + expect(getErrors(stats, true)).toMatchSnapshot('errors'); + }); });