1import chalk from 'chalk';
2
3import { TransformPipeline } from '.';
4
5export function postTransforms(versionName: string): TransformPipeline {
6  return {
7    logHeader(filePath: string) {
8      console.log(`Post-transforming ${chalk.magenta(filePath)}:`);
9    },
10    transforms: [
11      // react-native
12      {
13        paths: ['RCTRedBox.m', 'RCTLog.mm'],
14        replace: /#if (ABI\d+_\d+_\d+)RCT_DEBUG/g,
15        with: '#if $1RCT_DEV',
16      },
17      {
18        paths: ['NSTextStorage+FontScaling.h', 'NSTextStorage+FontScaling.m'],
19        replace: /NSTextStorage \(FontScaling\)/,
20        with: `NSTextStorage (${versionName}FontScaling)`,
21      },
22      {
23        paths: [
24          'NSTextStorage+FontScaling.h',
25          'NSTextStorage+FontScaling.m',
26          'RCTTextShadowView.m',
27        ],
28        replace: /\b(scaleFontSizeToFitSize|scaleFontSizeWithRatio|compareToSize)\b/g,
29        with: `${versionName.toLowerCase()}_rct_$1`,
30      },
31      {
32        paths: 'RCTWebView.m',
33        replace: /@"ABI\d+_\d+_\d+React-js-navigation"/,
34        with: '@"react-js-navigation"',
35      },
36      {
37        replace: new RegExp(`FB${versionName}ReactNativeSpec`, 'g'),
38        with: 'FBReactNativeSpec',
39      },
40      {
41        replace: new RegExp('\\b(Native\\w+Spec)\\b', 'g'),
42        with: `${versionName}$1`,
43      },
44      {
45        paths: 'RCTInspectorPackagerConnection.m',
46        replace: /\b(RECONNECT_DELAY_MS)\b/g,
47        with: `${versionName}$1`,
48      },
49      {
50        paths: 'RCTView.m',
51        replace: /\b(SwitchAccessibilityTrait)\b/g,
52        with: `${versionName}$1`,
53      },
54      {
55        paths: 'RCTSpringAnimation.m',
56        replace: /\b(MAX_DELTA_TIME)\b/g,
57        with: `${versionName}$1`,
58      },
59      {
60        paths: 'ModuleRegistry.cpp',
61        replace: /(std::string normalizeName\(std::string name\) \{)/,
62        with: `$1\n  if (name.compare(0, ${versionName.length}, "${versionName}") == 0) {\n    name = name.substr(${versionName.length});\n  }\n`,
63      },
64      {
65        paths: 'ModuleRegistry.cpp',
66        replace: /(\(name\.compare\(\d+, \d+, ")([^"]+)(RCT"\))/,
67        with: '$1$3',
68      },
69      {
70        paths: ['RCTSRWebSocket.h', 'UIView+Private.h'],
71        replace: /@interface (\w+) \((CertificateAdditions|Private)\)/g,
72        with: `@interface $1 (${versionName}$2)`,
73      },
74      {
75        // Fix prefixing imports from React-bridging
76        paths: 'ReactCommon',
77        replace: new RegExp(`(React)\\/${versionName}(bridging)\\/`, 'g'),
78        with: `$1/$2/${versionName}`,
79      },
80      {
81        // Files inside fabric directory used to have nested import paths and we transformed it wrong.
82        // This rules are here to fix it.
83        // e.g. `#include <react/debug/react_native_assert.h>`
84        //   -> `#include <ABI49_0_0React/ABI49_0_0debug/ABI49_0_0React_native_assert.h>`
85        //   -> `#include <ABI49_0_0React/debug/ABI49_0_0React_native_assert.h>`
86        paths: ['ReactCommon/react/', 'React/'],
87        replace: new RegExp(
88          `(^(#include|#import) <${versionName}React)/${versionName}([^/\\n]+?)/(${versionName})?([^/\\n]+?\\.h>$)`,
89          'gm'
90        ),
91        with: `$1/$3/${versionName}$5`,
92      },
93      {
94        // Same as above but for difference nested level.
95        paths: ['Libraries/AppDelegate/', 'ReactCommon/react/', 'React/'],
96        replace: new RegExp(
97          `(^(#include|#import) <${versionName}React)/${versionName}([^/\\n]+?)\\/([^/\\n]+?)\\/(${versionName})?([^/\\n]+?\\.h>$)`,
98          'gm'
99        ),
100        with: `$1/$3/$4/${versionName}$6`,
101      },
102      {
103        // Codegen adds methods to `RCTCxxConvert` that start with `JS_`, which refer to `JS::`
104        // C++ namespace that we prefix, so these methods must be prefixed as well.
105        paths: ['FBReactNativeSpec.h', 'FBReactNativeSpec-generated.mm'],
106        replace: /(RCTManagedPointer \*\))(JS_)/g,
107        with: `$1${versionName}$2`,
108      },
109
110      // Universal modules
111      {
112        paths: `UniversalModules/${versionName}EXScoped`,
113        replace: /(EXScopedABI\d+_\d+_\d+ReactNative)/g,
114        with: 'EXScopedReactNative',
115      },
116      {
117        paths: `${versionName}EXFileSystem`,
118        replace: new RegExp(`NSData\\+${versionName}EXFileSystem\\.h`, 'g'),
119        with: `${versionName}NSData+EXFileSystem.h`,
120      },
121      {
122        paths: [
123          `${versionName}EXNotifications`,
124          `${versionName}EXUpdates`,
125          `${versionName}EXJSONUtils`,
126        ],
127        replace: new RegExp(
128          `NSDictionary\\+${versionName}(EXNotificationsVerifyingClass|EXJSONUtils)\\.h`,
129          'g'
130        ),
131        with: `${versionName}NSDictionary+$1.h`,
132      },
133      {
134        paths: [
135          `${versionName}EXNotifications`,
136          `${versionName}EXAppState`,
137          `${versionName}EXVersionManager`,
138        ],
139        replace: new RegExp(`EXModuleRegistryHolder${versionName}React`, 'g'),
140        with: 'EXModuleRegistryHolderReact',
141      },
142      {
143        // Versioned ExpoKit has to use versioned modules provider
144        paths: 'EXVersionManager.mm',
145        replace: /@"(ExpoModulesProvider)"/,
146        with: `@"${versionName}$1"`,
147      },
148      {
149        paths: `${versionName}EXVersionManager.mm`,
150        replace: `#import <${versionName}Reacthermes/HermesExecutorFactory.h>`,
151        with: `#import <${versionName}reacthermes/${versionName}HermesExecutorFactory.h>`,
152      },
153
154      // react-native-maps
155      {
156        paths: 'AIRMapWMSTile',
157        replace: /\b(TileOverlay)\b/g,
158        with: `${versionName}$1`,
159      },
160      {
161        paths: 'AIRGoogleMapWMSTile',
162        replace: /\b(WMSTileOverlay)\b/g,
163        with: `${versionName}$1`,
164      },
165      {
166        paths: 'AIRGoogleMap',
167        replace: new RegExp(`^#import "${versionName}(GMU.+?\\.h)"`, 'gm'),
168        with: `#import <Google-Maps-iOS-Utils/$1>`,
169      },
170
171      // react-native-webview
172      {
173        paths: 'RNCWebView.m',
174        replace: new RegExp(`#import "objc/${versionName}runtime\\.h"`, ''),
175        with: '#import "objc/runtime.h"',
176      },
177      {
178        paths: 'RNCWebView.m',
179        replace: /\b(_SwizzleHelperWK)\b/g,
180        with: `${versionName}$1`,
181      },
182      {
183        // see issue: https://github.com/expo/expo/issues/4463
184        paths: 'RNCWebView.m',
185        replace: /MessageHandlerName = @"ABI\d+_\d+_\d+ReactNativeWebView";/,
186        with: `MessageHandlerName = @"ReactNativeWebView";`,
187      },
188      {
189        paths: 'EXVersionManager.mm',
190        replace: /\[(RNCWebView)/,
191        with: `[${versionName}$1`,
192      },
193
194      // react-native-reanimated
195      {
196        paths: 'EXVersionManager.mm',
197        replace: /(_bridge_reanimated)/g,
198        with: `${versionName}$1`,
199      },
200      {
201        paths: 'EXVersionManager.mm',
202        replace: /\b(REA)/g,
203        with: `${versionName}$1`,
204      },
205      {
206        paths: 'NativeProxy.mm',
207        replace: /@"ABI\d+_\d+_\d+RCTView"/g,
208        with: `@"RCTView"`,
209      },
210
211      // react-native-shared-element
212      {
213        paths: 'RNSharedElementNode.m',
214        replace: /\b(NSArray\s*\*\s*_imageResolvers)\b/,
215        with: 'static $1',
216      },
217
218      // react-native-safe-area-context
219      {
220        paths: [
221          'RNCSafeAreaUtils.h',
222          'RNCSafeAreaUtils.m',
223          'RNCSafeAreaProvider.m',
224          'RNCSafeAreaView.m',
225        ],
226        replace: /\b(UIEdgeInsetsEqualToEdgeInsetsWithThreshold)\b/g,
227        with: `${versionName}$1`,
228      },
229    ],
230  };
231}
232