Skip to content

Commit 336ce42

Browse files
committed
Implement CLASS directive
1 parent ee448dd commit 336ce42

File tree

5 files changed

+129
-1
lines changed

5 files changed

+129
-1
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Babel plugin that carries directives to React JSX:
99
* `rx-if / rx-else (rx-elseif)`
1010
* `rx-for`
1111
* `rx-switch / rx-case (rx-default)`
12+
* `rx-class`
1213

1314
## Installation
1415

@@ -65,4 +66,12 @@ plugins: [
6566
<p rx-case={3}>3</p>
6667
<p rx-default>?</p>
6768
</div>
69+
```
70+
71+
## The `rx-class` Directive
72+
73+
```
74+
<div className="box"
75+
rx-class={{isError: this.state.isError, isOk: this.state.isOk}}
76+
>...</div>
6877
```

directives/class.directive.js

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
const t = require('babel-types');
2+
const u = require('../utils');
3+
const Directive = require('./enum');
4+
5+
function transformClassDirective(path, state) {
6+
let classDirAttrs = path.node.openingElement.attributes;
7+
let classAttrIdx = u.getDirectiveIndex(classDirAttrs, Directive.CLASS);
8+
let classExpression = classDirAttrs[classAttrIdx].value.expression;
9+
let classNameAttr = classDirAttrs.find(prop => {
10+
return prop.name.name == 'className';
11+
});
12+
let classNameValue;
13+
14+
if (classNameAttr && t.isJSXExpressionContainer(classNameAttr.value)) {
15+
classNameValue = classNameAttr.value.expression;
16+
} else if (classNameAttr && t.isStringLiteral(classNameAttr.value)) {
17+
classNameValue = classNameAttr.value;
18+
}
19+
20+
let classNameArr = classNameValue ? t.arrayExpression([
21+
classNameValue
22+
]) : t.arrayExpression([]);
23+
24+
let classObjEntries = t.callExpression(
25+
t.memberExpression(
26+
t.identifier('Object'),
27+
t.identifier('entries')
28+
), [
29+
classExpression
30+
]
31+
);
32+
33+
let classObjFilteredEntries = t.callExpression(
34+
t.memberExpression(
35+
classObjEntries,
36+
t.identifier('filter')
37+
), [
38+
t.arrowFunctionExpression(
39+
[t.identifier('c')],
40+
t.binaryExpression(
41+
'===',
42+
t.memberExpression(
43+
t.identifier('c'),
44+
t.identifier('1')
45+
),
46+
t.booleanLiteral(true)
47+
)
48+
)
49+
]
50+
);
51+
52+
let classObjMappedEntries = t.callExpression(
53+
t.memberExpression(
54+
classObjFilteredEntries,
55+
t.identifier('map')
56+
), [
57+
t.arrowFunctionExpression(
58+
[t.identifier('c')],
59+
t.memberExpression(
60+
t.identifier('c'),
61+
t.identifier('0')
62+
)
63+
)
64+
]
65+
);
66+
67+
let classNameConcatenatedArr = t.callExpression(
68+
t.memberExpression(
69+
classNameArr,
70+
t.identifier('concat')
71+
), [
72+
classObjMappedEntries
73+
]
74+
);
75+
76+
let classNameString = t.callExpression(
77+
t.memberExpression(
78+
classNameConcatenatedArr,
79+
t.identifier('join')
80+
), [
81+
t.stringLiteral(' ')
82+
]
83+
);
84+
85+
let newClassNameProp = t.jSXAttribute(
86+
t.jSXIdentifier('className'),
87+
t.jSXExpressionContainer(
88+
classNameString
89+
)
90+
);
91+
92+
let classNameIdx = classDirAttrs.findIndex(attr => {
93+
return attr.name.name == 'className';
94+
});
95+
if (classNameIdx !== -1) classDirAttrs.splice(classNameIdx, 1);
96+
classDirAttrs.push(newClassNameProp);
97+
// return console.log('>>>>>>>>>>>>>>>>>', classDirAttrs);
98+
99+
path.replaceWith(
100+
u.createJSXElement(
101+
path.node.openingElement.name.name,
102+
classDirAttrs,
103+
path.node.children,
104+
[Directive.CLASS]
105+
)
106+
);
107+
}
108+
109+
module.exports = transformClassDirective;

directives/enum.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ const Directive = {
2121
},
2222
get DEFAULT() {
2323
return getDirectiveProp('default');
24+
},
25+
get CLASS() {
26+
return getDirectiveProp('class');
2427
}
2528
};
2629

directives/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
const transformIfDirective = require('./if.directive');
22
const transformForDirective = require('./for.directive');
33
const transformSwitchDirective = require('./switch.directive');
4+
const transformClassDirective = require('./class.directive');
45

56
module.exports = {
67
transformIfDirective,
78
transformForDirective,
8-
transformSwitchDirective
9+
transformSwitchDirective,
10+
transformClassDirective
911
};

index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ function directiveParser(_, opts) {
3535
return;
3636
}
3737

38+
if (hasDirective(path.node, Directive.CLASS)) {
39+
d.transformClassDirective(path, state);
40+
return;
41+
}
42+
3843
}
3944
}
4045
};

0 commit comments

Comments
 (0)