Skip to content

Commit 5101880

Browse files
added an option to change the merge order
1 parent 17d261e commit 5101880

File tree

11 files changed

+79
-6
lines changed

11 files changed

+79
-6
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ Configure the options for the plugin within your `.babelrc` as follows:
193193
|`generateScopedName`|`?GenerateScopedNameConfigurationType`|Refer to [Generating scoped names](https://github.com/css-modules/postcss-modules#generating-scoped-names)|`[path]___[name]__[local]___[hash:base64:5]`|
194194
|`removeImport`|`boolean`|Remove the matching style import. This option is used to enable server-side rendering.|`false`|
195195
|`webpackHotModuleReloading`|`boolean`|Enables hot reloading of CSS in webpack|`false`|
196+
|`styleNameFirst`|`boolean`|Changes the ordering of merging className with styleName|`false`|
196197
|`handleMissingStyleName`|`"throw"`, `"warn"`, `"ignore"`|Determines what should be done for undefined CSS modules (using a `styleName` for which there is no CSS module defined). Setting this option to `"ignore"` is equivalent to setting `errorWhenNotFound: false` in [react-css-modules](https://github.com/gajus/react-css-modules#errorwhennotfound). |`"throw"`|
197198

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

src/conditionalClassMerge.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,24 @@ import {
1111
export default (
1212
classNameExpression: any,
1313
styleNameExpression: any,
14+
styleNameFirst: boolean,
1415
): any => {
16+
if (styleNameFirst) {
17+
return binaryExpression(
18+
'+',
19+
styleNameExpression,
20+
conditionalExpression(
21+
classNameExpression,
22+
binaryExpression(
23+
'+',
24+
stringLiteral(' '),
25+
classNameExpression
26+
),
27+
stringLiteral('')
28+
)
29+
);
30+
}
31+
1532
return binaryExpression(
1633
'+',
1734
conditionalExpression(

src/index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,16 @@ export default ({
188188
}
189189

190190
const handleMissingStyleName = stats.opts && stats.opts.handleMissingStyleName || optionsDefaults.handleMissingStyleName;
191+
const styleNameFirst = stats.opts && stats.opts.styleNameFirst || false;
191192

192193
if (t.isStringLiteral(styleNameAttribute.value)) {
193194
resolveStringLiteral(
194195
path,
195196
filenameMap[filename].styleModuleImportMap,
196197
styleNameAttribute,
197198
{
198-
handleMissingStyleName
199+
handleMissingStyleName,
200+
styleNameFirst
199201
}
200202
);
201203

@@ -213,7 +215,8 @@ export default ({
213215
filenameMap[filename].importedHelperIndentifier,
214216
filenameMap[filename].styleModuleImportMapIdentifier,
215217
{
216-
handleMissingStyleName
218+
handleMissingStyleName,
219+
styleNameFirst
217220
}
218221
);
219222
}

src/replaceJsxExpressionContainer.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ export default (
6262
path.node.openingElement.attributes.push(jSXAttribute(
6363
jSXIdentifier('className'),
6464
jSXExpressionContainer(
65+
options.styleNameFirst ?
66+
binaryExpression(
67+
'+',
68+
styleNameExpression,
69+
t.stringLiteral(' ' + classNameAttribute.value.value),
70+
) :
6571
binaryExpression(
6672
'+',
6773
t.stringLiteral(classNameAttribute.value.value + ' '),
@@ -75,7 +81,8 @@ export default (
7581
jSXExpressionContainer(
7682
conditionalClassMerge(
7783
classNameAttribute.value.expression,
78-
styleNameExpression
84+
styleNameExpression,
85+
options.styleNameFirst
7986
)
8087
)
8188
));

src/resolveStringLiteral.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,16 @@ export default (path: *, styleModuleImportMap: StyleModuleImportMapType, styleNa
3030

3131
if (classNameAttribute) {
3232
if (isStringLiteral(classNameAttribute.value)) {
33-
classNameAttribute.value.value += ' ' + resolvedStyleName;
33+
if (options.styleNameFirst) {
34+
classNameAttribute.value.value = resolvedStyleName + ' ' + classNameAttribute.value.value;
35+
} else {
36+
classNameAttribute.value.value += ' ' + resolvedStyleName;
37+
}
3438
} else if (isJSXExpressionContainer(classNameAttribute.value)) {
3539
classNameAttribute.value.expression = conditionalClassMerge(
3640
classNameAttribute.value.expression,
37-
stringLiteral(resolvedStyleName)
41+
stringLiteral(resolvedStyleName),
42+
options.styleNameFirst
3843
);
3944
} else {
4045
throw new Error('Unexpected attribute value.');

src/schemas/optionsSchema.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
"webpackHotModuleReloading": {
4545
"type": "boolean"
4646
},
47+
"styleNameFirst": {
48+
"type": "boolean"
49+
},
4750
"handleMissingStyleName": {
4851
"enum": ["throw", "warn", "ignore"]
4952
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import './bar.css';
2+
3+
<div className='apple banana' styleName="a"></div>;
4+
5+
<div className={this.props.className} styleName="a"></div>;
6+
7+
<div className={Math.random() > 0.5 ? 'apple' : 'banana'} styleName="a"></div>;
8+
9+
<div className={this.props.className} styleName={foo}></div>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.a {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import _getClassName from 'babel-plugin-react-css-modules/dist/browser/getClassName';
2+
import './bar.css';
3+
4+
const _styleModuleImportMap = {
5+
'./bar.css': {
6+
'a': 'bar__a'
7+
}
8+
};
9+
<div className="bar__a apple banana"></div>;
10+
11+
<div className={'bar__a' + (this.props.className ? ' ' + this.props.className : '')}></div>;
12+
13+
<div className={'bar__a' + ((Math.random() > 0.5 ? 'apple' : 'banana') ? ' ' + (Math.random() > 0.5 ? 'apple' : 'banana') : '')}></div>;
14+
15+
<div className={_getClassName(foo, _styleModuleImportMap) + (this.props.className ? ' ' + this.props.className : '')}></div>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"plugins": [
3+
[
4+
"../../../../src",
5+
{
6+
"generateScopedName": "[name]__[local]",
7+
"styleNameFirst": true
8+
}
9+
]
10+
]
11+
}

test/fixtures/react-css-modules/provides handleMissingStyleName to getClassName at runtime/expected.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ const _styleModuleImportMap = {
99
const styleNameFoo = 'a-c';
1010

1111
<div className={_getClassName(styleNameFoo, _styleModuleImportMap, {
12-
'handleMissingStyleName': 'ignore'
12+
'handleMissingStyleName': 'ignore',
13+
'styleNameFirst': false
1314
})}></div>;

0 commit comments

Comments
 (0)