Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
117
fork

Configure Feed

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

at aed2c0a2cc6f443c51e8404641140cda8291b5b1 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}