Repository: webpack-contrib/css-loader
Pull request #938 (2019-05-28 16:54:22)

feat: replace `camelCase` option on `exportLocalsStyle` option
<!--
  HOLY CRAP a Pull Request. We ❤️ those!

  If you remove or skip this template, you'll make the 🐼 sad and the mighty god
  of Github will appear and pile-drive the close button from a great height
  while making animal noises.

  Please place an x (no spaces!) in all [ ] that apply
-->

This PR contains a:

- [ ] **bugfix**
- [x] new **feature**
- [ ] **code refactor**
- [ ] **test update** <!-- if bug or feature is checked, this should be too -->
- [ ] **typo fix**
- [ ] **metadata update**

### Motivation / Use-Case

rename option

### Breaking Changes

Yes

BREAKING CHANGE: `camelCase` option was removed in favor `exportLocalsStyle` option. Option value should be `String`. Use `camelCase` if you option value was `true` and `asIs` if you option value was `false`.

### Additional Info

No

codecov[bot]: # [Codecov](https://codecov.io/gh/webpack-contrib/css-loader/pull/938?src=pr&el=h1) Report
> Merging [#938](https://codecov.io/gh/webpack-contrib/css-loader/pull/938?src=pr&el=desc) into [master](https://codecov.io/gh/webpack-contrib/css-loader/commit/1d7a4643fc84bf08d2c2c61c5724469936762ad0?src=pr&el=desc) will **increase** coverage by `<.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/webpack-contrib/css-loader/pull/938/graphs/tree.svg?width=650&token=DlN3OQ0JnO&height=150&src=pr)](https://codecov.io/gh/webpack-contrib/css-loader/pull/938?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #938      +/-   ##
==========================================
+ Coverage   99.27%   99.27%   +<.01%     
==========================================
  Files          10       10              
  Lines         411      412       +1     
  Branches      121      122       +1     
==========================================
+ Hits          408      409       +1     
  Misses          3        3
```


| [Impacted Files](https://codecov.io/gh/webpack-contrib/css-loader/pull/938?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/utils.js](https://codecov.io/gh/webpack-contrib/css-loader/pull/938/diff?src=pr&el=tree#diff-c3JjL3V0aWxzLmpz) | `99.23% <100%> (ø)` | :arrow_up: |
| [src/index.js](https://codecov.io/gh/webpack-contrib/css-loader/pull/938/diff?src=pr&el=tree#diff-c3JjL2luZGV4Lmpz) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/webpack-contrib/css-loader/pull/938?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/webpack-contrib/css-loader/pull/938?src=pr&el=footer). Last update [1d7a464...4df6b97](https://codecov.io/gh/webpack-contrib/css-loader/pull/938?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/README.md b/README.md
index 9a3323e..efd6bb5 100644
--- a/README.md
+++ b/README.md
@@ -109,15 +109,15 @@ module.exports = {
 
 ## Options
 
-|                    Name                     |            Type             | Default | Description                                        |
-| :-----------------------------------------: | :-------------------------: | :-----: | :------------------------------------------------- |
-|              **[`url`](#url)**              |    `{Boolean\|Function}`    | `true`  | Enable/Disable `url()` handling                    |
-|           **[`import`](#import)**           |    `{Boolean\|Function}`    | `true`  | Enable/Disable @import handling                    |
-|          **[`modules`](#modules)**          | `{Boolean\|String\|Object}` | `false` | Enable/Disable CSS Modules and setup their options |
-|        **[`sourceMap`](#sourcemap)**        |         `{Boolean}`         | `false` | Enable/Disable Sourcemaps                          |
-|        **[`camelCase`](#camelcase)**        |     `{Boolean\|String}`     | `false` | Export Classnames in CamelCase                     |
-|    **[`importLoaders`](#importloaders)**    |         `{Number}`          |   `0`   | Number of loaders applied before CSS loader        |
-| **[`exportOnlyLocals`](#exportonlylocals)** |         `{Boolean}`         | `false` | Export only locals                                 |
+|                     Name                      |            Type             | Default | Description                                        |
+| :-------------------------------------------: | :-------------------------: | :-----: | :------------------------------------------------- |
+|               **[`url`](#url)**               |    `{Boolean\|Function}`    | `true`  | Enable/Disable `url()` handling                    |
+|            **[`import`](#import)**            |    `{Boolean\|Function}`    | `true`  | Enable/Disable @import handling                    |
+|           **[`modules`](#modules)**           | `{Boolean\|String\|Object}` | `false` | Enable/Disable CSS Modules and setup their options |
+|         **[`sourceMap`](#sourcemap)**         |         `{Boolean}`         | `false` | Enable/Disable Sourcemaps                          |
+|     **[`importLoaders`](#importloaders)**     |         `{Number}`          |   `0`   | Number of loaders applied before CSS loader        |
+| **[`exportLocalsStyle`](#exportlocalsstyle)** |         `{String}`          | `asIs`  | Setup style of exported classnames                 |
+|  **[`exportOnlyLocals`](#exportonlylocals)**  |         `{Boolean}`         | `false` | Export only locals                                 |
 
 ### `url`
 
@@ -672,7 +672,7 @@ To include source maps set the `sourceMap` option.
 
 I.e. the `mini-css-extract-plugin` can handle them.
 
-They are not enabled by default because they expose a runtime overhead and increase in bundle size (JS source maps do not). 
+They are not enabled by default because they expose a runtime overhead and increase in bundle size (JS source maps do not).
 
 In addition to that relative paths are buggy and you need to use an absolute public path which includes the server URL.
 
@@ -694,52 +694,6 @@ module.exports = {
 };
 ```
 
-### `camelCase`
-
-Type: `Boolean|String`
-Default: `false`
-
-By default, the exported JSON keys mirror the class names.
-
-|        Name        |    Type     | Description                                                                                                              |
-| :----------------: | :---------: | :----------------------------------------------------------------------------------------------------------------------- |
-|    **`false`**     | `{Boolean}` | Class names won't be camelized                                                                                           |
-|     **`true`**     | `{Boolean}` | Class names will be camelized, the original class name will not to be removed from the locals                            |
-|   **`'dashes'`**   | `{String}`  | Only dashes in class names will be camelized                                                                             |
-|    **`'only'`**    | `{String}`  | Introduced in `0.27.1`. Class names will be camelized, the original class name will be removed from the locals           |
-| **`'dashesOnly'`** | `{String}`  | Introduced in `0.27.1`. Dashes in class names will be camelized, the original class name will be removed from the locals |
-
-**file.css**
-
-```css
-.class-name {
-}
-```
-
-**file.js**
-
-```js
-import { className } from 'file.css';
-```
-
-**webpack.config.js**
-
-```js
-module.exports = {
-  module: {
-    rules: [
-      {
-        test: /\.css$/i,
-        loader: 'css-loader',
-        options: {
-          camelCase: true,
-        },
-      },
-    ],
-  },
-};
-```
-
 ### `importLoaders`
 
 Type: `Number`
@@ -774,6 +728,52 @@ module.exports = {
 
 This may change in the future when the module system (i. e. webpack) supports loader matching by origin.
 
+### `exportLocalsStyle`
+
+Type: `String`
+Default: `undefined`
+
+By default, the exported JSON keys mirror the class names (i.e `asIs` 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 |
+
+**file.css**
+
+```css
+.class-name {
+}
+```
+
+**file.js**
+
+```js
+import { className } from 'file.css';
+```
+
+**webpack.config.js**
+
+```js
+module.exports = {
+  module: {
+    rules: [
+      {
+        test: /\.css$/i,
+        loader: 'css-loader',
+        options: {
+          exportLocalsStyle: 'camelCase',
+        },
+      },
+    ],
+  },
+};
+```
+
 ### `exportOnlyLocals`
 
 Type: `Boolean`
@@ -821,7 +821,7 @@ module.exports = {
         test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/,
         loader: 'url-loader',
         options: {
-          limit: 10000,
+          limit: 8192,
         },
       },
     ],
diff --git a/src/index.js b/src/index.js
index 1a1c11b..5580999 100644
--- a/src/index.js
+++ b/src/index.js
@@ -104,7 +104,7 @@ export default function loader(content, map, meta) {
         .forEach((warning) => this.emitWarning(new Warning(warning)));
 
       const messages = result.messages || [];
-      const { exportOnlyLocals, importLoaders, camelCase } = options;
+      const { exportOnlyLocals, importLoaders, exportLocalsStyle } = options;
 
       // Run other loader (`postcss-loader`, `sass-loader` and etc) for importing CSS
       const importPrefix = getImportPrefix(this, importLoaders);
@@ -117,7 +117,11 @@ export default function loader(content, map, meta) {
         exportOnlyLocals
       );
 
-      const exports = getExports(messages, camelCase, importItemReplacer);
+      const exports = getExports(
+        messages,
+        exportLocalsStyle,
+        importItemReplacer
+      );
 
       if (exportOnlyLocals) {
         return callback(
diff --git a/src/options.json b/src/options.json
index 0f7f93e..b9f773f 100644
--- a/src/options.json
+++ b/src/options.json
@@ -74,24 +74,21 @@
     "sourceMap": {
       "type": "boolean"
     },
-    "camelCase": {
+    "importLoaders": {
       "anyOf": [
         {
           "type": "boolean"
         },
         {
-          "type": "string",
-          "enum": ["dashes", "only", "dashesOnly"]
+          "type": "number"
         }
       ]
     },
-    "importLoaders": {
+    "exportLocalsStyle": {
       "anyOf": [
         {
-          "type": "boolean"
-        },
-        {
-          "type": "number"
+          "type": "string",
+          "enum": ["asIs", "camelCase","camelCaseOnly", "dashes", "dashesOnly"]
         }
       ]
     },
diff --git a/src/utils.js b/src/utils.js
index 5745b63..5d8c2d2 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -152,7 +152,7 @@ function getImportItemReplacer(
   };
 }
 
-function getExports(messages, exportStyle, importItemReplacer) {
+function getExports(messages, exportLocalsStyle, importItemReplacer) {
   return messages
     .filter((message) => message.type === 'export')
     .reduce((accumulator, message) => {
@@ -171,8 +171,8 @@ function getExports(messages, exportStyle, importItemReplacer) {
 
       let targetKey;
 
-      switch (exportStyle) {
-        case true:
+      switch (exportLocalsStyle) {
+        case 'camelCase':
           addEntry(key);
           targetKey = camelCase(key);
 
@@ -180,6 +180,9 @@ function getExports(messages, exportStyle, importItemReplacer) {
             addEntry(targetKey);
           }
           break;
+        case 'camelCaseOnly':
+          addEntry(camelCase(key));
+          break;
         case 'dashes':
           addEntry(key);
           targetKey = dashesCamelCase(key);
@@ -188,12 +191,10 @@ function getExports(messages, exportStyle, importItemReplacer) {
             addEntry(targetKey);
           }
           break;
-        case 'only':
-          addEntry(camelCase(key));
-          break;
         case 'dashesOnly':
           addEntry(dashesCamelCase(key));
           break;
+        case 'asIs':
         default:
           addEntry(key);
           break;
@@ -338,8 +339,6 @@ export {
   getImportPrefix,
   getLocalIdent,
   placholderRegExps,
-  camelCase,
-  dashesCamelCase,
   getFilter,
   getImportItemReplacer,
   getExports,


Test patch:
diff --git a/test/__snapshots__/camelCase-option.test.js.snap b/test/__snapshots__/camelCase-option.test.js.snap
deleted file mode 100644
index 537f463..0000000
--- a/test/__snapshots__/camelCase-option.test.js.snap
+++ /dev/null
@@ -1,202 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`camelCase option dashes: errors 1`] = `Array []`;
-
-exports[`camelCase option dashes: locals 1`] = `
-Object {
-  "btn--info_is-disabled_1": "jDvNwV-WRSMB9n2z9QrzR",
-  "btn-info_is-disabled": "_1XTfjK5gKYeSzbdZhEXRpF",
-  "btnInfo_isDisabled": "_1XTfjK5gKYeSzbdZhEXRpF",
-  "btnInfo_isDisabled_1": "jDvNwV-WRSMB9n2z9QrzR",
-  "foo": "bar",
-  "my-btn-info_is-disabled": "value",
-  "myBtnInfo_isDisabled": "value",
-  "simple": "_1penVf9PMtov2qLxmtsMjq",
-}
-`;
-
-exports[`camelCase option dashes: module (evaluated) 1`] = `
-Array [
-  Array [
-    1,
-    "._1XTfjK5gKYeSzbdZhEXRpF {
-  color: blue;
-}
-
-.jDvNwV-WRSMB9n2z9QrzR {
-  color: blue;
-}
-
-._1penVf9PMtov2qLxmtsMjq {
-  color: red;
-}
-
-a {
-  color: yellow;
-}
-",
-    "",
-  ],
-]
-`;
-
-exports[`camelCase option dashes: warnings 1`] = `Array []`;
-
-exports[`camelCase option dashesOnly: errors 1`] = `Array []`;
-
-exports[`camelCase option dashesOnly: locals 1`] = `
-Object {
-  "btnInfo_isDisabled": "_1XTfjK5gKYeSzbdZhEXRpF",
-  "btnInfo_isDisabled_1": "jDvNwV-WRSMB9n2z9QrzR",
-  "foo": "bar",
-  "myBtnInfo_isDisabled": "value",
-  "simple": "_1penVf9PMtov2qLxmtsMjq",
-}
-`;
-
-exports[`camelCase option dashesOnly: module (evaluated) 1`] = `
-Array [
-  Array [
-    1,
-    "._1XTfjK5gKYeSzbdZhEXRpF {
-  color: blue;
-}
-
-.jDvNwV-WRSMB9n2z9QrzR {
-  color: blue;
-}
-
-._1penVf9PMtov2qLxmtsMjq {
-  color: red;
-}
-
-a {
-  color: yellow;
-}
-",
-    "",
-  ],
-]
-`;
-
-exports[`camelCase option dashesOnly: warnings 1`] = `Array []`;
-
-exports[`camelCase option not specified: errors 1`] = `Array []`;
-
-exports[`camelCase option not specified: locals 1`] = `
-Object {
-  "btn--info_is-disabled_1": "jDvNwV-WRSMB9n2z9QrzR",
-  "btn-info_is-disabled": "_1XTfjK5gKYeSzbdZhEXRpF",
-  "foo": "bar",
-  "my-btn-info_is-disabled": "value",
-  "simple": "_1penVf9PMtov2qLxmtsMjq",
-}
-`;
-
-exports[`camelCase option not specified: module (evaluated) 1`] = `
-Array [
-  Array [
-    1,
-    "._1XTfjK5gKYeSzbdZhEXRpF {
-  color: blue;
-}
-
-.jDvNwV-WRSMB9n2z9QrzR {
-  color: blue;
-}
-
-._1penVf9PMtov2qLxmtsMjq {
-  color: red;
-}
-
-a {
-  color: yellow;
-}
-",
-    "",
-  ],
-]
-`;
-
-exports[`camelCase option not specified: warnings 1`] = `Array []`;
-
-exports[`camelCase option only: errors 1`] = `Array []`;
-
-exports[`camelCase option only: locals 1`] = `
-Object {
-  "btnInfoIsDisabled": "_1XTfjK5gKYeSzbdZhEXRpF",
-  "btnInfoIsDisabled1": "jDvNwV-WRSMB9n2z9QrzR",
-  "foo": "bar",
-  "myBtnInfoIsDisabled": "value",
-  "simple": "_1penVf9PMtov2qLxmtsMjq",
-}
-`;
-
-exports[`camelCase option only: module (evaluated) 1`] = `
-Array [
-  Array [
-    1,
-    "._1XTfjK5gKYeSzbdZhEXRpF {
-  color: blue;
-}
-
-.jDvNwV-WRSMB9n2z9QrzR {
-  color: blue;
-}
-
-._1penVf9PMtov2qLxmtsMjq {
-  color: red;
-}
-
-a {
-  color: yellow;
-}
-",
-    "",
-  ],
-]
-`;
-
-exports[`camelCase option only: warnings 1`] = `Array []`;
-
-exports[`camelCase option true: errors 1`] = `Array []`;
-
-exports[`camelCase option true: locals 1`] = `
-Object {
-  "btn--info_is-disabled_1": "jDvNwV-WRSMB9n2z9QrzR",
-  "btn-info_is-disabled": "_1XTfjK5gKYeSzbdZhEXRpF",
-  "btnInfoIsDisabled": "_1XTfjK5gKYeSzbdZhEXRpF",
-  "btnInfoIsDisabled1": "jDvNwV-WRSMB9n2z9QrzR",
-  "foo": "bar",
-  "my-btn-info_is-disabled": "value",
-  "myBtnInfoIsDisabled": "value",
-  "simple": "_1penVf9PMtov2qLxmtsMjq",
-}
-`;
-
-exports[`camelCase option true: module (evaluated) 1`] = `
-Array [
-  Array [
-    1,
-    "._1XTfjK5gKYeSzbdZhEXRpF {
-  color: blue;
-}
-
-.jDvNwV-WRSMB9n2z9QrzR {
-  color: blue;
-}
-
-._1penVf9PMtov2qLxmtsMjq {
-  color: red;
-}
-
-a {
-  color: yellow;
-}
-",
-    "",
-  ],
-]
-`;
-
-exports[`camelCase option true: warnings 1`] = `Array []`;
diff --git a/test/__snapshots__/exportLocalsStyle-option.test.js.snap b/test/__snapshots__/exportLocalsStyle-option.test.js.snap
new file mode 100644
index 0000000..71c37fe
--- /dev/null
+++ b/test/__snapshots__/exportLocalsStyle-option.test.js.snap
@@ -0,0 +1,241 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`exportLocalsStyle option asIs: errors 1`] = `Array []`;
+
+exports[`exportLocalsStyle option asIs: locals 1`] = `
+Object {
+  "btn--info_is-disabled_1": "_1cmsy2E5swY7Ysn8h7qDun",
+  "btn-info_is-disabled": "qysDcl74sBAzry5FpDPQi",
+  "foo": "bar",
+  "my-btn-info_is-disabled": "value",
+  "simple": "f42SiWmkrcnocxM5cvNJw",
+}
+`;
+
+exports[`exportLocalsStyle option asIs: module (evaluated) 1`] = `
+Array [
+  Array [
+    1,
+    ".qysDcl74sBAzry5FpDPQi {
+  color: blue;
+}
+
+._1cmsy2E5swY7Ysn8h7qDun {
+  color: blue;
+}
+
+.f42SiWmkrcnocxM5cvNJw {
+  color: red;
+}
+
+a {
+  color: yellow;
+}
+",
+    "",
+  ],
+]
+`;
+
+exports[`exportLocalsStyle option asIs: warnings 1`] = `Array []`;
+
+exports[`exportLocalsStyle option camelCase: errors 1`] = `Array []`;
+
+exports[`exportLocalsStyle option camelCase: locals 1`] = `
+Object {
+  "btn--info_is-disabled_1": "_1cmsy2E5swY7Ysn8h7qDun",
+  "btn-info_is-disabled": "qysDcl74sBAzry5FpDPQi",
+  "btnInfoIsDisabled": "qysDcl74sBAzry5FpDPQi",
+  "btnInfoIsDisabled1": "_1cmsy2E5swY7Ysn8h7qDun",
+  "foo": "bar",
+  "my-btn-info_is-disabled": "value",
+  "myBtnInfoIsDisabled": "value",
+  "simple": "f42SiWmkrcnocxM5cvNJw",
+}
+`;
+
+exports[`exportLocalsStyle option camelCase: module (evaluated) 1`] = `
+Array [
+  Array [
+    1,
+    ".qysDcl74sBAzry5FpDPQi {
+  color: blue;
+}
+
+._1cmsy2E5swY7Ysn8h7qDun {
+  color: blue;
+}
+
+.f42SiWmkrcnocxM5cvNJw {
+  color: red;
+}
+
+a {
+  color: yellow;
+}
+",
+    "",
+  ],
+]
+`;
+
+exports[`exportLocalsStyle option camelCase: warnings 1`] = `Array []`;
+
+exports[`exportLocalsStyle option camelCaseOnly: errors 1`] = `Array []`;
+
+exports[`exportLocalsStyle option camelCaseOnly: locals 1`] = `
+Object {
+  "btnInfoIsDisabled": "qysDcl74sBAzry5FpDPQi",
+  "btnInfoIsDisabled1": "_1cmsy2E5swY7Ysn8h7qDun",
+  "foo": "bar",
+  "myBtnInfoIsDisabled": "value",
+  "simple": "f42SiWmkrcnocxM5cvNJw",
+}
+`;
+
+exports[`exportLocalsStyle option camelCaseOnly: module (evaluated) 1`] = `
+Array [
+  Array [
+    1,
+    ".qysDcl74sBAzry5FpDPQi {
+  color: blue;
+}
+
+._1cmsy2E5swY7Ysn8h7qDun {
+  color: blue;
+}
+
+.f42SiWmkrcnocxM5cvNJw {
+  color: red;
+}
+
+a {
+  color: yellow;
+}
+",
+    "",
+  ],
+]
+`;
+
+exports[`exportLocalsStyle option camelCaseOnly: warnings 1`] = `Array []`;
+
+exports[`exportLocalsStyle option dashes: errors 1`] = `Array []`;
+
+exports[`exportLocalsStyle option dashes: locals 1`] = `
+Object {
+  "btn--info_is-disabled_1": "_1cmsy2E5swY7Ysn8h7qDun",
+  "btn-info_is-disabled": "qysDcl74sBAzry5FpDPQi",
+  "btnInfo_isDisabled": "qysDcl74sBAzry5FpDPQi",
+  "btnInfo_isDisabled_1": "_1cmsy2E5swY7Ysn8h7qDun",
+  "foo": "bar",
+  "my-btn-info_is-disabled": "value",
+  "myBtnInfo_isDisabled": "value",
+  "simple": "f42SiWmkrcnocxM5cvNJw",
+}
+`;
+
+exports[`exportLocalsStyle option dashes: module (evaluated) 1`] = `
+Array [
+  Array [
+    1,
+    ".qysDcl74sBAzry5FpDPQi {
+  color: blue;
+}
+
+._1cmsy2E5swY7Ysn8h7qDun {
+  color: blue;
+}
+
+.f42SiWmkrcnocxM5cvNJw {
+  color: red;
+}
+
+a {
+  color: yellow;
+}
+",
+    "",
+  ],
+]
+`;
+
+exports[`exportLocalsStyle option dashes: warnings 1`] = `Array []`;
+
+exports[`exportLocalsStyle option dashesOnly: errors 1`] = `Array []`;
+
+exports[`exportLocalsStyle option dashesOnly: locals 1`] = `
+Object {
+  "btnInfo_isDisabled": "qysDcl74sBAzry5FpDPQi",
+  "btnInfo_isDisabled_1": "_1cmsy2E5swY7Ysn8h7qDun",
+  "foo": "bar",
+  "myBtnInfo_isDisabled": "value",
+  "simple": "f42SiWmkrcnocxM5cvNJw",
+}
+`;
+
+exports[`exportLocalsStyle option dashesOnly: module (evaluated) 1`] = `
+Array [
+  Array [
+    1,
+    ".qysDcl74sBAzry5FpDPQi {
+  color: blue;
+}
+
+._1cmsy2E5swY7Ysn8h7qDun {
+  color: blue;
+}
+
+.f42SiWmkrcnocxM5cvNJw {
+  color: red;
+}
+
+a {
+  color: yellow;
+}
+",
+    "",
+  ],
+]
+`;
+
+exports[`exportLocalsStyle option dashesOnly: warnings 1`] = `Array []`;
+
+exports[`exportLocalsStyle option not specified: errors 1`] = `Array []`;
+
+exports[`exportLocalsStyle option not specified: locals 1`] = `
+Object {
+  "btn--info_is-disabled_1": "_1cmsy2E5swY7Ysn8h7qDun",
+  "btn-info_is-disabled": "qysDcl74sBAzry5FpDPQi",
+  "foo": "bar",
+  "my-btn-info_is-disabled": "value",
+  "simple": "f42SiWmkrcnocxM5cvNJw",
+}
+`;
+
+exports[`exportLocalsStyle option not specified: module (evaluated) 1`] = `
+Array [
+  Array [
+    1,
+    ".qysDcl74sBAzry5FpDPQi {
+  color: blue;
+}
+
+._1cmsy2E5swY7Ysn8h7qDun {
+  color: blue;
+}
+
+.f42SiWmkrcnocxM5cvNJw {
+  color: red;
+}
+
+a {
+  color: yellow;
+}
+",
+    "",
+  ],
+]
+`;
+
+exports[`exportLocalsStyle option not specified: warnings 1`] = `Array []`;
diff --git a/test/__snapshots__/validate-options.test.js.snap b/test/__snapshots__/validate-options.test.js.snap
index b44a897..d6bcf1d 100644
--- a/test/__snapshots__/validate-options.test.js.snap
+++ b/test/__snapshots__/validate-options.test.js.snap
@@ -162,9 +162,8 @@ options.sourceMap should be boolean
 exports[`validate options 16`] = `
 "CSS Loader Invalid Options
 
-options.camelCase should be boolean
-options.camelCase should be equal to one of the allowed values
-options.camelCase should match some schema in anyOf
+options.exportLocalsStyle should be equal to one of the allowed values
+options.exportLocalsStyle should match some schema in anyOf
 "
 `;
 
diff --git a/test/camelCase-option.test.js b/test/exportLocalsStyle-option.test.js
similarity index 70%
rename from test/camelCase-option.test.js
rename to test/exportLocalsStyle-option.test.js
index 909a45d..151a1fb 100644
--- a/test/camelCase-option.test.js
+++ b/test/exportLocalsStyle-option.test.js
@@ -1,16 +1,30 @@
 import { webpack, evaluated } from './helpers';
 
-describe('camelCase option', () => {
-  it('true', async () => {
+describe('exportLocalsStyle option', () => {
+  it('not specified', async () => {
+    const config = { loader: { options: { modules: true } } };
+    const testId = './modules/exportLocalsStyle.css';
+    const stats = await webpack(testId, config);
+    const { modules } = stats.toJson();
+    const module = modules.find((m) => m.id === testId);
+    const evaluatedModule = evaluated(module.source);
+
+    expect(evaluatedModule).toMatchSnapshot('module (evaluated)');
+    expect(evaluatedModule.locals).toMatchSnapshot('locals');
+    expect(stats.compilation.warnings).toMatchSnapshot('warnings');
+    expect(stats.compilation.errors).toMatchSnapshot('errors');
+  });
+
+  it('asIs', async () => {
     const config = {
       loader: {
         options: {
           modules: true,
-          camelCase: true,
+          exportLocalsStyle: 'asIs',
         },
       },
     };
-    const testId = './modules/camelCase.css';
+    const testId = './modules/exportLocalsStyle.css';
     const stats = await webpack(testId, config);
     const { modules } = stats.toJson();
     const module = modules.find((m) => m.id === testId);
@@ -22,9 +36,16 @@ describe('camelCase option', () => {
     expect(stats.compilation.errors).toMatchSnapshot('errors');
   });
 
-  it('not specified', async () => {
-    const config = { loader: { options: { modules: true } } };
-    const testId = './modules/camelCase.css';
+  it('camelCase', async () => {
+    const config = {
+      loader: {
+        options: {
+          modules: true,
+          exportLocalsStyle: 'camelCase',
+        },
+      },
+    };
+    const testId = './modules/exportLocalsStyle.css';
     const stats = await webpack(testId, config);
     const { modules } = stats.toJson();
     const module = modules.find((m) => m.id === testId);
@@ -36,16 +57,16 @@ describe('camelCase option', () => {
     expect(stats.compilation.errors).toMatchSnapshot('errors');
   });
 
-  it('dashes', async () => {
+  it('camelCaseOnly', async () => {
     const config = {
       loader: {
         options: {
           modules: true,
-          camelCase: 'dashes',
+          exportLocalsStyle: 'camelCaseOnly',
         },
       },
     };
-    const testId = './modules/camelCase.css';
+    const testId = './modules/exportLocalsStyle.css';
     const stats = await webpack(testId, config);
     const { modules } = stats.toJson();
     const module = modules.find((m) => m.id === testId);
@@ -57,16 +78,16 @@ describe('camelCase option', () => {
     expect(stats.compilation.errors).toMatchSnapshot('errors');
   });
 
-  it('only', async () => {
+  it('dashes', async () => {
     const config = {
       loader: {
         options: {
           modules: true,
-          camelCase: 'only',
+          exportLocalsStyle: 'dashes',
         },
       },
     };
-    const testId = './modules/camelCase.css';
+    const testId = './modules/exportLocalsStyle.css';
     const stats = await webpack(testId, config);
     const { modules } = stats.toJson();
     const module = modules.find((m) => m.id === testId);
@@ -83,11 +104,11 @@ describe('camelCase option', () => {
       loader: {
         options: {
           modules: true,
-          camelCase: 'dashesOnly',
+          exportLocalsStyle: 'dashesOnly',
         },
       },
     };
-    const testId = './modules/camelCase.css';
+    const testId = './modules/exportLocalsStyle.css';
     const stats = await webpack(testId, config);
     const { modules } = stats.toJson();
     const module = modules.find((m) => m.id === testId);
diff --git a/test/fixtures/modules/camelCase.css b/test/fixtures/modules/exportLocalsStyle.css
similarity index 100%
rename from test/fixtures/modules/camelCase.css
rename to test/fixtures/modules/exportLocalsStyle.css
diff --git a/test/validate-options.test.js b/test/validate-options.test.js
index 1188b05..2f711d3 100644
--- a/test/validate-options.test.js
+++ b/test/validate-options.test.js
@@ -93,13 +93,12 @@ it('validate options', () => {
   expect(() => validate({ sourceMap: false })).not.toThrow();
   expect(() => validate({ sourceMap: 'true' })).toThrowErrorMatchingSnapshot();
 
-  expect(() => validate({ camelCase: true })).not.toThrow();
-  expect(() => validate({ camelCase: false })).not.toThrow();
-  expect(() => validate({ camelCase: 'dashes' })).not.toThrow();
-  expect(() => validate({ camelCase: 'only' })).not.toThrow();
-  expect(() => validate({ camelCase: 'dashesOnly' })).not.toThrow();
+  expect(() => validate({ exportLocalsStyle: 'camelCase' })).not.toThrow();
+  expect(() => validate({ exportLocalsStyle: 'camelCaseOnly' })).not.toThrow();
+  expect(() => validate({ exportLocalsStyle: 'dashes' })).not.toThrow();
+  expect(() => validate({ exportLocalsStyle: 'dashesOnly' })).not.toThrow();
   expect(() =>
-    validate({ camelCase: 'unknown' })
+    validate({ exportLocalsStyle: 'unknown' })
   ).toThrowErrorMatchingSnapshot();
 
   expect(() => validate({ importLoaders: false })).not.toThrow();