Closed veris-ankitpopli closed 5 years ago
Convert existing React Native Applications to V3 Templates. Why re-write screens when we can have scripts transform them ?
Courtesy: https://github.com/babel/babel/tree/master/packages/babel-plugin-syntax-jsx
export default function({ types: t, ...props }) { const generateElement = (path, state) => { const FILE = state.file, OPTIONS = Object.assign({}, { type: "type", value: "value" }, state.opts); const NODE = path.node; if (!/JSXElement/.test(NODE.type)) return NODE.expression ? NODE.expression : t.StringLiteral(NODE.value); const OPENING_ELEMENT = NODE.openingElement, CHILDREN = path.get("children"), ELEMENT_ATTRIBUTES = OPENING_ELEMENT.attributes, EXTENDS = isExtension(OPENING_ELEMENT, path); let type = t.StringLiteral(OPENING_ELEMENT.name.name.split(/(?=[A-Z])/).join("-").toLowerCase()), attributes = ELEMENT_ATTRIBUTES.length ? buildAttributeObject(ELEMENT_ATTRIBUTES, FILE) : t.NullLiteral(), children = CHILDREN.length ? t.ArrayExpression(CHILDREN.map(child => generateElement(child, state))) : t.NullLiteral(); const props = attributes.properties.map(({ key, value }) => t.ObjectProperty(t.StringLiteral(key.value), value)); return t.ObjectExpression([ ...props, t.ObjectProperty(t.StringLiteral(OPTIONS.type), EXTENDS ? t.NullLiteral() : type), t.ObjectProperty(t.StringLiteral(OPTIONS.value), children) ]); }; const generateAttrObject = nodes => { let arr = nodes.map(node => { let name = t.StringLiteral(node.name.name); let value = !node.value ? t.BooleanLiteral(true) : /JSXExpressionContainer/i.test(node.value.type) ? node.value.expression : node.value; return t.ObjectProperty(name, value); }); return [t.ObjectExpression(arr)]; }; const buildAttributeObject = function(attrs, file) { let _expressions = [], _spreads = []; while (attrs.length) { let attr = attrs.shift(); /^JSXSpreadAttribute$/i.test(attr.type) ? _spreads.push(attr.argument) : _expressions.push(attr); } let attrObject = _expressions.length ? generateAttrObject(_expressions) : null; if (_spreads.length) { let extension = attrObject ? _spreads.concat(attrObject) : _spreads; if (extension.length > 1) extension.unshift(t.ObjectExpression([])); attrObject = t.callExpression(file.addHelper("extends"), extension); } else { attrObject = attrObject[0]; } return attrObject; }; const isExtension = (openingElement, path) => path.scope.hasBinding(openingElement.name.name); return { visitor: { JSXElement: function(path, state) { path.replaceWith(generateElement(path, state)); } } }; }
<Image style={{width: 128, height: 128, alignSelf: 'center'}} source={'assets/images/successful_check_icon.png'}/>;
({ "style": {width: 128, height: 128, alignSelf: 'center'}, "source": 'assets/images/successful_check_icon.png', "type": "image", "value": null });
Convert existing React Native Applications to V3 Templates. Why re-write screens when we can have scripts transform them ?
Babel Transform Plugins
Sample Transform:
Courtesy: https://github.com/babel/babel/tree/master/packages/babel-plugin-syntax-jsx
Input
Output (V3 Component Declaration)
Caveats (as of now)