1import { IOSConfig } from '@expo/config-plugins'; 2import Minipass from 'minipass'; 3import path from 'path'; 4import { ReadEntry } from 'tar'; 5 6function escapeXMLCharacters(original: string): string { 7 const noAmps = original.replace('&', '&'); 8 const noLt = noAmps.replace('<', '<'); 9 const noGt = noLt.replace('>', '>'); 10 const noApos = noGt.replace('"', '\\"'); 11 return noApos.replace("'", "\\'"); 12} 13 14class Transformer extends Minipass { 15 data = ''; 16 17 constructor(private settings: { name: string; extension: string }) { 18 super(); 19 } 20 21 write(data: string) { 22 this.data += data; 23 return true; 24 } 25 26 getNormalizedName(): string { 27 if (['.xml', '.plist'].includes(this.settings.extension)) { 28 return escapeXMLCharacters(this.settings.name); 29 } 30 return this.settings.name; 31 } 32 33 end() { 34 const name = this.getNormalizedName(); 35 const replaced = this.data 36 .replace(/Hello App Display Name/g, name) 37 .replace(/HelloWorld/g, IOSConfig.XcodeUtils.sanitizedName(name)) 38 .replace(/helloworld/g, IOSConfig.XcodeUtils.sanitizedName(name.toLowerCase())); 39 super.write(replaced); 40 return super.end(); 41 } 42} 43 44export function createEntryResolver(name: string) { 45 return (entry: ReadEntry) => { 46 if (name) { 47 // Rewrite paths for bare workflow 48 entry.path = entry.path 49 .replace( 50 /HelloWorld/g, 51 entry.path.includes('android') 52 ? IOSConfig.XcodeUtils.sanitizedName(name.toLowerCase()) 53 : IOSConfig.XcodeUtils.sanitizedName(name) 54 ) 55 .replace(/helloworld/g, IOSConfig.XcodeUtils.sanitizedName(name).toLowerCase()); 56 } 57 if (entry.type && /^file$/i.test(entry.type) && path.basename(entry.path) === 'gitignore') { 58 // Rename `gitignore` because npm ignores files named `.gitignore` when publishing. 59 // See: https://github.com/npm/npm/issues/1862 60 entry.path = entry.path.replace(/gitignore$/, '.gitignore'); 61 } 62 }; 63} 64 65export function createFileTransform(name: string) { 66 return (entry: ReadEntry) => { 67 const extension = path.extname(entry.path); 68 69 // Binary files, don't process these (avoid decoding as utf8) 70 if ( 71 ![ 72 '.png', 73 '.jpg', 74 '.jpeg', 75 '.gif', 76 '.webp', 77 '.psd', 78 '.tiff', 79 '.svg', 80 '.jar', 81 '.keystore', 82 83 // Font files 84 '.otf', 85 '.ttf', 86 ].includes(extension) && 87 name 88 ) { 89 return new Transformer({ name, extension }); 90 } 91 return undefined; 92 }; 93} 94