Skip to content

Commit 4ab70fb

Browse files
PCreationsgajus
authored andcommitted
fix: handle multiple file import with dynamic resolution (fixes gajus#7 gajus#11 gajus#13 gajus#14 gajus#17) (gajus#12)
* fix: added escape hatch when testing attribute that do not have a name property (gajus#11) * fix: object expression generated on dynamic resolution now use quote to escape properties' name (gajus#14) * fix: getClassName now works as expected when multiple file use runtime resolution * fix: getClassName now works as expected when multiple file use runtime resolution
1 parent e3792b3 commit 4ab70fb

File tree

17 files changed

+119
-32
lines changed

17 files changed

+119
-32
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"build": "rm -fr ./dist && NODE_ENV=production babel ./src --out-dir ./dist --source-maps && npm run build-helper",
5353
"lint": "eslint ./src",
5454
"precommit": "npm run test",
55-
"test": "NODE_ENV=development npm run lint && npm run build && mocha --compilers js:babel-register && flow"
55+
"test": "NODE_ENV=development npm run lint && npm run build && NODE_ENV=test mocha --compilers js:babel-register && flow"
5656
},
5757
"version": "1.0.0"
5858
}

src/createObjectExpression.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const createObjectExpression = (t: BabelTypes, object: Object): ObjectExpression
2525

2626
properties.push(
2727
t.objectProperty(
28-
t.identifier(name),
28+
t.identifier('\'' + name + '\''),
2929
newValue
3030
)
3131
);

src/index.js

+35-20
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,22 @@ export default ({
1616
}: {
1717
types: BabelTypes
1818
}) => {
19-
let styleModuleImportMap;
20-
let importedHelperIndentifier;
21-
let styleModuleImportMapIdentifier;
19+
const filenameMap = {};
2220

23-
const setupFileForRuntimeResolution = (path) => {
21+
const setupFileForRuntimeResolution = (path, filename) => {
2422
const programPath = path.findParent((parentPath) => {
2523
return parentPath.isProgram();
2624
});
2725

28-
importedHelperIndentifier = programPath.scope.generateUidIdentifier('getClassName');
29-
styleModuleImportMapIdentifier = programPath.scope.generateUidIdentifier('styleModuleImportMap');
26+
filenameMap[filename].importedHelperIndentifier = programPath.scope.generateUidIdentifier('getClassName');
27+
filenameMap[filename].styleModuleImportMapIdentifier = programPath.scope.generateUidIdentifier('styleModuleImportMap');
3028

3129
programPath.unshiftContainer(
3230
'body',
3331
t.importDeclaration(
3432
[
3533
t.importDefaultSpecifier(
36-
importedHelperIndentifier
34+
filenameMap[filename].importedHelperIndentifier
3735
)
3836
],
3937
t.stringLiteral('babel-plugin-react-css-modules/dist/browser/getClassName')
@@ -49,12 +47,14 @@ export default ({
4947
'const',
5048
[
5149
t.variableDeclarator(
52-
styleModuleImportMapIdentifier,
53-
createObjectExpression(t, styleModuleImportMap)
50+
filenameMap[filename].styleModuleImportMapIdentifier,
51+
createObjectExpression(t, filenameMap[filename].styleModuleImportMap)
5452
)
5553
]
5654
)
5755
);
56+
// eslint-disable-next-line
57+
// console.log('setting up', filename, util.inspect(filenameMap,{depth: 5}))
5858
};
5959

6060
return {
@@ -65,13 +65,15 @@ export default ({
6565
return;
6666
}
6767

68+
const filename = stats.file.opts.filename;
6869
const targetFileDirectoryPath = dirname(stats.file.opts.filename);
6970
const targetResourcePath = resolve(targetFileDirectoryPath, path.node.source.value);
7071

7172
let styleImportName: string;
7273

7374
if (path.node.specifiers.length === 0) {
74-
styleImportName = 'random-' + Math.random();
75+
// eslint-disable-next-line no-process-env
76+
styleImportName = process.env.NODE_ENV === 'test' ? 'random-test' : 'random-' + Math.random();
7577
} else if (path.node.specifiers.length === 1) {
7678
styleImportName = path.node.specifiers[0].local.name;
7779
} else {
@@ -81,36 +83,49 @@ export default ({
8183
throw new Error('Unexpected use case.');
8284
}
8385

84-
styleModuleImportMap[styleImportName] = requireCssModule(targetResourcePath, {
86+
filenameMap[filename].styleModuleImportMap[styleImportName] = requireCssModule(targetResourcePath, {
8587
generateScopedName: stats.opts.generateScopedName
8688
});
8789
},
88-
JSXElement (path: Object): void {
90+
JSXElement (path: Object, stats: Object): void {
91+
const filename = stats.file.opts.filename;
8992
const styleNameAttribute = path.node.openingElement.attributes
9093
.find((attribute) => {
91-
return attribute.name.name === 'styleName';
94+
return typeof attribute.name !== 'undefined' && attribute.name.name === 'styleName';
9295
});
9396

9497
if (!styleNameAttribute) {
9598
return;
9699
}
97100

98101
if (t.isStringLiteral(styleNameAttribute.value)) {
99-
resolveStringLiteral(path, styleModuleImportMap, styleNameAttribute);
102+
resolveStringLiteral(
103+
path,
104+
filenameMap[filename].styleModuleImportMap,
105+
styleNameAttribute
106+
);
100107

101108
return;
102109
}
103110

104111
if (t.isJSXExpressionContainer(styleNameAttribute.value)) {
105-
if (!importedHelperIndentifier) {
106-
setupFileForRuntimeResolution(path);
112+
if (!filenameMap[filename].importedHelperIndentifier) {
113+
setupFileForRuntimeResolution(path, filename);
107114
}
108-
109-
replaceJsxExpressionContainer(t, styleNameAttribute, importedHelperIndentifier, styleModuleImportMapIdentifier);
115+
replaceJsxExpressionContainer(
116+
t,
117+
styleNameAttribute,
118+
filenameMap[filename].importedHelperIndentifier,
119+
filenameMap[filename].styleModuleImportMapIdentifier
120+
);
110121
}
111122
},
112-
Program () {
113-
styleModuleImportMap = {};
123+
Program (path: Object, stats: Object): void {
124+
const filename = stats.file.opts.filename;
125+
126+
filenameMap[filename] = {
127+
styleModuleImportMap: {}
128+
};
114129
}
115130
}
116131
};

src/resolveStringLiteral.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type {
1111
export default (path: Object, styleModuleImportMap: StyleModuleImportMapType, styleNameAttribute: JSXAttribute): void => {
1212
const classNameAttribute = path.node.openingElement.attributes
1313
.find((attribute) => {
14-
return attribute.name.name === 'className';
14+
return typeof attribute.name !== 'undefined' && attribute.name.name === 'className';
1515
});
1616

1717
const resolvedStyleName = getClassName(styleNameAttribute.value.value, styleModuleImportMap);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import './bar.css';
2+
3+
const props = {
4+
foo: 'bar'
5+
};
6+
7+
<div styleName="a" {...props}></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,7 @@
1+
import './bar.css';
2+
3+
const props = {
4+
foo: 'bar'
5+
};
6+
7+
<div className="bar__a" {...props}></div>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"plugins": [
3+
[
4+
"../../../../src",
5+
{
6+
"generateScopedName": "[name]__[local]"
7+
}
8+
]
9+
]
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import bar from './bar.css';
2+
import './foo.css';
3+
4+
const styleNameBar = 'bar.a-b';
5+
const styleNameFoo = 'a-b';
6+
7+
<div styleName={styleNameBar}></div>;
8+
<div styleName={styleNameFoo}></div>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.a-b {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import _getClassName from 'babel-plugin-react-css-modules/dist/browser/getClassName';
2+
import bar from './bar.css';
3+
import './foo.css';
4+
5+
const _styleModuleImportMap = {
6+
'bar': {
7+
'a-b': 'bar__a-b'
8+
},
9+
'random-test': {
10+
'a-b': 'foo__a-b'
11+
}
12+
};
13+
const styleNameBar = 'bar.a-b';
14+
const styleNameFoo = 'a-b';
15+
16+
<div styleName={_getClassName(styleNameBar, _styleModuleImportMap)}></div>;
17+
<div styleName={_getClassName(styleNameFoo, _styleModuleImportMap)}></div>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.a-b {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"plugins": [
3+
[
4+
"../../../../src",
5+
{
6+
"generateScopedName": "[name]__[local]"
7+
}
8+
]
9+
]
10+
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
import foo from './bar.css';
1+
import bar from './bar.css';
2+
import './foo.css';
23

3-
const styleNameValue = 'a';
4+
const styleNameBar = 'bar.a-b';
5+
const styleNameFoo = 'a-b';
46

5-
<div styleName={styleNameValue}></div>;
7+
<div styleName={styleNameBar}></div>;
8+
<div styleName={styleNameFoo}></div>;
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
.a {}
1+
.a-b {}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
import _getClassName from 'babel-plugin-react-css-modules/dist/browser/getClassName';
2-
import foo from './bar.css';
2+
import bar from './bar.css';
3+
import './foo.css';
34

45
const _styleModuleImportMap = {
5-
foo: {
6-
a: 'bar__a'
6+
'bar': {
7+
'a-b': 'bar__a-b'
8+
},
9+
'random-test': {
10+
'a-b': 'foo__a-b'
711
}
812
};
9-
const styleNameValue = 'a';
13+
const styleNameBar = 'bar.a-b';
14+
const styleNameFoo = 'a-b';
1015

11-
<div styleName={_getClassName(styleNameValue, _styleModuleImportMap)}></div>;
16+
<div styleName={_getClassName(styleNameBar, _styleModuleImportMap)}></div>;
17+
<div styleName={_getClassName(styleNameFoo, _styleModuleImportMap)}></div>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.a-b {}

0 commit comments

Comments
 (0)