this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 135 lines 3.5 kB view raw
1/** 2 * Codemod to replace namespaced React calls with named imports 3 * 4 * Before: 5 * import React from 'react' 6 * React.useEffect(() => {}, []) 7 * 8 * After: 9 * import { useEffect } from 'react' 10 * useEffect(() => {}, []) 11 * 12 * Usage: jscodeshift -t .jscodeshift/react-import.js <file-path> 13 * Example: jscodeshift -t .jscodeshift/react-import.js src/App.native.tsx 14 */ 15 16/* eslint-disable */ 17 18export const parser = 'tsx' 19 20export default function transformer(file, api) { 21 const j = api.jscodeshift 22 const root = j(file.source) 23 24 // Find the React import 25 let reactImportPath = null 26 const reactMembers = new Set() 27 28 root.find(j.ImportDeclaration).forEach(path => { 29 const node = path.value 30 if (node.source.value === 'react') { 31 node.specifiers.forEach(spec => { 32 // Check if this is a default import of React 33 if ( 34 spec.type === 'ImportDefaultSpecifier' && 35 spec.local.name === 'React' 36 ) { 37 reactImportPath = path 38 } 39 }) 40 } 41 }) 42 43 if (!reactImportPath) { 44 // No React import found, nothing to do 45 return file.source 46 } 47 48 // Find all React.* member expressions 49 root 50 .find(j.MemberExpression) 51 .filter(path => { 52 const node = path.value 53 return ( 54 node.object.type === 'Identifier' && 55 node.object.name === 'React' && 56 node.property.type === 'Identifier' 57 ) 58 }) 59 .forEach(path => { 60 const propertyName = path.value.property.name 61 reactMembers.add(propertyName) 62 }) 63 64 // Find all React.* JSX member expressions (e.g., <React.Fragment>) 65 root 66 .find(j.JSXMemberExpression) 67 .filter(path => { 68 const node = path.value 69 return node.object.name === 'React' && node.property.name 70 }) 71 .forEach(path => { 72 const propertyName = path.value.property.name 73 reactMembers.add(propertyName) 74 }) 75 76 // If no React members are used, remove the import 77 if (reactMembers.size === 0) { 78 reactImportPath.prune() 79 return root.toSource() 80 } 81 82 // Sort the members for consistent output 83 const sortedMembers = Array.from(reactMembers).sort() 84 85 // Create new import specifiers 86 const newSpecifiers = sortedMembers.map(name => 87 j.importSpecifier(j.identifier(name), j.identifier(name)), 88 ) 89 90 // Get the existing import specifiers 91 const sortedImports = Array.from(reactImportPath.value.specifiers).sort() 92 const existingSpecifiers = sortedImports.filter( 93 specifier => specifier.type !== 'ImportDefaultSpecifier', 94 ) 95 96 const allSpecifiers = [ 97 ...new Map( 98 [...existingSpecifiers, ...newSpecifiers].map(item => [ 99 item.imported.name, 100 item, 101 ]), 102 ).values(), 103 ] 104 105 // Update the import declaration 106 reactImportPath.value.specifiers = allSpecifiers 107 108 // Replace all React.* member expressions with just the identifier 109 root 110 .find(j.MemberExpression) 111 .filter(path => { 112 const node = path.value 113 return ( 114 node.object.type === 'Identifier' && 115 node.object.name === 'React' && 116 node.property.type === 'Identifier' 117 ) 118 }) 119 .replaceWith(path => { 120 return j.identifier(path.value.property.name) 121 }) 122 123 // Replace all React.* JSX member expressions with just the identifier 124 root 125 .find(j.JSXMemberExpression) 126 .filter(path => { 127 const node = path.value 128 return node.object.name === 'React' && node.property.name 129 }) 130 .replaceWith(path => { 131 return j.jsxIdentifier(path.value.property.name) 132 }) 133 134 return root.toSource() 135}