Skip to content

Commit e988338

Browse files
allow to specify function to processCss, preprocessCss, append, prepend, generateScopedName, closes michalkvasnicak#2
1 parent 6f782d3 commit e988338

9 files changed

+180
-4
lines changed

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,25 @@ npm install --save-dev babel-plugin-css-modules-transform
5656
```json
5757
{
5858
"plugins": [
59-
["css-modules-transform", { "generateScopedName": "[name]__[local]___[hash:base64:5]" }]
59+
[
60+
"css-modules-transform", {
61+
"generateScopedName": "[name]__[local]___[hash:base64:5]", // in case you don't want to use a function
62+
"generateScopedName": "./path/to/module-exporting-a-function.js", // in case you want to use a function
63+
"generateScopedName": "npm-module-name",
64+
"preprocessCss": "./path/to/module-exporting-a-function.js",
65+
"preprocessCss": "npm-module-name",
66+
"processCss": "./path/to/module-exporting-a-function.js",
67+
"processCss": "npm-module-name",
68+
"append": [
69+
"npm-module-name",
70+
"./path/to/module-exporting-a-function.js"
71+
],
72+
"prepend": [
73+
"npm-module-name",
74+
"./path/to/module-exporting-a-function.js"
75+
],
76+
}
77+
]
6078
]
6179
}
6280
```

src/index.js

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
import { resolve, dirname } from 'path';
22

3+
const simpleRequires = [
4+
'createImportedName',
5+
'generateScopedName',
6+
'processCss',
7+
'preprocessCss'
8+
];
9+
10+
const complexRequires = [
11+
'append',
12+
'prepend'
13+
];
14+
315
const defaultOptions = {
416
generateScopedName: '[name]__[local]___[hash:base64:5]'
517
};
@@ -8,7 +20,83 @@ export default function transformCssModules({ types: t }) {
820
return {
921
visitor: {
1022
CallExpression(path, { file, opts }) {
11-
require('css-modules-require-hook')({ ...defaultOptions, ...opts });
23+
const currentConfig = { ...defaultOptions, ...opts };
24+
25+
// check if there are simple requires and if they are functions
26+
simpleRequires.forEach(key => {
27+
if (typeof currentConfig[key] !== 'string') {
28+
return;
29+
}
30+
31+
const modulePath = resolve(process.cwd(), currentConfig[key]);
32+
33+
// this one can be require or string
34+
if (key === 'generateScopedName') {
35+
try {
36+
// if it is existing file, require it, otherwise use value
37+
currentConfig[key] = require(modulePath);
38+
} catch (e) {
39+
try {
40+
currentConfig[key] = require(currentConfig[key]);
41+
} catch (_e) {
42+
// do nothing, because it is not a valid path
43+
}
44+
}
45+
46+
if (typeof currentConfig[key] !== 'function' && typeof currentConfig[key] !== 'string') {
47+
throw new Error(`Configuration '${key}' is not a string or function.`);
48+
}
49+
50+
return;
51+
}
52+
53+
if (currentConfig.hasOwnProperty(key)) {
54+
try {
55+
currentConfig[key] = require(modulePath);
56+
} catch (e) {
57+
try {
58+
currentConfig[key] = require(currentConfig[key]);
59+
} catch (_e) {
60+
// do nothing because it is not a valid path
61+
}
62+
}
63+
64+
if (typeof currentConfig[key] !== 'function') {
65+
throw new Error(`Module '${modulePath}' does not exist or is not a function.`);
66+
}
67+
}
68+
});
69+
70+
complexRequires.forEach(key => {
71+
if (!currentConfig.hasOwnProperty(key)) {
72+
return;
73+
}
74+
75+
if (!Array.isArray(currentConfig[key])) {
76+
throw new Error(`Configuration '${key}' has to be an array.`);
77+
}
78+
79+
currentConfig[key].forEach((plugin, index) => {
80+
// first try to load it using npm
81+
try {
82+
currentConfig[key][index] = require(plugin);
83+
} catch (e) {
84+
try {
85+
currentConfig[key][index] = require(resolve(process.cwd(), path));
86+
} catch (_e) {
87+
// do nothing
88+
}
89+
}
90+
91+
if (typeof currentConfig[key][index] !== 'function') {
92+
throw new Error(`Configuration '${key}' has to be valid path to a module at index ${index} or it does not export a function.`);
93+
}
94+
95+
currentConfig[key][index] = currentConfig[key][index]();
96+
});
97+
});
98+
99+
require('css-modules-require-hook')(currentConfig);
12100

13101
const { callee: { name: calleeName }, arguments: args } = path.node;
14102

test/fixtures/append.module.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = function() {};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};

test/fixtures/prepend.module.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};

test/fixtures/preprocessCss.module.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};

test/fixtures/processCss.module.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};

test/index.spec.js

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { resolve } from 'path';
44
import { readFileSync } from 'fs';
55

66
describe('babel-plugin-css-modules-transform', () => {
7-
function transform(path) {
7+
function transform(path, configuration = {}) {
88
return babel.transformFileSync(resolve(__dirname, path), {
99
plugins: [
1010
'transform-strict-mode',
@@ -14,7 +14,7 @@ describe('babel-plugin-css-modules-transform', () => {
1414
'transform-object-rest-spread',
1515
'transform-es2015-spread',
1616
'transform-export-extensions',
17-
'../src/index.js'
17+
['../src/index.js', configuration]
1818
]
1919
});
2020
}
@@ -33,6 +33,70 @@ describe('babel-plugin-css-modules-transform', () => {
3333
);
3434
});
3535

36+
it('should throw if generateScopeName is not exporting a function', () => {
37+
expect(
38+
() => transform('fixtures/require.js', { generateScopedName: 'test/fixtures/generateScopedName.module.js' })
39+
).to.throw(
40+
/^.+: Configuration '.+' is not a string or function\.$/
41+
);
42+
});
43+
44+
it('should not throw if generateScopeName is exporting a function', () => {
45+
expect(
46+
() => transform('fixtures/require.js', { generateScopedName: 'test/fixtures/generateScopedName.function.module.js' })
47+
).to.not.throw(
48+
/^.+: Configuration '.+' is not a string or function\.$/
49+
);
50+
});
51+
52+
it('should throw if processCss is not a function', () => {
53+
expect(
54+
() => transform('fixtures/require.js', { processCss: 'test/fixtures/processCss.module.js' })
55+
).to.throw(
56+
/^.+: Module '.+' does not exist or is not a function\.$/
57+
);
58+
});
59+
60+
it('should throw if preprocessCss is not a function', () => {
61+
expect(
62+
() => transform('fixtures/require.js', { preprocessCss: 'test/fixtures/preprocessCss.module.js' })
63+
).to.throw(
64+
/^.+: Module '.+' does not exist or is not a function\.$/
65+
);
66+
});
67+
68+
it('should throw if append is not an array', () => {
69+
expect(
70+
() => transform('fixtures/require.js', { append: {} })
71+
).to.throw(
72+
/^.+: Configuration '.+' has to be an array\.$/
73+
);
74+
});
75+
76+
it('should throw if prepend is not an array', () => {
77+
expect(
78+
() => transform('fixtures/require.js', { prepend: {} })
79+
).to.throw(
80+
/^.+: Configuration '.+' has to be an array\.$/
81+
);
82+
});
83+
84+
it('should throw if append does not contain functions', () => {
85+
expect(
86+
() => transform('fixtures/require.js', { append: ['test/fixtures/append.module.js'] })
87+
).to.throw(
88+
/^.+: Configuration '.+' has to be valid path to a module at index 0 or it does not export a function\.$/
89+
);
90+
});
91+
92+
it('should throw if prepend does not contain functions', () => {
93+
expect(
94+
() => transform('fixtures/require.js', { prepend: ['test/fixtures/append.module.js'] })
95+
).to.throw(
96+
/^.+: Configuration '.+' has to be valid path to a module at index 0 or it does not export a function\.$/
97+
);
98+
});
99+
36100
it('should replace require call with hash of class name => css class name', () => {
37101
expect(transform('fixtures/require.js').code).to.be.equal(readExpected('fixtures/require.expected.js'));
38102
expect(transform('fixtures/import.js').code).to.be.equal(readExpected('fixtures/import.expected.js'));

0 commit comments

Comments
 (0)