Skip to content
This repository was archived by the owner on Apr 9, 2020. It is now read-only.

Commit dec29db

Browse files
committed
Add support for custom factory methods
1 parent 46403e0 commit dec29db

File tree

5 files changed

+91
-12
lines changed

5 files changed

+91
-12
lines changed

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,14 @@ It must be an array of the transforms you want to use:
6262
}, {
6363
// can be an NPM module name or a local path
6464
"transform": "./src/my-custom-transform"
65-
}]
65+
}],
66+
// you can use custom factory methods,
67+
// defaults to: ["React.createClass", "createClass"]
68+
"factoryMethods": [
69+
"React.createClass",
70+
"createClass",
71+
"myComponentFactory"
72+
]
6673
}
6774
}
6875
}
@@ -190,10 +197,6 @@ Don’t forget to tag it with `react-transform` keyword on npm.
190197
* **https://github.com/alexkuz/react-transform-debug-inspector**
191198
* Feeling inspired? Send a PR!
192199
193-
## Limitations
194-
195-
Currently, it can only locate components of two types: ES6 classes with `render` method and explicit `React.createClass()` calls. I’m open to adding more heuristics for other common patterns, given enough interest.
196-
197200
## Discussion
198201
199202
You can discuss React Transform and related projects in **#react-transform** channel on [Reactiflux Slack](http://reactiflux.com).

src/index.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export default function ({ Plugin, types: t }) {
2828
const depthKey = '__reactTransformDepth';
2929
const recordsKey = '__reactTransformRecords';
3030
const wrapComponentIdKey = '__reactTransformWrapComponentId';
31+
const optionsKey = '__reactTransformOptions';
3132

3233
function isRenderMethod(member) {
3334
return member.kind === 'method' &&
@@ -41,15 +42,28 @@ export default function ({ Plugin, types: t }) {
4142
return cls.body.body.filter(isRenderMethod).length > 0;
4243
}
4344

44-
const isCreateClassCallExpression = t.buildMatchMemberExpression('React.createClass');
45+
function isCreateClassCallExpression(node, factoryMethods) {
46+
for (const method of factoryMethods) {
47+
if (method.indexOf('.') !== -1) {
48+
if (t.buildMatchMemberExpression(method)(node.callee)) {
49+
return true;
50+
}
51+
} else {
52+
if (node.callee.name === method) {
53+
return true;
54+
}
55+
}
56+
}
57+
}
58+
4559
/**
4660
* Does this node look like a createClass() call?
4761
*/
48-
function isCreateClass(node) {
62+
function isCreateClass(node, factoryMethods = ['React.createClass', 'createClass']) {
4963
if (!node || !t.isCallExpression(node)) {
5064
return false;
5165
}
52-
if (!isCreateClassCallExpression(node.callee)) {
66+
if (!isCreateClassCallExpression(node, factoryMethods)) {
5367
return false;
5468
}
5569
const args = node.arguments;
@@ -257,7 +271,8 @@ export default function ({ Plugin, types: t }) {
257271

258272
CallExpression: {
259273
exit(node, parent, scope, file) {
260-
if (!isCreateClass(node)) {
274+
const { factoryMethods } = this.state[optionsKey];
275+
if (!isCreateClass(node, factoryMethods)) {
261276
return;
262277
}
263278

@@ -273,6 +288,7 @@ export default function ({ Plugin, types: t }) {
273288

274289
Program: {
275290
enter(node, parent, scope, file) {
291+
this.state[optionsKey] = getPluginOptions(file);
276292
this.state[wrapComponentIdKey] = scope.generateUidIdentifier('wrapComponent');
277293
},
278294

@@ -282,11 +298,12 @@ export default function ({ Plugin, types: t }) {
282298
}
283299

284300
// Generate a variable holding component records
285-
const allTransformOptions = getPluginOptions(file).transforms;
301+
const allTransforms = this.state[optionsKey].transforms;
302+
286303
const [recordsId, recordsVar] = defineComponentRecords(scope, this.state);
287304

288305
// Import transformation functions and initialize them
289-
const initTransformCalls = allTransformOptions.map(transformOptions =>
306+
const initTransformCalls = allTransforms.map(transformOptions =>
290307
defineInitTransformCall(scope, file, recordsId, transformOptions)
291308
).filter(Boolean);
292309
const initTransformIds = initTransformCalls.map(c => c[0]);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
var myComponentFactory = require('myComponentFactory');
2+
3+
var A = myComponentFactory({
4+
displayName: 'A',
5+
6+
render() {}
7+
});
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'use strict';
2+
3+
var _myCustomModuleWrap2 = require('my-custom-module/wrap');
4+
5+
var _myCustomModuleWrap3 = _interopRequireDefault(_myCustomModuleWrap2);
6+
7+
var _react = require('react');
8+
9+
var _myOtherCustomModuleWrap2 = require('my-other-custom-module/wrap');
10+
11+
var _myOtherCustomModuleWrap3 = _interopRequireDefault(_myOtherCustomModuleWrap2);
12+
13+
var _components = {
14+
_$A: {
15+
displayName: 'A'
16+
}
17+
};
18+
19+
var _reactComponentWrapper = (0, _myCustomModuleWrap3['default'])({
20+
filename: '%FIXTURE_PATH%',
21+
components: _components,
22+
locals: [module],
23+
imports: [_react]
24+
});
25+
26+
var _reactComponentWrapper2 = (0, _myOtherCustomModuleWrap3['default'])({
27+
filename: '%FIXTURE_PATH%',
28+
components: _components,
29+
locals: [],
30+
imports: []
31+
});
32+
33+
function _wrapComponent(uniqueId) {
34+
return function (ReactClass) {
35+
return _reactComponentWrapper2(_reactComponentWrapper(ReactClass, uniqueId), uniqueId);
36+
};
37+
}
38+
39+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
40+
41+
var myComponentFactory = require('myComponentFactory');
42+
43+
var A = _wrapComponent('_$A')(myComponentFactory({
44+
displayName: 'A',
45+
46+
render: function render() {}
47+
}));

test/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@ describe('finds React components', () => {
2424
imports: ['react']
2525
}, {
2626
transform: 'my-other-custom-module/wrap'
27-
}]
27+
}],
28+
factoryMethods: [
29+
'React.createClass',
30+
'createClass',
31+
'myComponentFactory'
32+
]
2833
}
2934
}
3035
}).code;

0 commit comments

Comments
 (0)