Skip to content

Commit cfc1432

Browse files
refactor: move the localsConvention option to the modules option
BREAKING CHANGE: the `localsConvention` option was moved to the `module` option (`modules.localsConvention`)
1 parent 56c0427 commit cfc1432

11 files changed

+1011
-558
lines changed

README.md

+59-58
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,15 @@ module.exports = {
109109

110110
## Options
111111

112-
| Name | Type | Default | Description |
113-
| :-----------------------------------------: | :-------------------------: | :----------------: | :--------------------------------------------------------------------- |
114-
| **[`url`](#url)** | `{Boolean\|Function}` | `true` | Enables/Disables `url`/`image-set` functions handling |
115-
| **[`import`](#import)** | `{Boolean\|Function}` | `true` | Enables/Disables `@import` at-rules handling |
116-
| **[`modules`](#modules)** | `{Boolean\|String\|Object}` | `false` | Enables/Disables CSS Modules and their configuration |
117-
| **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps |
118-
| **[`importLoaders`](#importloaders)** | `{Number}` | `0` | Enables/Disables or setups number of loaders applied before CSS loader |
119-
| **[`localsConvention`](#localsconvention)** | `{String}` | `'asIs'` | Style of exported classnames |
120-
| **[`onlyLocals`](#onlylocals)** | `{Boolean}` | `false` | Export only locals |
121-
| **[`esModule`](#esmodule)** | `{Boolean}` | `false` | Use ES modules syntax |
112+
| Name | Type | Default | Description |
113+
| :-----------------------------------: | :-------------------------: | :----------------: | :--------------------------------------------------------------------- |
114+
| **[`url`](#url)** | `{Boolean\|Function}` | `true` | Enables/Disables `url`/`image-set` functions handling |
115+
| **[`import`](#import)** | `{Boolean\|Function}` | `true` | Enables/Disables `@import` at-rules handling |
116+
| **[`modules`](#modules)** | `{Boolean\|String\|Object}` | `false` | Enables/Disables CSS Modules and their configuration |
117+
| **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps |
118+
| **[`importLoaders`](#importloaders)** | `{Number}` | `0` | Enables/Disables or setups number of loaders applied before CSS loader |
119+
| **[`onlyLocals`](#onlylocals)** | `{Boolean}` | `false` | Export only locals |
120+
| **[`esModule`](#esmodule)** | `{Boolean}` | `false` | Use ES modules syntax |
122121

123122
### `url`
124123

@@ -532,6 +531,7 @@ module.exports = {
532531
mode: 'local',
533532
exportGlobals: true,
534533
localIdentName: '[path][name]__[local]--[hash:base64:5]',
534+
localsConvention: 'camelCase',
535535
context: path.resolve(__dirname, 'src'),
536536
hashPrefix: 'my-custom-hash',
537537
},
@@ -756,6 +756,55 @@ module.exports = {
756756
};
757757
```
758758

759+
### `localsConvention`
760+
761+
Type: `String`
762+
Default: `'asIs'`
763+
764+
Style of exported classnames.
765+
766+
By default, the exported JSON keys mirror the class names (i.e `asIs` value).
767+
768+
| Name | Type | Description |
769+
| :-------------------: | :--------: | :----------------------------------------------------------------------------------------------- |
770+
| **`'asIs'`** | `{String}` | Class names will be exported as is. |
771+
| **`'camelCase'`** | `{String}` | Class names will be camelized, the original class name will not to be removed from the locals |
772+
| **`'camelCaseOnly'`** | `{String}` | Class names will be camelized, the original class name will be removed from the locals |
773+
| **`'dashes'`** | `{String}` | Only dashes in class names will be camelized |
774+
| **`'dashesOnly'`** | `{String}` | Dashes in class names will be camelized, the original class name will be removed from the locals |
775+
776+
**file.css**
777+
778+
```css
779+
.class-name {
780+
}
781+
```
782+
783+
**file.js**
784+
785+
```js
786+
import { className } from 'file.css';
787+
```
788+
789+
**webpack.config.js**
790+
791+
```js
792+
module.exports = {
793+
module: {
794+
rules: [
795+
{
796+
test: /\.css$/i,
797+
loader: 'css-loader',
798+
options: {
799+
mode: 'local',
800+
localsConvention: 'camelCase',
801+
},
802+
},
803+
],
804+
},
805+
};
806+
```
807+
759808
##### `context`
760809

761810
Type: `String`
@@ -930,54 +979,6 @@ module.exports = {
930979

931980
This may change in the future when the module system (i. e. webpack) supports loader matching by origin.
932981

933-
### `localsConvention`
934-
935-
Type: `String`
936-
Default: `'asIs'`
937-
938-
Style of exported classnames.
939-
940-
By default, the exported JSON keys mirror the class names (i.e `asIs` value).
941-
942-
| Name | Type | Description |
943-
| :-------------------: | :--------: | :----------------------------------------------------------------------------------------------- |
944-
| **`'asIs'`** | `{String}` | Class names will be exported as is. |
945-
| **`'camelCase'`** | `{String}` | Class names will be camelized, the original class name will not to be removed from the locals |
946-
| **`'camelCaseOnly'`** | `{String}` | Class names will be camelized, the original class name will be removed from the locals |
947-
| **`'dashes'`** | `{String}` | Only dashes in class names will be camelized |
948-
| **`'dashesOnly'`** | `{String}` | Dashes in class names will be camelized, the original class name will be removed from the locals |
949-
950-
**file.css**
951-
952-
```css
953-
.class-name {
954-
}
955-
```
956-
957-
**file.js**
958-
959-
```js
960-
import { className } from 'file.css';
961-
```
962-
963-
**webpack.config.js**
964-
965-
```js
966-
module.exports = {
967-
module: {
968-
rules: [
969-
{
970-
test: /\.css$/i,
971-
loader: 'css-loader',
972-
options: {
973-
localsConvention: 'camelCase',
974-
},
975-
},
976-
],
977-
},
978-
};
979-
```
980-
981982
### `onlyLocals`
982983

983984
Type: `Boolean`

src/index.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Warning from './Warning';
1313
import schema from './options.json';
1414
import { icssParser, importParser, urlParser } from './plugins';
1515
import {
16+
getModulesOptions,
1617
getPreRequester,
1718
getExportCode,
1819
getFilter,
@@ -31,7 +32,6 @@ export default function loader(content, map, meta) {
3132
baseDataPath: 'options',
3233
});
3334

34-
const callback = this.async();
3535
const sourceMap =
3636
typeof options.sourceMap === 'boolean' ? options.sourceMap : this.sourceMap;
3737
const plugins = [];
@@ -41,8 +41,12 @@ export default function loader(content, map, meta) {
4141
const urlHandler = (url) =>
4242
stringifyRequest(this, preRequester(options.importLoaders) + url);
4343

44+
let modulesOptions;
45+
4446
if (shouldUseModulesPlugins(options.modules, this.resourcePath)) {
45-
plugins.push(...getModulesPlugins(options, this));
47+
modulesOptions = getModulesOptions(options, this);
48+
49+
plugins.push(...getModulesPlugins(modulesOptions, this));
4650

4751
const icssResolver = this.getResolve({
4852
mainFields: ['css', 'style', 'main', '...'],
@@ -104,6 +108,8 @@ export default function loader(content, map, meta) {
104108
}
105109
}
106110

111+
const callback = this.async();
112+
107113
postcss(plugins)
108114
.process(content, {
109115
from: this.resourcePath,
@@ -171,7 +177,6 @@ export default function loader(content, map, meta) {
171177
);
172178
});
173179

174-
const { localsConvention } = options;
175180
const esModule =
176181
typeof options.esModule !== 'undefined' ? options.esModule : false;
177182

@@ -188,9 +193,9 @@ export default function loader(content, map, meta) {
188193
const exportCode = getExportCode(
189194
exports,
190195
exportType,
191-
localsConvention,
192196
icssReplacements,
193-
esModule
197+
esModule,
198+
modulesOptions
194199
);
195200

196201
return callback(null, `${importCode}${moduleCode}${exportCode}`);

src/options.json

+10-4
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@
7575
}
7676
]
7777
},
78+
"localsConvention": {
79+
"description": "Style of exported classnames (https://github.com/webpack-contrib/css-loader#localsconvention).",
80+
"enum": [
81+
"asIs",
82+
"camelCase",
83+
"camelCaseOnly",
84+
"dashes",
85+
"dashesOnly"
86+
]
87+
},
7888
"context": {
7989
"type": "string"
8090
},
@@ -110,10 +120,6 @@
110120
}
111121
]
112122
},
113-
"localsConvention": {
114-
"description": "Style of exported classnames (https://github.com/webpack-contrib/css-loader#localsconvention).",
115-
"enum": ["asIs", "camelCase", "camelCaseOnly", "dashes", "dashesOnly"]
116-
},
117123
"onlyLocals": {
118124
"description": "Export only locals (https://github.com/webpack-contrib/css-loader#onlylocals).",
119125
"type": "boolean"

src/utils.js

+14-7
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,16 @@ function shouldUseModulesPlugins(modules, resourcePath) {
136136
return true;
137137
}
138138

139-
function getModulesPlugins(options, loaderContext) {
139+
function getModulesOptions(options, loaderContext) {
140140
let modulesOptions = {
141141
mode: 'local',
142-
exportGlobals: false,
143142
localIdentName: '[hash:base64]',
143+
// eslint-disable-next-line no-undefined
144+
localIdentRegExp: undefined,
145+
localsConvention: 'asIs',
144146
getLocalIdent,
145147
hashPrefix: '',
146-
localIdentRegExp: null,
148+
exportGlobals: false,
147149
};
148150

149151
if (
@@ -153,13 +155,17 @@ function getModulesPlugins(options, loaderContext) {
153155
modulesOptions.mode =
154156
typeof options.modules === 'string' ? options.modules : 'local';
155157
} else {
156-
modulesOptions = Object.assign({}, modulesOptions, options.modules);
158+
modulesOptions = { ...modulesOptions, ...options.modules };
157159
}
158160

159161
if (typeof modulesOptions.mode === 'function') {
160162
modulesOptions.mode = modulesOptions.mode(loaderContext.resourcePath);
161163
}
162164

165+
return modulesOptions;
166+
}
167+
168+
function getModulesPlugins(modulesOptions, loaderContext) {
163169
let plugins = [];
164170

165171
try {
@@ -357,9 +363,9 @@ function dashesCamelCase(str) {
357363
function getExportCode(
358364
exports,
359365
exportType,
360-
localsConvention,
361366
icssReplacements,
362-
esModule
367+
esModule,
368+
modulesOptions
363369
) {
364370
let code = '';
365371
let localsCode = '';
@@ -373,7 +379,7 @@ function getExportCode(
373379
};
374380

375381
for (const { name, value } of exports) {
376-
switch (localsConvention) {
382+
switch (modulesOptions.localsConvention) {
377383
case 'camelCase': {
378384
addExportToLocalsCode(name, value);
379385

@@ -467,6 +473,7 @@ function isUrlRequestable(url) {
467473
export {
468474
normalizeUrl,
469475
getFilter,
476+
getModulesOptions,
470477
getModulesPlugins,
471478
normalizeSourceMap,
472479
getPreRequester,

0 commit comments

Comments
 (0)