-
Notifications
You must be signed in to change notification settings - Fork 2
/
element-classes.js
127 lines (110 loc) · 2.71 KB
/
element-classes.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/**
*
* It should convert this:
*
class App extends Component {
render() {
return <div className="test" />;
}
}
class App2 extends Component {
render() {
return <div className={foobar} />
}
}
class App3 extends Component {
render() {
return <div />
}
}
*
* To this:
class App extends Component {
render() {
return <div className={"test" + ((this.props.elementClasses ? " " + this.props.elementClasses : ""))} />;
}
}
class App2 extends Component {
render() {
return <div className={foobar + ((this.props.elementClasses ? " " + this.props.elementClasses : ""))} />;
}
}
class App3 extends Component {
render() {
return (
<div
className={(this.props.elementClasses ? " " + this.props.elementClasses : "")} />
);
}
}
*
*/
export default function transformer(file, api) {
const j = api.jscodeshift;
const elementClassesExpression = j.memberExpression(
j.memberExpression(j.thisExpression(), j.identifier('props')),
j.identifier('elementClasses')
);
const elementClassesString = j.binaryExpression(
'+',
j.stringLiteral(' '),
j.memberExpression(
j.memberExpression(j.thisExpression(), j.identifier('props')),
j.identifier('elementClasses')
)
);
const elementClassesTernary = j.conditionalExpression(
elementClassesExpression,
elementClassesString,
j.stringLiteral('')
);
const classNameAttribute = j.jsxAttribute(
j.jsxIdentifier('className'),
j.jsxExpressionContainer(elementClassesTernary)
);
const addToClassName = classNameAttr => {
const prevVal = classNameAttr.value;
if (prevVal.type === 'JSXExpressionContainer') {
classNameAttr.value.expression = j.binaryExpression(
'+',
prevVal.expression,
elementClassesTernary
);
} else if (prevVal.type === 'Literal') {
classNameAttr.value = j.jsxExpressionContainer(
j.binaryExpression('+', prevVal, elementClassesTernary)
);
}
};
return j(file.source)
.find(j.MethodDefinition, {key: {name: 'render'}})
.forEach(path => {
j(path)
.find(j.ReturnStatement)
.forEach(path => {
if (path.node.argument.type === 'JSXElement') {
const firstElementOpening =
path.node.argument.openingElement;
if (firstElementOpening.name.name === 'svg') {
return;
}
const classNameAttr = firstElementOpening.attributes.find(
attr => attr.name && attr.name.name === 'className'
);
if (classNameAttr) {
addToClassName(classNameAttr);
} else {
firstElementOpening.attributes.push(
classNameAttribute
);
}
}
});
})
.toSource({
objectCurlySpacing: false,
useTabs: true,
quote: 'auto',
reuseWhitespace: false
});
}