Skip to content

Commit d7d3f5c

Browse files
committed
feat: allow generateScopedName configuration as a function
1 parent bd75572 commit d7d3f5c

File tree

6 files changed

+52
-14
lines changed

6 files changed

+52
-14
lines changed

README.md

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,30 @@ NODE_ENV=production ./test
170170

171171
## Configuration
172172

173-
|Name|Description|Default|
174-
|---|---|---|
175-
|`context`|Must match webpack [`context`](https://webpack.github.io/docs/configuration.html#context) configuration. [`css-loader`](https://github.com/webpack/css-loader) inherits `context` values from webpack. Other CSS module implementations might use different context resolution logic.|`process.cwd()`|
176-
|`exclude`| a RegExp that will exclude otherwise included files e.g., to exclude all styles from node_modules `exclude: 'node_modules'`|
177-
|`filetypes`|Configure [postcss syntax loaders](https://github.com/postcss/postcss#syntaxes) like sugerss, LESS and SCSS and extra plugins for them. ||
178-
|`generateScopedName`|Refer to [Generating scoped names](https://github.com/css-modules/postcss-modules#generating-scoped-names)|`[path]___[name]__[local]___[hash:base64:5]`|
179-
|`removeImport`|Remove the matching style import. This option is used to enable server-side rendering.|`false`|
180-
|`webpackHotModuleReloading`|Enables hot reloading of CSS in webpack|`false`|
173+
```js
174+
type FiletypeOptionsType = {|
175+
+syntax: string,
176+
+plugins?: $ReadOnlyArray<string>
177+
|};
178+
179+
type FiletypesConfigurationType = {
180+
[key: string]: FiletypeOptionsType
181+
};
182+
183+
type GenerateScopedNameType = (localName: string, resourcePath: string) => string;
184+
185+
type GenerateScopedNameConfigurationType = GenerateScopedNameType | string;
186+
187+
```
188+
189+
|Name|Type|Description|Default|
190+
|---|---|---|---|
191+
|`context`|`string`|Must match webpack [`context`](https://webpack.github.io/docs/configuration.html#context) configuration. [`css-loader`](https://github.com/webpack/css-loader) inherits `context` values from webpack. Other CSS module implementations might use different context resolution logic.|`process.cwd()`|
192+
|`exclude`|`string`|A RegExp that will exclude otherwise included files e.g., to exclude all styles from node_modules `exclude: 'node_modules'`|
193+
|`filetypes`|`?FiletypesConfigurationType`|Configure [postcss syntax loaders](https://github.com/postcss/postcss#syntaxes) like sugerss, LESS and SCSS and extra plugins for them. ||
194+
|`generateScopedName`|`?GenerateScopedNameConfigurationType`|Refer to [Generating scoped names](https://github.com/css-modules/postcss-modules#generating-scoped-names)|`[path]___[name]__[local]___[hash:base64:5]`|
195+
|`removeImport`|`boolean`|Remove the matching style import. This option is used to enable server-side rendering.|`false`|
196+
|`webpackHotModuleReloading`|`boolean`|Enables hot reloading of CSS in webpack|`false`|
181197

182198
Missing a configuration? [Raise an issue](https://github.com/gajus/babel-plugin-react-css-modules/issues/new?title=New%20configuration:).
183199

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
},
77
"dependencies": {
88
"ajv": "^4.11.4",
9+
"ajv-keywords": "^2.1.0",
910
"babel-plugin-syntax-jsx": "^6.18.0",
1011
"babel-types": "^6.19.0",
1112
"generic-names": "^1.0.2",

src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
} from 'path';
77
import babelPluginJsxSyntax from 'babel-plugin-syntax-jsx';
88
import BabelTypes from 'babel-types';
9+
import ajvKeywords from 'ajv-keywords';
910
import Ajv from 'ajv';
1011
import optionsSchema from './schemas/optionsSchema.json';
1112
import createObjectExpression from './createObjectExpression';
@@ -15,6 +16,8 @@ import replaceJsxExpressionContainer from './replaceJsxExpressionContainer';
1516

1617
const ajv = new Ajv();
1718

19+
ajvKeywords(ajv);
20+
1821
const validate = ajv.compile(optionsSchema);
1922

2023
export default ({

src/requireCssModule.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Parser from 'postcss-modules-parser';
1515
import Scope from 'postcss-modules-scope';
1616
import Values from 'postcss-modules-values';
1717
import type {
18+
GenerateScopedNameConfigurationType,
1819
StyleModuleMapType
1920
} from './types';
2021

@@ -80,18 +81,24 @@ const getTokens = (runner, cssSourceFilePath: string, filetypeOptions: ?Filetype
8081
};
8182

8283
type OptionsType = {|
83-
generateScopedName?: string,
8484
filetypes: FiletypesConfigurationType,
85+
generateScopedName?: GenerateScopedNameConfigurationType,
8586
context?: string
8687
|};
8788

8889
export default (cssSourceFilePath: string, options: OptionsType): StyleModuleMapType => {
8990
// eslint-disable-next-line prefer-const
9091
let runner;
9192

92-
const scopedName = genericNames(options.generateScopedName || '[path]___[name]__[local]___[hash:base64:5]', {
93-
context: options.context || process.cwd()
94-
});
93+
let generateScopedName;
94+
95+
if (options.generateScopedName && typeof options.generateScopedName === 'function') {
96+
generateScopedName = options.generateScopedName;
97+
} else {
98+
generateScopedName = genericNames(options.generateScopedName || '[path]___[name]__[local]___[hash:base64:5]', {
99+
context: options.context || process.cwd()
100+
});
101+
}
95102

96103
const filetypeOptions = getFiletypeOptions(cssSourceFilePath, options.filetypes);
97104

@@ -110,7 +117,7 @@ export default (cssSourceFilePath: string, options: OptionsType): StyleModuleMap
110117
LocalByDefault,
111118
ExtractImports,
112119
new Scope({
113-
generateScopedName: scopedName
120+
generateScopedName
114121
}),
115122
new Parser({
116123
fetch

src/schemas/optionsSchema.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@
2929
"type": "object"
3030
},
3131
"generateScopedName": {
32-
"type": "string"
32+
"oneOf": [
33+
{
34+
"type": "string"
35+
},
36+
{
37+
"typeof": "function"
38+
}
39+
]
3340
},
3441
"removeImport": {
3542
"type": "boolean"

src/types.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ export type StyleModuleMapType = {
77
export type StyleModuleImportMapType = {
88
[key: string]: StyleModuleMapType
99
};
10+
11+
export type GenerateScopedNameType = (localName: string, resourcePath: string) => string;
12+
13+
export type GenerateScopedNameConfigurationType = GenerateScopedNameType | string;

0 commit comments

Comments
 (0)