1
1
import React from 'react' ;
2
2
3
- let css = ( rawCSSWithProps ) => ( target , name , descriptor ) => ( {
3
+ /*
4
+ This get's used as decorator @css
5
+
6
+ Get's the template literal passed to it argument.
7
+ This contains references to props as well
8
+
9
+ Method decorators expect a function to be returned,
10
+ this function gets the parent class, name of the function -
11
+ render in this case and the descriptor for the function.
12
+ */
13
+ let css = ( rawCSS ) => ( parentClass , name , descriptor ) => ( {
4
14
...descriptor ,
5
15
value : function ( ) {
6
- let props ;
7
- let giveMeProps = ( object ) => {
8
- props = object . props ;
16
+ let originalProps ;
17
+
18
+ /* Totally stealing props by fake rendering the component */
19
+ let getProps = ( object ) => {
20
+ originalProps = object . props ;
9
21
return object ;
10
22
} ;
11
- let rendered = descriptor . value . apply ( giveMeProps ( this ) , arguments ) ;
23
+ let rendered = descriptor . value . apply ( getProps ( this ) , arguments ) ;
12
24
13
- let rawCSS = fillProps ( rawCSSWithProps [ 0 ] , props )
14
- let style = parseCss ( rawCSS ) ;
15
- let newProps = { ...props , style} ;
25
+ /* Replace props and return realCSS™ */
26
+ let realCSS = fillProps ( rawCSS , originalProps )
16
27
28
+ /* Convert real CSS to javascripty CSS */
29
+ let style = parseCss ( realCSS ) ;
30
+
31
+ /* Merge styles into original props */
32
+ let newProps = { ...originalProps , style} ;
33
+
34
+ /*
35
+ Pass on a clone of the rendered component
36
+ with our merged props.
37
+ This overrides the original render function
38
+ */
17
39
return React . cloneElement ( rendered , newProps , rendered . props . children ) ;
18
40
}
19
41
} ) ;
20
42
21
- let camelCase = ( key ) => key . replace ( / ( \- [ a - z ] ) / g, $1 => $1 . toUpperCase ( ) . replace ( '-' , '' ) ) ;
43
+ /*
44
+ Replace props with actual values
22
45
23
- let fillProps = ( rawCSSWithProps , props ) => {
46
+ Uses regex pattern to match references to props
47
+
48
+ Supports direct usage
49
+ color: {this.props.color}
50
+
51
+ Does not evaluate conditions (yet)
52
+ color: {this.props.color || 'blue'}
53
+ */
54
+ let fillProps = ( rawCSS , props ) => {
55
+ rawCSS = rawCSS [ 0 ] ; // template literal = array
24
56
let re = / { t h i s .p r o p s .* } / g;
25
- let matches = rawCSSWithProps . match ( re ) ;
57
+ let matches = rawCSS . match ( re ) ;
26
58
if ( matches && matches . length ) {
27
59
for ( let match of matches ) {
28
60
let keyword = match ;
29
61
keyword = keyword . replace ( '{this.props.' , '' ) ;
30
- keyword = keyword . substring ( 0 , keyword . length - 1 ) ; // }
62
+ keyword = keyword . substring ( 0 , keyword . length - 1 ) ; // remove }
31
63
keyword = keyword . trim ( ) ;
32
-
33
- rawCSSWithProps = rawCSSWithProps . replace ( match , props [ keyword ] ) ;
64
+ rawCSS = rawCSS . replace ( match , props [ keyword ] ) ;
34
65
}
35
66
}
36
- return rawCSSWithProps ;
67
+ return rawCSS ;
37
68
}
38
69
39
- let parseCss = ( rawCSS ) => {
70
+ /*
71
+ Convert realCSS to javascripty CSS
72
+
73
+ Split on semi-colon
74
+ Trim the whitespace
75
+ Camel case keys
76
+ */
77
+ let parseCss = ( realCSS ) => {
40
78
let styles = { } ;
41
- let rules = rawCSS . trim ( ) . split ( ';' ) ;
79
+ let rules = realCSS . trim ( ) . split ( ';' ) ;
42
80
for ( let rule of rules ) {
43
81
let [ key , value ] = rule . trim ( ) . split ( ':' ) ;
44
82
if ( key && value ) {
@@ -50,4 +88,6 @@ let parseCss = (rawCSS) => {
50
88
return styles ;
51
89
}
52
90
91
+ let camelCase = ( key ) => key . replace ( / ( \- [ a - z ] ) / g, $1 => $1 . toUpperCase ( ) . replace ( '-' , '' ) ) ;
92
+
53
93
export default css ;
0 commit comments