From d6c31a17a0dde3e2bcf2b5e55f913c3645d32868 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Wed, 10 Apr 2024 18:11:59 +0300 Subject: [PATCH 1/2] fix: automatically rename class `default` to `_default` when named export is enabled (#1590) --- README.md | 8 ++- src/utils.js | 6 +- .../__snapshots__/modules-option.test.js.snap | 68 +++++++++++++++++++ test/fixtures/modules/issue-1589/source.css | 3 + test/fixtures/modules/issue-1589/source.js | 5 ++ test/modules-option.test.js | 35 ++++++++++ 6 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/modules/issue-1589/source.css create mode 100644 test/fixtures/modules/issue-1589/source.js diff --git a/README.md b/README.md index 4c8b8bbe..c9e1f447 100644 --- a/README.md +++ b/README.md @@ -1156,7 +1156,7 @@ Enables/disables ES modules named export for locals. > **Warning** > -> It is not allowed to use the `default` reserved word in css classes. +> Because it is not allowed to use the `default` class in CSS when the `namedExport` is `true` (since ECMA modules have a reserved keyword `default` for default export), it will be automatically renamed to the `_default` class. **styles.css** @@ -1167,6 +1167,9 @@ Enables/disables ES modules named export for locals. .bar { color: blue; } +.default { + color: green; +} ``` **index.js** @@ -1179,6 +1182,9 @@ console.log(styles["foo-baz"], styles.bar); // If using `exportLocalsConvention: "camel-case-only"`: console.log(styles.fooBaz, styles.bar); + +// For the `default` classname +console.log(styles["_default"]); ``` You can enable a ES module named export using: diff --git a/src/utils.js b/src/utils.js index 57adc01c..0ccc6dbd 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1184,12 +1184,16 @@ function getExportCode( ? new Set(names) : new Set([names]); - for (const name of normalizedNames) { + for (let name of normalizedNames) { const serializedValue = isTemplateLiteralSupported ? convertToTemplateLiteral(value) : JSON.stringify(value); if (options.modules.namedExport) { + if (name === "default") { + name = `_${name}`; + } + if (!validIdentifier.test(name) || keywords.has(name)) { identifierId += 1; diff --git a/test/__snapshots__/modules-option.test.js.snap b/test/__snapshots__/modules-option.test.js.snap index 8300e020..37c78af1 100644 --- a/test/__snapshots__/modules-option.test.js.snap +++ b/test/__snapshots__/modules-option.test.js.snap @@ -12317,6 +12317,74 @@ exports[`"modules" option should work with \`@scope\` at-rule: result 1`] = ` exports[`"modules" option should work with \`@scope\` at-rule: warnings 1`] = `[]`; +exports[`"modules" option should work with \`default\` class and with named export: errors 1`] = `[]`; + +exports[`"modules" option should work with \`default\` class and with named export: module 1`] = ` +"// Imports +import ___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___ from "../../../../src/runtime/noSourceMaps.js"; +import ___CSS_LOADER_API_IMPORT___ from "../../../../src/runtime/api.js"; +var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___); +// Module +___CSS_LOADER_EXPORT___.push([module.id, \`.VP7CYSvMVRONwmJxbckO { + background: red +} +\`, ""]); +// Exports +export var _default = \`VP7CYSvMVRONwmJxbckO\`; +export default ___CSS_LOADER_EXPORT___; +" +`; + +exports[`"modules" option should work with \`default\` class and with named export: result 1`] = ` +[ + [ + "./modules/issue-1589/source.css", + ".VP7CYSvMVRONwmJxbckO { + background: red +} +", + "", + ], +] +`; + +exports[`"modules" option should work with \`default\` class and with named export: warnings 1`] = `[]`; + +exports[`"modules" option should work with \`default\` class and without named export: errors 1`] = `[]`; + +exports[`"modules" option should work with \`default\` class and without named export: module 1`] = ` +"// Imports +import ___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___ from "../../../../src/runtime/noSourceMaps.js"; +import ___CSS_LOADER_API_IMPORT___ from "../../../../src/runtime/api.js"; +var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___); +// Module +___CSS_LOADER_EXPORT___.push([module.id, \`.VP7CYSvMVRONwmJxbckO { + background: red +} +\`, ""]); +// Exports +___CSS_LOADER_EXPORT___.locals = { + "default": \`VP7CYSvMVRONwmJxbckO\` +}; +export default ___CSS_LOADER_EXPORT___; +" +`; + +exports[`"modules" option should work with \`default\` class and without named export: result 1`] = ` +[ + [ + "./modules/issue-1589/source.css", + ".VP7CYSvMVRONwmJxbckO { + background: red +} +", + "", + ], +] +`; + +exports[`"modules" option should work with \`default\` class and without named export: warnings 1`] = `[]`; + exports[`"modules" option should work with CSS nesting: errors 1`] = `[]`; exports[`"modules" option should work with CSS nesting: module 1`] = ` diff --git a/test/fixtures/modules/issue-1589/source.css b/test/fixtures/modules/issue-1589/source.css new file mode 100644 index 00000000..14dab2de --- /dev/null +++ b/test/fixtures/modules/issue-1589/source.css @@ -0,0 +1,3 @@ +.default { + background: red +} diff --git a/test/fixtures/modules/issue-1589/source.js b/test/fixtures/modules/issue-1589/source.js new file mode 100644 index 00000000..9b8393fb --- /dev/null +++ b/test/fixtures/modules/issue-1589/source.js @@ -0,0 +1,5 @@ +import * as css from './source.css'; + +__export__ = css.default; + +export default css; diff --git a/test/modules-option.test.js b/test/modules-option.test.js index c17f55dd..c2d190c9 100644 --- a/test/modules-option.test.js +++ b/test/modules-option.test.js @@ -2657,4 +2657,39 @@ describe('"modules" option', () => { expect(getWarnings(stats)).toMatchSnapshot("warnings"); expect(getErrors(stats)).toMatchSnapshot("errors"); }); + + it("should work with `default` class and without named export", async () => { + const compiler = getCompiler("./modules/issue-1589/source.js", { + modules: { + exportLocalsConvention: "as-is", + namedExport: false, + }, + }); + const stats = await compile(compiler); + + expect( + getModuleSource("./modules/issue-1589/source.css", stats), + ).toMatchSnapshot("module"); + expect(getExecutedCode("main.bundle.js", compiler, stats)).toMatchSnapshot( + "result", + ); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); + + it("should work with `default` class and with named export", async () => { + const compiler = getCompiler("./modules/issue-1589/source.js", { + modules: true, + }); + const stats = await compile(compiler); + + expect( + getModuleSource("./modules/issue-1589/source.css", stats), + ).toMatchSnapshot("module"); + expect(getExecutedCode("main.bundle.js", compiler, stats)).toMatchSnapshot( + "result", + ); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); }); From 5c717c986784f20307aaa66e46c8805b84f22cc8 Mon Sep 17 00:00:00 2001 From: "alexander.akait" Date: Wed, 10 Apr 2024 18:12:16 +0300 Subject: [PATCH 2/2] chore(release): 7.1.1 --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87f91b0b..4af76802 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [7.1.1](https://github.com/webpack-contrib/css-loader/compare/v7.1.0...v7.1.1) (2024-04-10) + + +### Bug Fixes + +* automatically rename class `default` to `_default` when named export is enabled ([#1590](https://github.com/webpack-contrib/css-loader/issues/1590)) ([d6c31a1](https://github.com/webpack-contrib/css-loader/commit/d6c31a17a0dde3e2bcf2b5e55f913c3645d32868)) + ## [7.1.0](https://github.com/webpack-contrib/css-loader/compare/v7.0.0...v7.1.0) (2024-04-08) diff --git a/package-lock.json b/package-lock.json index 9e429408..c09926ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "css-loader", - "version": "7.1.0", + "version": "7.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "css-loader", - "version": "7.1.0", + "version": "7.1.1", "license": "MIT", "dependencies": { "icss-utils": "^5.1.0", diff --git a/package.json b/package.json index de1f1be5..2cfbbf2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-loader", - "version": "7.1.0", + "version": "7.1.1", "description": "css loader module for webpack", "license": "MIT", "repository": "webpack-contrib/css-loader",