Repository: webpack-contrib/css-loader (js)

Issue:
export classes (include `:global`)
if not use css-module, how to get class from file ?

``` css
//style.css
.block {width:1 00%;}
.block_mod {color: red;}
```

``` js
//index.es6
import slyle form './style.css';
//style = [
//  'block',
//  'block_mod'
//];
```


Pull request:
feat: the `exportGlobals` option for export global classes and ids
<!--
  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**
- [x] **test update** <!-- if bug or feature is checked, this should be too -->
- [ ] **typo fix**
- [x] **metadata update**

### Motivation / Use-Case

fixes #258

### Breaking Changes

No

### Additional Info

No

Patch:
diff --git a/README.md b/README.md
index 737f15c..a6bee2f 100644
--- a/README.md
+++ b/README.md
@@ -528,6 +528,7 @@ module.exports = {
         options: {
           modules: {
             mode: 'local',
+            exportGlobals: true,
             localIdentName: '[path][name]__[local]--[hash:base64:5]',
             context: path.resolve(__dirname, 'src'),
             hashPrefix: 'my-custom-hash',
@@ -605,6 +606,33 @@ module.exports = {
 };
 ```
 
+##### `exportGlobals`
+
+Type: `Boolean`
+Default: `false`
+
+Allow `css-loader` to export names from global class or id, so you can use that as local name.
+
+**webpack.config.js**
+
+```js
+module.exports = {
+  module: {
+    rules: [
+      {
+        test: /\.css$/i,
+        loader: 'css-loader',
+        options: {
+          modules: {
+            exportGlobals: true,
+          },
+        },
+      },
+    ],
+  },
+};
+```
+
 ##### `localIdentName`
 
 Type: `String`
diff --git a/src/options.json b/src/options.json
index 742c28c..706e4e9 100644
--- a/src/options.json
+++ b/src/options.json
@@ -46,6 +46,9 @@
                 }
               ]
             },
+            "exportGlobals": {
+              "type": "boolean"
+            },
             "localIdentName": {
               "type": "string"
             },
diff --git a/src/utils.js b/src/utils.js
index 0bfed95..a4c6511 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -99,6 +99,7 @@ function getFilter(filter, resourcePath, defaultFilter = null) {
 function getModulesPlugins(options, loaderContext) {
   let modulesOptions = {
     mode: 'local',
+    exportGlobals: false,
     localIdentName: '[hash:base64]',
     getLocalIdent,
     hashPrefix: '',
@@ -116,11 +117,7 @@ function getModulesPlugins(options, loaderContext) {
   }
 
   if (typeof modulesOptions.mode === 'function') {
-    const modeFromFunction = modulesOptions.mode(loaderContext.resourcePath);
-
-    if (modeFromFunction === 'local' || modeFromFunction === 'global') {
-      modulesOptions.mode = modeFromFunction;
-    }
+    modulesOptions.mode = modulesOptions.mode(loaderContext.resourcePath);
   }
 
   let plugins = [];
@@ -158,6 +155,7 @@ function getModulesPlugins(options, loaderContext) {
 
           return localIdent;
         },
+        exportGlobals: modulesOptions.exportGlobals,
       }),
     ];
   } catch (error) {


Test patch:
diff --git a/test/__snapshots__/modules-option.test.js.snap b/test/__snapshots__/modules-option.test.js.snap
index ae8349d..ceab550 100644
--- a/test/__snapshots__/modules-option.test.js.snap
+++ b/test/__snapshots__/modules-option.test.js.snap
@@ -368,6 +368,8 @@ Array [
   "ModuleError: Module Error (from \`replaced original path\`):
 options.mode must be either \\"global\\", \\"local\\" or \\"pure\\" (default \\"local\\")",
   "ModuleError: Module Error (from \`replaced original path\`):
+options.mode must be either \\"global\\", \\"local\\" or \\"pure\\" (default \\"local\\")",
+  "ModuleError: Module Error (from \`replaced original path\`):
 options.mode must be either \\"global\\", \\"local\\" or \\"pure\\" (default \\"local\\")",
 ]
 `;
@@ -409,6 +411,9 @@ exports[`"modules" option issue #1063 throw error: result 1`] = `
 :local(.otherClassGlobalFile) {
   color: coral;
 }
+.foo :local(.bar) {
+  color: red;
+}
 "
 `;
 
@@ -416,7 +421,21 @@ exports[`"modules" option issue #1063 throw error: warnings 1`] = `Array []`;
 
 exports[`"modules" option issue #1063: errors 1`] = `Array []`;
 
-exports[`"modules" option issue #1063: module 1`] = `
+exports[`"modules" option issue #1063: module with the \`global\` mode 1`] = `
+"// Imports
+var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../src/runtime/api.js\\");
+exports = ___CSS_LOADER_API_IMPORT___(false);
+// Module
+exports.push([module.id, \\".classNameGlobalFile {\\\\n  color: black;\\\\n}\\\\n\\\\n._2rcag09JpwrP4_hfyyRmm- {\\\\n  color: coral;\\\\n}\\\\n\\", \\"\\"]);
+// Exports
+exports.locals = {
+	\\"otherClassGlobalFile\\": \\"_2rcag09JpwrP4_hfyyRmm-\\"
+};
+module.exports = exports;
+"
+`;
+
+exports[`"modules" option issue #1063: module with the \`local\` mode 1`] = `
 "// Imports
 var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../src/runtime/api.js\\");
 exports = ___CSS_LOADER_API_IMPORT___(false);
@@ -430,15 +449,16 @@ module.exports = exports;
 "
 `;
 
-exports[`"modules" option issue #1063: module 2`] = `
+exports[`"modules" option issue #1063: module with the \`pure\` mode 1`] = `
 "// Imports
 var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../src/runtime/api.js\\");
 exports = ___CSS_LOADER_API_IMPORT___(false);
 // Module
-exports.push([module.id, \\".classNameGlobalFile {\\\\n  color: black;\\\\n}\\\\n\\\\n._2rcag09JpwrP4_hfyyRmm- {\\\\n  color: coral;\\\\n}\\\\n\\", \\"\\"]);
+exports.push([module.id, \\"._1rycxa6QkLdgO7vayuTDvk ._3Otdq1jay-xaQGguOXb-0X {\\\\n  color: red;\\\\n}\\\\n\\", \\"\\"]);
 // Exports
 exports.locals = {
-	\\"otherClassGlobalFile\\": \\"_2rcag09JpwrP4_hfyyRmm-\\"
+	\\"foo\\": \\"_1rycxa6QkLdgO7vayuTDvk\\",
+	\\"bar\\": \\"_3Otdq1jay-xaQGguOXb-0X\\"
 };
 module.exports = exports;
 "
@@ -459,6 +479,9 @@ exports[`"modules" option issue #1063: result 1`] = `
 ._2rcag09JpwrP4_hfyyRmm- {
   color: coral;
 }
+._1rycxa6QkLdgO7vayuTDvk ._3Otdq1jay-xaQGguOXb-0X {
+  color: red;
+}
 "
 `;
 
@@ -11098,3 +11121,128 @@ Array [
 `;
 
 exports[`"modules" option should work with the "[local]" placeholder for the "localIdentName" option: warnings 1`] = `Array []`;
+
+exports[`"modules" option should work with the \`exportGlobals\` option (the \`mode\` option is \`global\`): errors 1`] = `Array []`;
+
+exports[`"modules" option should work with the \`exportGlobals\` option (the \`mode\` option is \`global\`): module 1`] = `
+"// Imports
+var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../src/runtime/api.js\\");
+exports = ___CSS_LOADER_API_IMPORT___(false);
+// Module
+exports.push([module.id, \\".QLhabfC4HjcIBmobkGW_v {\\\\n  background-color: red;\\\\n}\\\\n\\\\n._1fCLE6vkQLICB5aEeEaLgd {\\\\n  background-color: green;\\\\n}\\\\n\\\\n.baz {\\\\n  background-color: blue;\\\\n}\\\\n\\", \\"\\"]);
+// Exports
+exports.locals = {
+	\\"foo\\": \\"QLhabfC4HjcIBmobkGW_v\\",
+	\\"bar\\": \\"_1fCLE6vkQLICB5aEeEaLgd\\",
+	\\"baz\\": \\"baz\\"
+};
+module.exports = exports;
+"
+`;
+
+exports[`"modules" option should work with the \`exportGlobals\` option (the \`mode\` option is \`global\`): result 1`] = `
+Array [
+  Array [
+    "./modules/exportGlobals-global/exportGlobals.css",
+    ".QLhabfC4HjcIBmobkGW_v {
+  background-color: red;
+}
+
+._1fCLE6vkQLICB5aEeEaLgd {
+  background-color: green;
+}
+
+.baz {
+  background-color: blue;
+}
+",
+    "",
+  ],
+]
+`;
+
+exports[`"modules" option should work with the \`exportGlobals\` option (the \`mode\` option is \`global\`): warnings 1`] = `Array []`;
+
+exports[`"modules" option should work with the \`exportGlobals\` option (the \`mode\` option is \`local\`): errors 1`] = `Array []`;
+
+exports[`"modules" option should work with the \`exportGlobals\` option (the \`mode\` option is \`local\`): module 1`] = `
+"// Imports
+var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../src/runtime/api.js\\");
+exports = ___CSS_LOADER_API_IMPORT___(false);
+// Module
+exports.push([module.id, \\".foo {\\\\n  background-color: red;\\\\n}\\\\n\\\\n._3loyPgwYlZ-RBGWccx71es {\\\\n  background-color: green;\\\\n}\\\\n\\\\n.baz {\\\\n  background-color: blue;\\\\n}\\\\n\\", \\"\\"]);
+// Exports
+exports.locals = {
+	\\"foo\\": \\"foo\\",
+	\\"bar\\": \\"_3loyPgwYlZ-RBGWccx71es\\",
+	\\"baz\\": \\"baz\\"
+};
+module.exports = exports;
+"
+`;
+
+exports[`"modules" option should work with the \`exportGlobals\` option (the \`mode\` option is \`local\`): result 1`] = `
+Array [
+  Array [
+    "./modules/exportGlobals-local/exportGlobals.css",
+    ".foo {
+  background-color: red;
+}
+
+._3loyPgwYlZ-RBGWccx71es {
+  background-color: green;
+}
+
+.baz {
+  background-color: blue;
+}
+",
+    "",
+  ],
+]
+`;
+
+exports[`"modules" option should work with the \`exportGlobals\` option (the \`mode\` option is \`local\`): warnings 1`] = `Array []`;
+
+exports[`"modules" option should work with the \`exportGlobals\` option (the \`mode\` option is \`pure\`): errors 1`] = `Array []`;
+
+exports[`"modules" option should work with the \`exportGlobals\` option (the \`mode\` option is \`pure\`): module 1`] = `
+"// Imports
+var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../src/runtime/api.js\\");
+exports = ___CSS_LOADER_API_IMPORT___(false);
+// Module
+exports.push([module.id, \\"._3OALfsKrVzw8QnGzfteWls {\\\\n  background-color: red;\\\\n}\\\\n\\\\n._3w1OTKuiiZvf8WY1tCPaZH ._1cmRmgT7HI056zoTdHDOVh {\\\\n  background-color: green;\\\\n}\\\\n\\\\n._3pB9KhpUqVA1pPH1Y8ei3y .baz {\\\\n  background-color: blue;\\\\n}\\\\n\\", \\"\\"]);
+// Exports
+exports.locals = {
+	\\"foo\\": \\"_3OALfsKrVzw8QnGzfteWls\\",
+	\\"one\\": \\"_3w1OTKuiiZvf8WY1tCPaZH\\",
+	\\"bar\\": \\"_1cmRmgT7HI056zoTdHDOVh\\",
+	\\"two\\": \\"_3pB9KhpUqVA1pPH1Y8ei3y\\",
+	\\"baz\\": \\"baz\\"
+};
+module.exports = exports;
+"
+`;
+
+exports[`"modules" option should work with the \`exportGlobals\` option (the \`mode\` option is \`pure\`): result 1`] = `
+Array [
+  Array [
+    "./modules/exportGlobals-pure/exportGlobals.css",
+    "._3OALfsKrVzw8QnGzfteWls {
+  background-color: red;
+}
+
+._3w1OTKuiiZvf8WY1tCPaZH ._1cmRmgT7HI056zoTdHDOVh {
+  background-color: green;
+}
+
+._3pB9KhpUqVA1pPH1Y8ei3y .baz {
+  background-color: blue;
+}
+",
+    "",
+  ],
+]
+`;
+
+exports[`"modules" option should work with the \`exportGlobals\` option (the \`mode\` option is \`pure\`): warnings 1`] = `Array []`;
diff --git a/test/__snapshots__/validate-options.test.js.snap b/test/__snapshots__/validate-options.test.js.snap
index e7f0351..bc1b236 100644
--- a/test/__snapshots__/validate-options.test.js.snap
+++ b/test/__snapshots__/validate-options.test.js.snap
@@ -48,10 +48,15 @@ exports[`validate options should throw an error on the "modules" option with "{"
  - options.modules.context should be a string."
 `;
 
+exports[`validate options should throw an error on the "modules" option with "{"exportGlobals":"invalid"}" value 1`] = `
+"Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
+ - options.modules.exportGlobals should be a boolean."
+`;
+
 exports[`validate options should throw an error on the "modules" option with "{"getLocalIdent":[]}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.getLocalIdent should be one of these:
@@ -74,7 +79,7 @@ exports[`validate options should throw an error on the "modules" option with "{"
 exports[`validate options should throw an error on the "modules" option with "{"localIdentRegExp":true}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.localIdentRegExp should be one of these:
@@ -87,7 +92,7 @@ exports[`validate options should throw an error on the "modules" option with "{"
 exports[`validate options should throw an error on the "modules" option with "{"mode":"globals"}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.mode should be one of these:
@@ -101,7 +106,7 @@ exports[`validate options should throw an error on the "modules" option with "{"
 exports[`validate options should throw an error on the "modules" option with "{"mode":"locals"}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.mode should be one of these:
@@ -115,7 +120,7 @@ exports[`validate options should throw an error on the "modules" option with "{"
 exports[`validate options should throw an error on the "modules" option with "{"mode":"pures"}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.mode should be one of these:
@@ -129,7 +134,7 @@ exports[`validate options should throw an error on the "modules" option with "{"
 exports[`validate options should throw an error on the "modules" option with "{"mode":true}" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules.mode should be one of these:
@@ -143,53 +148,53 @@ exports[`validate options should throw an error on the "modules" option with "{"
 exports[`validate options should throw an error on the "modules" option with "globals" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules should be a boolean.
     * options.modules should be one of these:
       \\"local\\" | \\"global\\" | \\"pure\\"
     * options.modules should be an object:
-      object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }"
+      object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }"
 `;
 
 exports[`validate options should throw an error on the "modules" option with "locals" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules should be a boolean.
     * options.modules should be one of these:
       \\"local\\" | \\"global\\" | \\"pure\\"
     * options.modules should be an object:
-      object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }"
+      object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }"
 `;
 
 exports[`validate options should throw an error on the "modules" option with "pures" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules should be a boolean.
     * options.modules should be one of these:
       \\"local\\" | \\"global\\" | \\"pure\\"
     * options.modules should be an object:
-      object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }"
+      object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }"
 `;
 
 exports[`validate options should throw an error on the "modules" option with "true" value 1`] = `
 "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
  - options.modules should be one of these:
-   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
+   boolean | \\"local\\" | \\"global\\" | \\"pure\\" | object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }
    -> Enables/Disables CSS Modules and their configuration (https://github.com/webpack-contrib/css-loader#modules).
    Details:
     * options.modules should be a boolean.
     * options.modules should be one of these:
       \\"local\\" | \\"global\\" | \\"pure\\"
     * options.modules should be an object:
-      object { mode?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }"
+      object { mode?, exportGlobals?, localIdentName?, localIdentRegExp?, context?, hashPrefix?, getLocalIdent? }"
 `;
 
 exports[`validate options should throw an error on the "onlyLocals" option with "true" value 1`] = `
diff --git a/test/fixtures/modules/exportGlobals-global/exportGlobals.css b/test/fixtures/modules/exportGlobals-global/exportGlobals.css
new file mode 100644
index 0000000..fea8c37
--- /dev/null
+++ b/test/fixtures/modules/exportGlobals-global/exportGlobals.css
@@ -0,0 +1,11 @@
+.foo {
+  background-color: red;
+}
+
+:local(.bar) {
+  background-color: green;
+}
+
+:global(.baz) {
+  background-color: blue;
+}
diff --git a/test/fixtures/modules/exportGlobals-global/exportGlobals.js b/test/fixtures/modules/exportGlobals-global/exportGlobals.js
new file mode 100644
index 0000000..17cc87d
--- /dev/null
+++ b/test/fixtures/modules/exportGlobals-global/exportGlobals.js
@@ -0,0 +1,5 @@
+import css from './exportGlobals.css';
+
+__export__ = css;
+
+export default css;
diff --git a/test/fixtures/modules/exportGlobals-local/exportGlobals.css b/test/fixtures/modules/exportGlobals-local/exportGlobals.css
new file mode 100644
index 0000000..fea8c37
--- /dev/null
+++ b/test/fixtures/modules/exportGlobals-local/exportGlobals.css
@@ -0,0 +1,11 @@
+.foo {
+  background-color: red;
+}
+
+:local(.bar) {
+  background-color: green;
+}
+
+:global(.baz) {
+  background-color: blue;
+}
diff --git a/test/fixtures/modules/exportGlobals-local/exportGlobals.js b/test/fixtures/modules/exportGlobals-local/exportGlobals.js
new file mode 100644
index 0000000..17cc87d
--- /dev/null
+++ b/test/fixtures/modules/exportGlobals-local/exportGlobals.js
@@ -0,0 +1,5 @@
+import css from './exportGlobals.css';
+
+__export__ = css;
+
+export default css;
diff --git a/test/fixtures/modules/exportGlobals-pure/exportGlobals.css b/test/fixtures/modules/exportGlobals-pure/exportGlobals.css
new file mode 100644
index 0000000..a334282
--- /dev/null
+++ b/test/fixtures/modules/exportGlobals-pure/exportGlobals.css
@@ -0,0 +1,11 @@
+.foo {
+  background-color: red;
+}
+
+.one :local(.bar) {
+  background-color: green;
+}
+
+.two :global(.baz) {
+  background-color: blue;
+}
diff --git a/test/fixtures/modules/exportGlobals-pure/exportGlobals.js b/test/fixtures/modules/exportGlobals-pure/exportGlobals.js
new file mode 100644
index 0000000..17cc87d
--- /dev/null
+++ b/test/fixtures/modules/exportGlobals-pure/exportGlobals.js
@@ -0,0 +1,5 @@
+import css from './exportGlobals.css';
+
+__export__ = css;
+
+export default css;
diff --git a/test/fixtures/modules/issue-1063/issue-1063.js b/test/fixtures/modules/issue-1063/issue-1063.js
index c602c8c..4544dd6 100644
--- a/test/fixtures/modules/issue-1063/issue-1063.js
+++ b/test/fixtures/modules/issue-1063/issue-1063.js
@@ -1,6 +1,7 @@
 import css1 from './local.css';
 import css2 from './global.css';
+import css3 from './pure.css';
 
-__export__ = css1 + css2;
+__export__ = css1 + css2 + css3;
 
-export default css1 + css2;
+export default css1 + css2 + css3;
diff --git a/test/fixtures/modules/issue-1063/pure.css b/test/fixtures/modules/issue-1063/pure.css
new file mode 100644
index 0000000..679c427
--- /dev/null
+++ b/test/fixtures/modules/issue-1063/pure.css
@@ -0,0 +1,3 @@
+.foo :local(.bar) {
+  color: red;
+}
diff --git a/test/modules-option.test.js b/test/modules-option.test.js
index b62a708..31762f6 100644
--- a/test/modules-option.test.js
+++ b/test/modules-option.test.js
@@ -570,6 +570,10 @@ describe('"modules" option', () => {
     const compiler = getCompiler('./modules/issue-1063/issue-1063.js', {
       modules: {
         mode: (resourcePath) => {
+          if (/pure.css$/i.test(resourcePath)) {
+            return 'pure';
+          }
+
           if (/global.css$/i.test(resourcePath)) {
             return 'global';
           }
@@ -582,10 +586,13 @@ describe('"modules" option', () => {
 
     expect(
       getModuleSource('./modules/issue-1063/local.css', stats)
-    ).toMatchSnapshot('module');
+    ).toMatchSnapshot('module with the `local` mode');
     expect(
       getModuleSource('./modules/issue-1063/global.css', stats)
-    ).toMatchSnapshot('module');
+    ).toMatchSnapshot('module with the `global` mode');
+    expect(
+      getModuleSource('./modules/issue-1063/pure.css', stats)
+    ).toMatchSnapshot('module with the `pure` mode');
     expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
       'result'
     );
@@ -615,4 +622,70 @@ describe('"modules" option', () => {
     expect(getWarnings(stats)).toMatchSnapshot('warnings');
     expect(getErrors(stats)).toMatchSnapshot('errors');
   });
+
+  it('should work with the `exportGlobals` option (the `mode` option is `global`)', async () => {
+    const compiler = getCompiler(
+      './modules/exportGlobals-global/exportGlobals.js',
+      {
+        modules: {
+          mode: 'local',
+          exportGlobals: true,
+        },
+      }
+    );
+    const stats = await compile(compiler);
+
+    expect(
+      getModuleSource('./modules/exportGlobals-global/exportGlobals.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 the `exportGlobals` option (the `mode` option is `local`)', async () => {
+    const compiler = getCompiler(
+      './modules/exportGlobals-local/exportGlobals.js',
+      {
+        modules: {
+          mode: 'global',
+          exportGlobals: true,
+        },
+      }
+    );
+    const stats = await compile(compiler);
+
+    expect(
+      getModuleSource('./modules/exportGlobals-local/exportGlobals.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 the `exportGlobals` option (the `mode` option is `pure`)', async () => {
+    const compiler = getCompiler(
+      './modules/exportGlobals-pure/exportGlobals.js',
+      {
+        modules: {
+          mode: 'pure',
+          exportGlobals: true,
+        },
+      }
+    );
+    const stats = await compile(compiler);
+
+    expect(
+      getModuleSource('./modules/exportGlobals-pure/exportGlobals.css', stats)
+    ).toMatchSnapshot('module');
+    expect(getExecutedCode('main.bundle.js', compiler, stats)).toMatchSnapshot(
+      'result'
+    );
+    expect(getWarnings(stats)).toMatchSnapshot('warnings');
+    expect(getErrors(stats)).toMatchSnapshot('errors');
+  });
 });
diff --git a/test/validate-options.test.js b/test/validate-options.test.js
index db5ad6c..96a595c 100644
--- a/test/validate-options.test.js
+++ b/test/validate-options.test.js
@@ -27,6 +27,7 @@ describe('validate options', () => {
         { getLocalIdent: () => {} },
         { localIdentRegExp: 'page-(.*)\\.js' },
         { localIdentRegExp: /page-(.*)\.js/ },
+        { exportGlobals: true },
       ],
       failure: [
         'true',
@@ -42,6 +43,7 @@ describe('validate options', () => {
         { hashPrefix: true },
         { getLocalIdent: [] },
         { localIdentRegExp: true },
+        { exportGlobals: 'invalid' },
       ],
     },
     sourceMap: {