Skip to content

Commit

Permalink
feat: added dashed variants for the exportLocalsConvention options
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Apr 4, 2024
1 parent a956101 commit 63fee36
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 55 deletions.
42 changes: 21 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,11 +320,11 @@ type modules =
namedExport: boolean;
exportGlobals: boolean;
exportLocalsConvention:
| "asIs"
| "camelCase"
| "camelCaseOnly"
| "as-is"
| "camel-case"
| "camel-case-only"
| "dashes"
| "dashesOnly"
| "dashes-only"
| ((name: string) => string);
exportOnlyLocals: boolean;
};
Expand Down Expand Up @@ -602,7 +602,7 @@ module.exports = {
localIdentContext: path.resolve(__dirname, "src"),
localIdentHashSalt: "my-custom-hash",
namedExport: true,
exportLocalsConvention: "camelCase",
exportLocalsConvention: "as-is",
exportOnlyLocals: false,
},
},
Expand Down Expand Up @@ -1152,7 +1152,7 @@ Enables/disables ES modules named export for locals.
> **Warning**
>
> It is not allowed to use JavaScript reserved words in css class names unless
> `exportLocalsConvention` is `"asIs"`.
> `exportLocalsConvention` is `"as-is"`.
**styles.css**

Expand All @@ -1171,7 +1171,7 @@ Enables/disables ES modules named export for locals.
import * as styles from "./styles.css";

console.log(styles.fooBaz, styles.bar);
// or if using `exportLocalsConvention: "asIs"`:
// or if using `exportLocalsConvention: "as-is"`:
console.log(styles["foo-baz"], styles.bar);
```

Expand Down Expand Up @@ -1239,29 +1239,29 @@ Type:

```ts
type exportLocalsConvention =
| "asIs"
| "camelCase"
| "camelCaseOnly"
| "as-is"
| "camel-case"
| "camel-case-only"
| "dashes"
| "dashesOnly"
| "dashes-only"
| ((name: string) => string);
```

Default: based on the `modules.namedExport` option value, if `true` - `camelCaseOnly`, otherwise `asIs`
Default: based on the `modules.namedExport` option value, if `true` - `camelCaseOnly`, otherwise `as-is`

Style of exported class names.

###### `string`

By default, the exported JSON keys mirror the class names (i.e `asIs` value).
By default, the exported JSON keys mirror the class names (i.e `as-is` value).

| Name | Type | Description |
| :-------------------: | :------: | :----------------------------------------------------------------------------------------------- |
| **`'asIs'`** | `string` | Class names will be exported as is. |
| **`'camelCase'`** | `string` | Class names will be camelized, the original class name will not to be removed from the locals |
| **`'camelCaseOnly'`** | `string` | Class names will be camelized, the original class name will be removed from the locals |
| **`'dashes'`** | `string` | Only dashes in class names will be camelized |
| **`'dashesOnly'`** | `string` | Dashes in class names will be camelized, the original class name will be removed from the locals |
| Name | Type | Description |
| :---------------------: | :------: | :----------------------------------------------------------------------------------------------- |
| **`'as-is'`** | `string` | Class names will be exported as is. |
| **`'camel-case'`** | `string` | Class names will be camelized, the original class name will not to be removed from the locals |
| **`'camel-case-only'`** | `string` | Class names will be camelized, the original class name will be removed from the locals |
| **`'dashes'`** | `string` | Only dashes in class names will be camelized |
| **`'dashes-only'`** | `string` | Dashes in class names will be camelized, the original class name will be removed from the locals |

**file.css**

Expand All @@ -1287,7 +1287,7 @@ module.exports = {
loader: "css-loader",
options: {
modules: {
exportLocalsConvention: "camelCase",
exportLocalsConvention: "camel-case",
},
},
},
Expand Down
6 changes: 5 additions & 1 deletion src/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,14 @@
{
"enum": [
"asIs",
"as-is",
"camelCase",
"camel-case",
"camelCaseOnly",
"camel-case-only",
"dashes",
"dashesOnly"
"dashesOnly",
"dashes-only"
]
},
{
Expand Down
19 changes: 14 additions & 5 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -527,8 +527,8 @@ function getModulesOptions(rawOptions, esModule, exportType, loaderContext) {
typeof rawModulesOptions.exportLocalsConvention !== "undefined"
? rawModulesOptions.exportLocalsConvention
: namedExport
? "asIs"
: "camelCaseOnly";
? "as-is"
: "camel-case-only";
const modulesOptions = {
auto,
mode: "local",
Expand All @@ -555,21 +555,27 @@ function getModulesOptions(rawOptions, esModule, exportType, loaderContext) {
if (typeof modulesOptions.exportLocalsConvention === "string") {
exportLocalsConventionType = modulesOptions.exportLocalsConvention;

modulesOptions.useExportsAs = exportLocalsConventionType === "asIs";
modulesOptions.useExportsAs =
exportLocalsConventionType === "as-is" ||
exportLocalsConventionType === "asIs";
modulesOptions.exportLocalsConvention = (name) => {
switch (exportLocalsConventionType) {
case "camel-case":
case "camelCase": {
return [name, camelCase(name)];
}
case "camel-case-only":
case "camelCaseOnly": {
return camelCase(name);
}
case "dashes": {
return [name, dashesCamelCase(name)];
}
case "dashes-only":
case "dashesOnly": {
return dashesCamelCase(name);
}
case "as-is":
case "asIs":
default:
return name;
Expand Down Expand Up @@ -644,11 +650,14 @@ function getModulesOptions(rawOptions, esModule, exportType, loaderContext) {
if (
typeof exportLocalsConventionType === "string" &&
exportLocalsConventionType !== "asIs" &&
exportLocalsConventionType !== "as-is" &&
exportLocalsConventionType !== "camelCaseOnly" &&
exportLocalsConventionType !== "dashesOnly"
exportLocalsConventionType !== "camel-case-only" &&
exportLocalsConventionType !== "dashesOnly" &&
exportLocalsConventionType !== "dashes-only"
) {
throw new Error(
'The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "asIs", "camelCaseOnly" or "dashesOnly"',
'The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "as-is", "camel-case-only" or "dashes-only"',
);
}
}
Expand Down
42 changes: 20 additions & 22 deletions test/__snapshots__/modules-option.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2552,7 +2552,7 @@ exports[`"modules" option should throw an error when class has unsupported name
exports[`"modules" option should throw an error when the "namedExport" is enabled and the "exportLocalsConvention" options has not "camelCaseOnly" value: errors 1`] = `
[
"ModuleBuildError: Module build failed (from \`replaced original path\`):
Error: The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "asIs", "camelCaseOnly" or "dashesOnly"",
Error: The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "as-is", "camel-case-only" or "dashes-only"",
]
`;

Expand All @@ -2579,7 +2579,7 @@ exports[`"modules" option should throw error when the "exportLocalsConvention" f
exports[`"modules" option should throw error with composes when the "namedExport" is enabled and "exportLocalsConvention" options has invalid value: errors 1`] = `
[
"ModuleBuildError: Module build failed (from \`replaced original path\`):
Error: The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "asIs", "camelCaseOnly" or "dashesOnly"",
Error: The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "as-is", "camel-case-only" or "dashes-only"",
]
`;

Expand Down Expand Up @@ -6454,9 +6454,9 @@ a {

exports[`"modules" option should work and respect the "localConvention" option with the "asIs" value: warnings 1`] = `[]`;

exports[`"modules" option should work and respect the "localConvention" option with the "camelCase" value: errors 1`] = `[]`;
exports[`"modules" option should work and respect the "localConvention" option with the "camel-case-only" value: errors 1`] = `[]`;

exports[`"modules" option should work and respect the "localConvention" option with the "camelCase" value: module 1`] = `
exports[`"modules" option should work and respect the "localConvention" option with the "camel-case-only" value: 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";
Expand All @@ -6483,23 +6483,17 @@ a {
}
\`, ""]);
// Exports
___CSS_LOADER_EXPORT___.locals = {
"foo": \`bar\`,
"my-btn-info_is-disabled": \`value\`,
"myBtnInfoIsDisabled": \`value\`,
"btn-info_is-disabled": \`rmc8ltu8P1VXaeqLNU6N\`,
"btnInfoIsDisabled": \`rmc8ltu8P1VXaeqLNU6N\`,
"btn--info_is-disabled_1": \`AooVHuvzAIGXWngdfslc\`,
"btnInfoIsDisabled1": \`AooVHuvzAIGXWngdfslc\`,
"simple": \`snmJCrfw3LVnrlx87XVC\`,
"foo_bar": \`vA4oeh0XymefKJVIJyg1\`,
"fooBar": \`vA4oeh0XymefKJVIJyg1\`
};
export var foo = \`bar\`;
export var myBtnInfoIsDisabled = \`value\`;
export var btnInfoIsDisabled = \`rmc8ltu8P1VXaeqLNU6N\`;
export var btnInfoIsDisabled1 = \`AooVHuvzAIGXWngdfslc\`;
export var simple = \`snmJCrfw3LVnrlx87XVC\`;
export var fooBar = \`vA4oeh0XymefKJVIJyg1\`;
export default ___CSS_LOADER_EXPORT___;
"
`;

exports[`"modules" option should work and respect the "localConvention" option with the "camelCase" value: result 1`] = `
exports[`"modules" option should work and respect the "localConvention" option with the "camel-case-only" value: result 1`] = `
[
[
"./modules/localsConvention/localsConvention.css",
Expand Down Expand Up @@ -6528,11 +6522,11 @@ a {
]
`;

exports[`"modules" option should work and respect the "localConvention" option with the "camelCase" value: warnings 1`] = `[]`;
exports[`"modules" option should work and respect the "localConvention" option with the "camel-case-only" value: warnings 1`] = `[]`;

exports[`"modules" option should work and respect the "localConvention" option with the "camelCaseOnly" value: errors 1`] = `[]`;
exports[`"modules" option should work and respect the "localConvention" option with the "camelCase" value: errors 1`] = `[]`;

exports[`"modules" option should work and respect the "localConvention" option with the "camelCaseOnly" value: module 1`] = `
exports[`"modules" option should work and respect the "localConvention" option with the "camelCase" value: 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";
Expand Down Expand Up @@ -6561,17 +6555,21 @@ a {
// Exports
___CSS_LOADER_EXPORT___.locals = {
"foo": \`bar\`,
"my-btn-info_is-disabled": \`value\`,
"myBtnInfoIsDisabled": \`value\`,
"btn-info_is-disabled": \`rmc8ltu8P1VXaeqLNU6N\`,
"btnInfoIsDisabled": \`rmc8ltu8P1VXaeqLNU6N\`,
"btn--info_is-disabled_1": \`AooVHuvzAIGXWngdfslc\`,
"btnInfoIsDisabled1": \`AooVHuvzAIGXWngdfslc\`,
"simple": \`snmJCrfw3LVnrlx87XVC\`,
"foo_bar": \`vA4oeh0XymefKJVIJyg1\`,
"fooBar": \`vA4oeh0XymefKJVIJyg1\`
};
export default ___CSS_LOADER_EXPORT___;
"
`;

exports[`"modules" option should work and respect the "localConvention" option with the "camelCaseOnly" value: result 1`] = `
exports[`"modules" option should work and respect the "localConvention" option with the "camelCase" value: result 1`] = `
[
[
"./modules/localsConvention/localsConvention.css",
Expand Down Expand Up @@ -6600,7 +6598,7 @@ a {
]
`;

exports[`"modules" option should work and respect the "localConvention" option with the "camelCaseOnly" value: warnings 1`] = `[]`;
exports[`"modules" option should work and respect the "localConvention" option with the "camelCase" value: warnings 1`] = `[]`;

exports[`"modules" option should work and respect the "localConvention" option with the "dashes" value: errors 1`] = `[]`;

Expand Down
4 changes: 2 additions & 2 deletions test/__snapshots__/validate-options.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ exports[`validate options should throw an error on the "modules" option with "{"
-> Read more at https://github.com/webpack-contrib/css-loader#modules
Details:
* options.modules.exportLocalsConvention should be one of these:
"asIs" | "camelCase" | "camelCaseOnly" | "dashes" | "dashesOnly" | function
"asIs" | "as-is" | "camelCase" | "camel-case" | "camelCaseOnly" | "camel-case-only" | "dashes" | "dashesOnly" | "dashes-only" | function
-> Style of exported classnames.
-> Read more at https://github.com/webpack-contrib/css-loader#localsconvention
Details:
* options.modules.exportLocalsConvention should be one of these:
"asIs" | "camelCase" | "camelCaseOnly" | "dashes" | "dashesOnly"
"asIs" | "as-is" | "camelCase" | "camel-case" | "camelCaseOnly" | "camel-case-only" | "dashes" | "dashesOnly" | "dashes-only"
* options.modules.exportLocalsConvention should be an instance of function."
`;

Expand Down
5 changes: 2 additions & 3 deletions test/modules-option.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1412,14 +1412,13 @@ describe('"modules" option', () => {
expect(getErrors(stats)).toMatchSnapshot("errors");
});

it('should work and respect the "localConvention" option with the "camelCaseOnly" value', async () => {
it('should work and respect the "localConvention" option with the "camel-case-only" value', async () => {
const compiler = getCompiler(
"./modules/localsConvention/localsConvention.js",
{
modules: {
mode: "local",
exportLocalsConvention: "camelCaseOnly",
namedExport: false,
exportLocalsConvention: "camel-case-only",
},
},
);
Expand Down
5 changes: 4 additions & 1 deletion test/validate-options.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,13 @@ describe("validate options", () => {
{ auto: /custom-regex/ },
{ auto: () => true },
{ exportLocalsConvention: "asIs" },
{ exportLocalsConvention: "as-is" },
{ exportLocalsConvention: "camelCase", namedExport: false },
{ exportLocalsConvention: "camel-case", namedExport: false },
{ exportLocalsConvention: "camelCaseOnly" },
{ exportLocalsConvention: "camel-case-only" },
{ exportLocalsConvention: "dashes", namedExport: false },
{ exportLocalsConvention: "dashesOnly" },
{ exportLocalsConvention: "dashes-only" },
{
exportLocalsConvention: (localName) =>
`${localName.replace(/-/g, "_")}`,
Expand Down

0 comments on commit 63fee36

Please sign in to comment.