-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.js
128 lines (118 loc) · 3.81 KB
/
utils.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
128
function getObjectFromExpression( expression ) {
let obj = {};
expression.properties.forEach( ( property ) => {
if ( property.value.value ) {
obj[ property.key.name ] = property.value.value;
} else if ( property.value.elements ) {
obj[ property.key.name ] = getArrayFromExpression( property.value );
} else if ( property.value.properties ) {
obj[ property.key.name ] = getObjectFromExpression( property.value );
}
} );
return obj;
}
function getArrayFromExpression( expression ) {
const props = [];
if ( expression && expression.elements ) {
expression.elements.forEach( ( element ) => {
if ( element.type === 'StringLiteral' ) {
props.push( element.value );
}
if ( element.type === 'ArrayExpression' ) {
// We have an object to process
if ( element.elements ) {
const prop = getArrayFromExpression( element );
props.push( prop );
}
}
else if ( element.type === 'ObjectExpression' ) {
// We have an object to process
const prop = getObjectFromExpression( element );
props.push( prop );
}
} );
}
return props;
};
function getExpressionArgs( expression, types ) {
let args = [];
// let currentNode = expression.left;
if ( types.isIdentifier( expression ) ) {
args.push( { type: 'identifier', value: expression.name } );
} else if ( types.isStringLiteral( expression ) ) {
args.push( { type: 'value', value: `'${ expression.value }'` } );
} else if ( types.isLiteral( expression ) ) {
// Should handle booleans, integers, floats etc
args.push( { type: 'value', value: String( expression.value ) } );
} else if ( types.isMemberExpression( expression )) {
args.push( { type: 'identifier', value: `${ expression.object.name }.${ expression.property.name }` } );
} else if ( types.isUnaryExpression( expression ) ) {
args = [ ...args, ...getExpressionArgs( expression.argument, types ) ];
}
else if ( types.isBinaryExpression( expression ) ) {
args = [
...args,
...getExpressionArgs( expression.left, types ),
...getExpressionArgs( expression.right, types )
];
}
return args;
}
function injectContextToJSXElementComponents( path, contextVar, t ) {
path.traverse( {
JSXElement(subPath){
// If we find a JSX element, check to see if it's a component,
// and if so, inject a `__context__` JSXAttribute.
if ( isJSXElementComponent( subPath ) ) {
const contextAttribute = t.jSXAttribute( t.jSXIdentifier( '__context__' ), t.jSXExpressionContainer( t.identifier( contextVar ) ) );
subPath.node.openingElement.attributes.push( contextAttribute );
}
}
} );
}
function getJSXElementName( path ) {
return path.node.openingElement?.name?.name
}
function isJSXElementComponent( path ) {
const elementName = getJSXElementName( path );
if ( typeof elementName === 'string' ) {
// Find out if we're dealing with a component or regular html element.
// Assume that a capital letter means a component.
// TODO - Double check this - pretty sure its a JSX rule.
const elementIntialLetter = elementName.substring(0, 1);
if ( elementIntialLetter.toUpperCase() === elementIntialLetter ) {
return true;
}
}
return false;
}
function isJSXElementTextInput( subPath ) {
const element = subPath.node;
if ( ! element.openingElement ) {
return false;
}
const { name } = element.openingElement;
if ( name?.name !== 'input' ) {
return false;
}
// Now check to see if the elements `type` attribute is set to `text`.
const typeAttr = element.openingElement.attributes.find( ( attr ) => {
return attr?.name?.name === 'type';
} );
if ( ! typeAttr ) {
return false;
}
const { value } = typeAttr;
if ( value.value !== 'text' ) {
return false;
}
return true;
}
module.exports = {
getExpressionArgs,
getArrayFromExpression,
getObjectFromExpression,
injectContextToJSXElementComponents,
isJSXElementComponent,
isJSXElementTextInput,
};