18d307f52SEvan Baconimport { IOSConfig } from '@expo/config-plugins'; 28d307f52SEvan Baconimport Minipass from 'minipass'; 38d307f52SEvan Baconimport path from 'path'; 48d307f52SEvan Baconimport { ReadEntry } from 'tar'; 58d307f52SEvan Bacon 68d307f52SEvan Baconfunction escapeXMLCharacters(original: string): string { 78d307f52SEvan Bacon const noAmps = original.replace('&', '&'); 88d307f52SEvan Bacon const noLt = noAmps.replace('<', '<'); 98d307f52SEvan Bacon const noGt = noLt.replace('>', '>'); 108d307f52SEvan Bacon const noApos = noGt.replace('"', '\\"'); 118d307f52SEvan Bacon return noApos.replace("'", "\\'"); 128d307f52SEvan Bacon} 138d307f52SEvan Bacon 148d307f52SEvan Baconclass Transformer extends Minipass { 158d307f52SEvan Bacon data = ''; 168d307f52SEvan Bacon 178d307f52SEvan Bacon constructor(private settings: { name: string; extension: string }) { 188d307f52SEvan Bacon super(); 198d307f52SEvan Bacon } 208d307f52SEvan Bacon 218d307f52SEvan Bacon write(data: string) { 228d307f52SEvan Bacon this.data += data; 238d307f52SEvan Bacon return true; 248d307f52SEvan Bacon } 258d307f52SEvan Bacon 268d307f52SEvan Bacon getNormalizedName(): string { 278d307f52SEvan Bacon if (['.xml', '.plist'].includes(this.settings.extension)) { 288d307f52SEvan Bacon return escapeXMLCharacters(this.settings.name); 298d307f52SEvan Bacon } 308d307f52SEvan Bacon return this.settings.name; 318d307f52SEvan Bacon } 328d307f52SEvan Bacon 338d307f52SEvan Bacon end() { 348d307f52SEvan Bacon const name = this.getNormalizedName(); 358d307f52SEvan Bacon const replaced = this.data 368d307f52SEvan Bacon .replace(/Hello App Display Name/g, name) 378d307f52SEvan Bacon .replace(/HelloWorld/g, IOSConfig.XcodeUtils.sanitizedName(name)) 388d307f52SEvan Bacon .replace(/helloworld/g, IOSConfig.XcodeUtils.sanitizedName(name.toLowerCase())); 398d307f52SEvan Bacon super.write(replaced); 408d307f52SEvan Bacon return super.end(); 418d307f52SEvan Bacon } 428d307f52SEvan Bacon} 438d307f52SEvan Bacon 448d307f52SEvan Baconexport function createEntryResolver(name: string) { 458d307f52SEvan Bacon return (entry: ReadEntry) => { 468d307f52SEvan Bacon if (name) { 478d307f52SEvan Bacon // Rewrite paths for bare workflow 488d307f52SEvan Bacon entry.path = entry.path 498d307f52SEvan Bacon .replace( 508d307f52SEvan Bacon /HelloWorld/g, 518d307f52SEvan Bacon entry.path.includes('android') 528d307f52SEvan Bacon ? IOSConfig.XcodeUtils.sanitizedName(name.toLowerCase()) 538d307f52SEvan Bacon : IOSConfig.XcodeUtils.sanitizedName(name) 548d307f52SEvan Bacon ) 558d307f52SEvan Bacon .replace(/helloworld/g, IOSConfig.XcodeUtils.sanitizedName(name).toLowerCase()); 568d307f52SEvan Bacon } 578d307f52SEvan Bacon if (entry.type && /^file$/i.test(entry.type) && path.basename(entry.path) === 'gitignore') { 588d307f52SEvan Bacon // Rename `gitignore` because npm ignores files named `.gitignore` when publishing. 598d307f52SEvan Bacon // See: https://github.com/npm/npm/issues/1862 608d307f52SEvan Bacon entry.path = entry.path.replace(/gitignore$/, '.gitignore'); 618d307f52SEvan Bacon } 628d307f52SEvan Bacon }; 638d307f52SEvan Bacon} 648d307f52SEvan Bacon 658d307f52SEvan Baconexport function createFileTransform(name: string) { 668d307f52SEvan Bacon return (entry: ReadEntry) => { 678d307f52SEvan Bacon const extension = path.extname(entry.path); 688d307f52SEvan Bacon 698d307f52SEvan Bacon // Binary files, don't process these (avoid decoding as utf8) 708d307f52SEvan Bacon if ( 718d307f52SEvan Bacon ![ 728d307f52SEvan Bacon '.png', 738d307f52SEvan Bacon '.jpg', 748d307f52SEvan Bacon '.jpeg', 758d307f52SEvan Bacon '.gif', 768d307f52SEvan Bacon '.webp', 778d307f52SEvan Bacon '.psd', 788d307f52SEvan Bacon '.tiff', 798d307f52SEvan Bacon '.svg', 808d307f52SEvan Bacon '.jar', 818d307f52SEvan Bacon '.keystore', 82*f3dc3b4eSEvan Bacon 83*f3dc3b4eSEvan Bacon // Font files 84*f3dc3b4eSEvan Bacon '.otf', 85*f3dc3b4eSEvan Bacon '.ttf', 868d307f52SEvan Bacon ].includes(extension) && 878d307f52SEvan Bacon name 888d307f52SEvan Bacon ) { 898d307f52SEvan Bacon return new Transformer({ name, extension }); 908d307f52SEvan Bacon } 918d307f52SEvan Bacon return undefined; 928d307f52SEvan Bacon }; 938d307f52SEvan Bacon} 94