react-native-boost 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/plugin/esm/index.mjs +528 -168
- package/dist/plugin/esm/index.mjs.map +1 -1
- package/dist/plugin/index.js +528 -168
- package/dist/plugin/index.js.map +1 -1
- package/dist/runtime/esm/index.mjs +2 -3
- package/dist/runtime/esm/index.mjs.map +1 -1
- package/dist/runtime/esm/index.web.mjs.map +1 -1
- package/dist/runtime/index.d.ts +2 -1
- package/dist/runtime/index.js +1 -2
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/index.web.d.ts +2 -1
- package/dist/runtime/index.web.js.map +1 -1
- package/package.json +12 -20
- package/src/plugin/index.ts +1 -1
- package/src/plugin/optimizers/text/index.ts +71 -72
- package/src/plugin/optimizers/view/index.ts +5 -25
- package/src/plugin/types/index.ts +12 -1
- package/src/plugin/utils/common/attributes.ts +165 -0
- package/src/plugin/utils/common/index.ts +1 -3
- package/src/plugin/utils/common/validation.ts +515 -0
- package/src/plugin/utils/constants.ts +9 -0
- package/src/plugin/utils/format-test-result.ts +29 -0
- package/src/plugin/utils/generate-test-plugin.ts +3 -3
- package/src/runtime/index.ts +2 -3
- package/src/runtime/types/react-native.d.ts +0 -6
- package/src/plugin/utils/common/ancestors.ts +0 -120
- package/src/plugin/utils/common/node-types.ts +0 -22
package/dist/plugin/index.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
var helperPluginUtils = require('@babel/helper-plugin-utils');
|
|
4
4
|
var core = require('@babel/core');
|
|
5
|
-
var helperModuleImports = require('@babel/helper-module-imports');
|
|
6
5
|
var minimatch = require('minimatch');
|
|
7
6
|
var nodePath = require('node:path');
|
|
7
|
+
var helperModuleImports = require('@babel/helper-module-imports');
|
|
8
8
|
|
|
9
9
|
class PluginError extends Error {
|
|
10
10
|
constructor(message) {
|
|
@@ -13,52 +13,6 @@ class PluginError extends Error {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
const RUNTIME_MODULE_NAME = "react-native-boost/runtime";
|
|
17
|
-
const ACCESSIBILITY_PROPERTIES = /* @__PURE__ */ new Set([
|
|
18
|
-
"accessibilityLabel",
|
|
19
|
-
"aria-label",
|
|
20
|
-
"accessibilityState",
|
|
21
|
-
"aria-busy",
|
|
22
|
-
"aria-checked",
|
|
23
|
-
"aria-disabled",
|
|
24
|
-
"aria-expanded",
|
|
25
|
-
"aria-selected",
|
|
26
|
-
"accessible"
|
|
27
|
-
]);
|
|
28
|
-
|
|
29
|
-
function addFileImportHint({
|
|
30
|
-
file,
|
|
31
|
-
nameHint,
|
|
32
|
-
path,
|
|
33
|
-
importName,
|
|
34
|
-
moduleName,
|
|
35
|
-
importType = "named"
|
|
36
|
-
}) {
|
|
37
|
-
var _a;
|
|
38
|
-
if (!((_a = file.__hasImports) == null ? void 0 : _a[nameHint])) {
|
|
39
|
-
file.__hasImports = file.__hasImports || {};
|
|
40
|
-
file.__hasImports[nameHint] = importType === "default" ? helperModuleImports.addDefault(path, moduleName, { nameHint }) : helperModuleImports.addNamed(path, importName, moduleName, { nameHint });
|
|
41
|
-
}
|
|
42
|
-
return file.__hasImports[nameHint];
|
|
43
|
-
}
|
|
44
|
-
const replaceWithNativeComponent = (path, parent, file, nativeComponentName) => {
|
|
45
|
-
const nativeIdentifier = addFileImportHint({
|
|
46
|
-
file,
|
|
47
|
-
nameHint: nativeComponentName,
|
|
48
|
-
path,
|
|
49
|
-
importName: nativeComponentName,
|
|
50
|
-
moduleName: RUNTIME_MODULE_NAME,
|
|
51
|
-
importType: "named"
|
|
52
|
-
});
|
|
53
|
-
const currentName = path.node.name.name;
|
|
54
|
-
const jsxName = path.node.name;
|
|
55
|
-
jsxName.name = nativeIdentifier.name;
|
|
56
|
-
if (!path.node.selfClosing && parent.closingElement && core.types.isJSXIdentifier(parent.closingElement.name) && parent.closingElement.name.name === currentName) {
|
|
57
|
-
parent.closingElement.name.name = nativeIdentifier.name;
|
|
58
|
-
}
|
|
59
|
-
return nativeIdentifier;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
16
|
const ensureArray = (value) => {
|
|
63
17
|
if (Array.isArray(value)) return value;
|
|
64
18
|
return [value];
|
|
@@ -159,6 +113,372 @@ const isReactNativeImport = (path, expectedImportedName) => {
|
|
|
159
113
|
}
|
|
160
114
|
return false;
|
|
161
115
|
};
|
|
116
|
+
const hasUnsafeViewAncestor = (path, allowUnknownAncestors = false) => {
|
|
117
|
+
const classification = classifyViewAncestors(path);
|
|
118
|
+
if (classification === "text") return true;
|
|
119
|
+
if (classification === "unknown" && !allowUnknownAncestors) return true;
|
|
120
|
+
return false;
|
|
121
|
+
};
|
|
122
|
+
function classifyViewAncestors(path) {
|
|
123
|
+
const context = {
|
|
124
|
+
componentCache: /* @__PURE__ */ new WeakMap(),
|
|
125
|
+
componentInProgress: /* @__PURE__ */ new WeakSet(),
|
|
126
|
+
renderExpressionInProgress: /* @__PURE__ */ new WeakSet()
|
|
127
|
+
};
|
|
128
|
+
let classification = "safe";
|
|
129
|
+
let ancestorPath = path.parentPath.parentPath;
|
|
130
|
+
while (ancestorPath) {
|
|
131
|
+
if (ancestorPath.isJSXElement()) {
|
|
132
|
+
const ancestorClassification = classifyJSXElementAsAncestor(ancestorPath, context);
|
|
133
|
+
classification = mergeAncestorClassification(classification, ancestorClassification);
|
|
134
|
+
if (classification === "text") return classification;
|
|
135
|
+
}
|
|
136
|
+
ancestorPath = ancestorPath.parentPath;
|
|
137
|
+
}
|
|
138
|
+
return classification;
|
|
139
|
+
}
|
|
140
|
+
function classifyJSXElementAsAncestor(path, context) {
|
|
141
|
+
const openingElementName = path.node.openingElement.name;
|
|
142
|
+
if (core.types.isJSXIdentifier(openingElementName)) {
|
|
143
|
+
return classifyJSXIdentifierAsAncestor(path, openingElementName.name, context);
|
|
144
|
+
}
|
|
145
|
+
if (core.types.isJSXMemberExpression(openingElementName)) {
|
|
146
|
+
return classifyJSXMemberExpressionAsAncestor(path, openingElementName);
|
|
147
|
+
}
|
|
148
|
+
return "unknown";
|
|
149
|
+
}
|
|
150
|
+
function classifyJSXIdentifierAsAncestor(path, identifierName, context) {
|
|
151
|
+
if (identifierName === "Fragment") return "safe";
|
|
152
|
+
const binding = path.scope.getBinding(identifierName);
|
|
153
|
+
if (!binding) return "unknown";
|
|
154
|
+
return classifyBindingAsAncestor(binding, context);
|
|
155
|
+
}
|
|
156
|
+
function classifyJSXMemberExpressionAsAncestor(path, expression) {
|
|
157
|
+
if (!core.types.isJSXIdentifier(expression.object) || !core.types.isJSXIdentifier(expression.property)) {
|
|
158
|
+
return "unknown";
|
|
159
|
+
}
|
|
160
|
+
const binding = path.scope.getBinding(expression.object.name);
|
|
161
|
+
if (!binding || binding.kind !== "module" || !core.types.isImportNamespaceSpecifier(binding.path.node)) {
|
|
162
|
+
return "unknown";
|
|
163
|
+
}
|
|
164
|
+
const importDeclaration = binding.path.parent;
|
|
165
|
+
if (!core.types.isImportDeclaration(importDeclaration)) return "unknown";
|
|
166
|
+
if (importDeclaration.source.value === "react-native") {
|
|
167
|
+
return expression.property.name === "Text" ? "text" : "safe";
|
|
168
|
+
}
|
|
169
|
+
if (importDeclaration.source.value === "react" && expression.property.name === "Fragment") {
|
|
170
|
+
return "safe";
|
|
171
|
+
}
|
|
172
|
+
return "unknown";
|
|
173
|
+
}
|
|
174
|
+
function classifyBindingAsAncestor(binding, context) {
|
|
175
|
+
if (binding.kind === "module") {
|
|
176
|
+
return classifyModuleBindingAsAncestor(binding);
|
|
177
|
+
}
|
|
178
|
+
return classifyLocalBindingAsAncestor(binding, context);
|
|
179
|
+
}
|
|
180
|
+
function classifyModuleBindingAsAncestor(binding) {
|
|
181
|
+
const importDeclaration = binding.path.parent;
|
|
182
|
+
if (!core.types.isImportDeclaration(importDeclaration)) return "unknown";
|
|
183
|
+
const source = importDeclaration.source.value;
|
|
184
|
+
if (source === "react-native") {
|
|
185
|
+
if (core.types.isImportSpecifier(binding.path.node)) {
|
|
186
|
+
const importedName = getImportSpecifierImportedName(binding.path.node);
|
|
187
|
+
if (!importedName) return "unknown";
|
|
188
|
+
return importedName === "Text" ? "text" : "safe";
|
|
189
|
+
}
|
|
190
|
+
if (core.types.isImportNamespaceSpecifier(binding.path.node)) {
|
|
191
|
+
return "safe";
|
|
192
|
+
}
|
|
193
|
+
return "unknown";
|
|
194
|
+
}
|
|
195
|
+
if (source === "react" && core.types.isImportSpecifier(binding.path.node)) {
|
|
196
|
+
const importedName = getImportSpecifierImportedName(binding.path.node);
|
|
197
|
+
if (importedName === "Fragment") return "safe";
|
|
198
|
+
}
|
|
199
|
+
return "unknown";
|
|
200
|
+
}
|
|
201
|
+
function classifyLocalBindingAsAncestor(binding, context) {
|
|
202
|
+
const cacheKey = binding.path.node;
|
|
203
|
+
const cached = context.componentCache.get(cacheKey);
|
|
204
|
+
if (cached) return cached;
|
|
205
|
+
if (context.componentInProgress.has(cacheKey)) {
|
|
206
|
+
return "unknown";
|
|
207
|
+
}
|
|
208
|
+
context.componentInProgress.add(cacheKey);
|
|
209
|
+
let classification;
|
|
210
|
+
if (binding.path.isFunctionDeclaration()) {
|
|
211
|
+
classification = analyzeFunctionComponent(binding.path, context);
|
|
212
|
+
} else if (binding.path.isVariableDeclarator()) {
|
|
213
|
+
classification = analyzeVariableDeclaratorComponent(binding.path, context);
|
|
214
|
+
} else {
|
|
215
|
+
classification = "unknown";
|
|
216
|
+
}
|
|
217
|
+
context.componentInProgress.delete(cacheKey);
|
|
218
|
+
context.componentCache.set(cacheKey, classification);
|
|
219
|
+
return classification;
|
|
220
|
+
}
|
|
221
|
+
function analyzeVariableDeclaratorComponent(path, context) {
|
|
222
|
+
const initPath = path.get("init");
|
|
223
|
+
if (!initPath.node) return "unknown";
|
|
224
|
+
if (initPath.isArrowFunctionExpression() || initPath.isFunctionExpression()) {
|
|
225
|
+
return analyzeFunctionComponent(initPath, context);
|
|
226
|
+
}
|
|
227
|
+
if (initPath.isCallExpression()) {
|
|
228
|
+
return analyzeCallWrappedComponent(initPath, context);
|
|
229
|
+
}
|
|
230
|
+
if (initPath.isIdentifier()) {
|
|
231
|
+
const aliasBinding = path.scope.getBinding(initPath.node.name);
|
|
232
|
+
if (!aliasBinding) return "unknown";
|
|
233
|
+
return classifyBindingAsAncestor(aliasBinding, context);
|
|
234
|
+
}
|
|
235
|
+
return "unknown";
|
|
236
|
+
}
|
|
237
|
+
function analyzeCallWrappedComponent(path, context) {
|
|
238
|
+
if (!isReactMemoOrForwardRefCall(path)) return "unknown";
|
|
239
|
+
const [firstArgumentPath] = path.get("arguments");
|
|
240
|
+
if (!(firstArgumentPath == null ? void 0 : firstArgumentPath.node)) return "unknown";
|
|
241
|
+
if (firstArgumentPath.isArrowFunctionExpression() || firstArgumentPath.isFunctionExpression()) {
|
|
242
|
+
return analyzeFunctionComponent(firstArgumentPath, context);
|
|
243
|
+
}
|
|
244
|
+
if (firstArgumentPath.isIdentifier()) {
|
|
245
|
+
const wrappedComponentBinding = path.scope.getBinding(firstArgumentPath.node.name);
|
|
246
|
+
if (!wrappedComponentBinding) return "unknown";
|
|
247
|
+
return classifyBindingAsAncestor(wrappedComponentBinding, context);
|
|
248
|
+
}
|
|
249
|
+
if (firstArgumentPath.isCallExpression()) {
|
|
250
|
+
return analyzeCallWrappedComponent(firstArgumentPath, context);
|
|
251
|
+
}
|
|
252
|
+
return "unknown";
|
|
253
|
+
}
|
|
254
|
+
function isReactMemoOrForwardRefCall(path) {
|
|
255
|
+
const calleePath = path.get("callee");
|
|
256
|
+
if (calleePath.isIdentifier()) {
|
|
257
|
+
if (!isMemoOrForwardRefName(calleePath.node.name)) return false;
|
|
258
|
+
const binding = path.scope.getBinding(calleePath.node.name);
|
|
259
|
+
return isReactImportBinding(binding);
|
|
260
|
+
}
|
|
261
|
+
if (calleePath.isMemberExpression()) {
|
|
262
|
+
const objectPath = calleePath.get("object");
|
|
263
|
+
const propertyPath = calleePath.get("property");
|
|
264
|
+
if (!objectPath.isIdentifier() || !propertyPath.isIdentifier()) return false;
|
|
265
|
+
if (!isMemoOrForwardRefName(propertyPath.node.name)) return false;
|
|
266
|
+
const objectBinding = path.scope.getBinding(objectPath.node.name);
|
|
267
|
+
return isReactImportBinding(objectBinding);
|
|
268
|
+
}
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
function isMemoOrForwardRefName(name) {
|
|
272
|
+
return name === "memo" || name === "forwardRef";
|
|
273
|
+
}
|
|
274
|
+
function isReactImportBinding(binding) {
|
|
275
|
+
if (!binding || binding.kind !== "module") return false;
|
|
276
|
+
const importDeclaration = binding.path.parent;
|
|
277
|
+
return core.types.isImportDeclaration(importDeclaration) && importDeclaration.source.value === "react";
|
|
278
|
+
}
|
|
279
|
+
function analyzeFunctionComponent(path, context) {
|
|
280
|
+
const bodyPath = path.get("body");
|
|
281
|
+
if (!bodyPath.isBlockStatement()) {
|
|
282
|
+
return analyzeRenderExpression(bodyPath, context);
|
|
283
|
+
}
|
|
284
|
+
let classification = "safe";
|
|
285
|
+
for (const statementPath of bodyPath.get("body")) {
|
|
286
|
+
if (!statementPath.isReturnStatement()) continue;
|
|
287
|
+
const argumentPath = statementPath.get("argument");
|
|
288
|
+
if (!argumentPath.node) continue;
|
|
289
|
+
const returnClassification = analyzeRenderExpression(argumentPath, context);
|
|
290
|
+
classification = mergeAncestorClassification(classification, returnClassification);
|
|
291
|
+
if (classification === "text") return classification;
|
|
292
|
+
}
|
|
293
|
+
return classification;
|
|
294
|
+
}
|
|
295
|
+
function analyzeRenderExpression(path, context) {
|
|
296
|
+
if (path.isJSXFragment()) {
|
|
297
|
+
return analyzeJSXChildren(path.get("children"), context);
|
|
298
|
+
}
|
|
299
|
+
let classification = "safe";
|
|
300
|
+
let hasJSX = false;
|
|
301
|
+
path.traverse({
|
|
302
|
+
JSXOpeningElement(jsxPath) {
|
|
303
|
+
hasJSX = true;
|
|
304
|
+
const jsxElementPath = jsxPath.parentPath;
|
|
305
|
+
if (!jsxElementPath.isJSXElement()) {
|
|
306
|
+
classification = mergeAncestorClassification(classification, "unknown");
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const jsxClassification = classifyJSXElementAsAncestor(jsxElementPath, context);
|
|
310
|
+
classification = mergeAncestorClassification(classification, jsxClassification);
|
|
311
|
+
if (classification === "text") {
|
|
312
|
+
jsxPath.stop();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
if (hasJSX) return classification;
|
|
317
|
+
if (path.isIdentifier()) {
|
|
318
|
+
return analyzeIdentifierRenderExpression(path, context);
|
|
319
|
+
}
|
|
320
|
+
if (path.isMemberExpression() && isPropsChildrenMemberExpression(path.node)) {
|
|
321
|
+
return "safe";
|
|
322
|
+
}
|
|
323
|
+
if (path.isNullLiteral() || path.isBooleanLiteral() || path.isNumericLiteral() || path.isStringLiteral() || path.isBigIntLiteral()) {
|
|
324
|
+
return "safe";
|
|
325
|
+
}
|
|
326
|
+
return "unknown";
|
|
327
|
+
}
|
|
328
|
+
function analyzeJSXChildren(children, context) {
|
|
329
|
+
let classification = "safe";
|
|
330
|
+
for (const childPath of children) {
|
|
331
|
+
if (childPath.isJSXElement()) {
|
|
332
|
+
const childClassification = classifyJSXElementAsAncestor(childPath, context);
|
|
333
|
+
classification = mergeAncestorClassification(classification, childClassification);
|
|
334
|
+
} else if (childPath.isJSXFragment()) {
|
|
335
|
+
const fragmentClassification = analyzeJSXChildren(childPath.get("children"), context);
|
|
336
|
+
classification = mergeAncestorClassification(classification, fragmentClassification);
|
|
337
|
+
} else if (childPath.isJSXExpressionContainer()) {
|
|
338
|
+
const expressionPath = childPath.get("expression");
|
|
339
|
+
if (!expressionPath.node || expressionPath.isJSXEmptyExpression()) continue;
|
|
340
|
+
const expressionClassification = analyzeRenderExpression(expressionPath, context);
|
|
341
|
+
classification = mergeAncestorClassification(classification, expressionClassification);
|
|
342
|
+
} else if (childPath.isJSXSpreadChild()) {
|
|
343
|
+
classification = mergeAncestorClassification(classification, "unknown");
|
|
344
|
+
}
|
|
345
|
+
if (classification === "text") {
|
|
346
|
+
return classification;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return classification;
|
|
350
|
+
}
|
|
351
|
+
function analyzeIdentifierRenderExpression(path, context) {
|
|
352
|
+
if (path.node.name === "children") return "safe";
|
|
353
|
+
const binding = path.scope.getBinding(path.node.name);
|
|
354
|
+
if (!binding) return "unknown";
|
|
355
|
+
if (binding.kind === "param") {
|
|
356
|
+
return binding.identifier.name === "children" ? "safe" : "unknown";
|
|
357
|
+
}
|
|
358
|
+
if (!binding.path.isVariableDeclarator()) return "unknown";
|
|
359
|
+
const cacheKey = binding.path.node;
|
|
360
|
+
if (context.renderExpressionInProgress.has(cacheKey)) {
|
|
361
|
+
return "unknown";
|
|
362
|
+
}
|
|
363
|
+
const initPath = binding.path.get("init");
|
|
364
|
+
if (!initPath.node) return "unknown";
|
|
365
|
+
context.renderExpressionInProgress.add(cacheKey);
|
|
366
|
+
const classification = analyzeRenderExpression(initPath, context);
|
|
367
|
+
context.renderExpressionInProgress.delete(cacheKey);
|
|
368
|
+
return classification;
|
|
369
|
+
}
|
|
370
|
+
function isPropsChildrenMemberExpression(expression) {
|
|
371
|
+
if (!core.types.isIdentifier(expression.object, { name: "props" })) return false;
|
|
372
|
+
if (!core.types.isIdentifier(expression.property, { name: "children" })) return false;
|
|
373
|
+
return !expression.computed;
|
|
374
|
+
}
|
|
375
|
+
function mergeAncestorClassification(current, next) {
|
|
376
|
+
if (current === "text" || next === "text") return "text";
|
|
377
|
+
if (current === "unknown" || next === "unknown") return "unknown";
|
|
378
|
+
return "safe";
|
|
379
|
+
}
|
|
380
|
+
function getImportSpecifierImportedName(specifier) {
|
|
381
|
+
if (core.types.isIdentifier(specifier.imported)) {
|
|
382
|
+
return specifier.imported.name;
|
|
383
|
+
}
|
|
384
|
+
if (core.types.isStringLiteral(specifier.imported)) {
|
|
385
|
+
return specifier.imported.value;
|
|
386
|
+
}
|
|
387
|
+
return void 0;
|
|
388
|
+
}
|
|
389
|
+
const hasExpoRouterLinkParentWithAsChild = (path) => {
|
|
390
|
+
const textElementPath = path.parentPath;
|
|
391
|
+
if (!textElementPath.isJSXElement()) return false;
|
|
392
|
+
let ancestorPath = textElementPath.parentPath;
|
|
393
|
+
while (ancestorPath) {
|
|
394
|
+
if (ancestorPath.isJSXElement()) {
|
|
395
|
+
if (!isExpoRouterLinkElement(ancestorPath)) return false;
|
|
396
|
+
return hasTruthyAsChildAttribute(ancestorPath.node.openingElement.attributes);
|
|
397
|
+
}
|
|
398
|
+
ancestorPath = ancestorPath.parentPath;
|
|
399
|
+
}
|
|
400
|
+
return false;
|
|
401
|
+
};
|
|
402
|
+
function isExpoRouterLinkElement(path) {
|
|
403
|
+
const openingElementName = path.node.openingElement.name;
|
|
404
|
+
if (core.types.isJSXIdentifier(openingElementName)) {
|
|
405
|
+
const binding = path.scope.getBinding(openingElementName.name);
|
|
406
|
+
if (!binding || binding.kind !== "module") return false;
|
|
407
|
+
if (!core.types.isImportSpecifier(binding.path.node)) return false;
|
|
408
|
+
const importDeclaration = binding.path.parent;
|
|
409
|
+
if (!core.types.isImportDeclaration(importDeclaration) || importDeclaration.source.value !== "expo-router") return false;
|
|
410
|
+
const imported = binding.path.node.imported;
|
|
411
|
+
return core.types.isIdentifier(imported, { name: "Link" }) || core.types.isStringLiteral(imported) && imported.value === "Link";
|
|
412
|
+
}
|
|
413
|
+
if (core.types.isJSXMemberExpression(openingElementName)) {
|
|
414
|
+
if (!core.types.isJSXIdentifier(openingElementName.object)) return false;
|
|
415
|
+
if (!core.types.isJSXIdentifier(openingElementName.property, { name: "Link" })) return false;
|
|
416
|
+
const namespaceBinding = path.scope.getBinding(openingElementName.object.name);
|
|
417
|
+
if (!namespaceBinding || namespaceBinding.kind !== "module") return false;
|
|
418
|
+
if (!core.types.isImportNamespaceSpecifier(namespaceBinding.path.node)) return false;
|
|
419
|
+
const importDeclaration = namespaceBinding.path.parent;
|
|
420
|
+
return core.types.isImportDeclaration(importDeclaration) && importDeclaration.source.value === "expo-router";
|
|
421
|
+
}
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
function hasTruthyAsChildAttribute(attributes) {
|
|
425
|
+
let asChildAttribute;
|
|
426
|
+
for (const attribute of attributes) {
|
|
427
|
+
if (core.types.isJSXAttribute(attribute) && core.types.isJSXIdentifier(attribute.name, { name: "asChild" })) {
|
|
428
|
+
asChildAttribute = attribute;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (!asChildAttribute) return false;
|
|
432
|
+
return isJSXAttributeValueTruthy(asChildAttribute.value);
|
|
433
|
+
}
|
|
434
|
+
function isJSXAttributeValueTruthy(value) {
|
|
435
|
+
if (!value) return true;
|
|
436
|
+
if (core.types.isStringLiteral(value)) return value.value.length > 0;
|
|
437
|
+
if (core.types.isJSXElement(value) || core.types.isJSXFragment(value)) return true;
|
|
438
|
+
if (core.types.isJSXExpressionContainer(value)) {
|
|
439
|
+
const staticTruthiness = getStaticExpressionTruthiness(value.expression);
|
|
440
|
+
return staticTruthiness != null ? staticTruthiness : true;
|
|
441
|
+
}
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
444
|
+
function getStaticExpressionTruthiness(expression) {
|
|
445
|
+
var _a, _b;
|
|
446
|
+
if (core.types.isJSXEmptyExpression(expression)) return false;
|
|
447
|
+
if (core.types.isBooleanLiteral(expression)) return expression.value;
|
|
448
|
+
if (core.types.isNullLiteral(expression)) return false;
|
|
449
|
+
if (core.types.isStringLiteral(expression)) return expression.value.length > 0;
|
|
450
|
+
if (core.types.isNumericLiteral(expression)) return expression.value !== 0 && !Number.isNaN(expression.value);
|
|
451
|
+
if (core.types.isBigIntLiteral(expression)) return expression.value !== "0";
|
|
452
|
+
if (core.types.isIdentifier(expression, { name: "undefined" })) return false;
|
|
453
|
+
if (core.types.isTemplateLiteral(expression) && expression.expressions.length === 0) {
|
|
454
|
+
return ((_b = (_a = expression.quasis[0]) == null ? void 0 : _a.value.cooked) != null ? _b : "").length > 0;
|
|
455
|
+
}
|
|
456
|
+
if (core.types.isUnaryExpression(expression, { operator: "!" })) {
|
|
457
|
+
const staticTruthiness = getStaticExpressionTruthiness(expression.argument);
|
|
458
|
+
return staticTruthiness === void 0 ? void 0 : !staticTruthiness;
|
|
459
|
+
}
|
|
460
|
+
return void 0;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const RUNTIME_MODULE_NAME = "react-native-boost/runtime";
|
|
464
|
+
const ACCESSIBILITY_PROPERTIES = /* @__PURE__ */ new Set([
|
|
465
|
+
"accessibilityLabel",
|
|
466
|
+
"aria-label",
|
|
467
|
+
"accessibilityState",
|
|
468
|
+
"aria-busy",
|
|
469
|
+
"aria-checked",
|
|
470
|
+
"aria-disabled",
|
|
471
|
+
"aria-expanded",
|
|
472
|
+
"aria-selected",
|
|
473
|
+
"accessible"
|
|
474
|
+
]);
|
|
475
|
+
const USER_SELECT_STYLE_TO_SELECTABLE_PROP = {
|
|
476
|
+
auto: true,
|
|
477
|
+
text: true,
|
|
478
|
+
none: false,
|
|
479
|
+
contain: true,
|
|
480
|
+
all: true
|
|
481
|
+
};
|
|
162
482
|
|
|
163
483
|
const hasBlacklistedProperty = (path, blacklist) => {
|
|
164
484
|
return path.node.attributes.some((attribute) => {
|
|
@@ -190,6 +510,47 @@ const hasBlacklistedProperty = (path, blacklist) => {
|
|
|
190
510
|
return false;
|
|
191
511
|
});
|
|
192
512
|
};
|
|
513
|
+
const addDefaultProperty = (path, key, value) => {
|
|
514
|
+
let propertyIsFound = false;
|
|
515
|
+
let hasUnresolvableSpread = false;
|
|
516
|
+
for (const attribute of path.node.attributes) {
|
|
517
|
+
if (core.types.isJSXAttribute(attribute) && attribute.name.name === key) {
|
|
518
|
+
propertyIsFound = true;
|
|
519
|
+
break;
|
|
520
|
+
}
|
|
521
|
+
if (core.types.isJSXSpreadAttribute(attribute)) {
|
|
522
|
+
if (core.types.isObjectExpression(attribute.argument)) {
|
|
523
|
+
const propertyInSpread = attribute.argument.properties.some(
|
|
524
|
+
(p) => core.types.isObjectProperty(p) && core.types.isIdentifier(p.key) && p.key.name === key || core.types.isObjectProperty(p) && core.types.isStringLiteral(p.key) && p.key.value === key
|
|
525
|
+
);
|
|
526
|
+
if (propertyInSpread) {
|
|
527
|
+
propertyIsFound = true;
|
|
528
|
+
break;
|
|
529
|
+
}
|
|
530
|
+
} else if (core.types.isIdentifier(attribute.argument)) {
|
|
531
|
+
const binding = path.scope.getBinding(attribute.argument.name);
|
|
532
|
+
if ((binding == null ? void 0 : binding.path.node) && core.types.isVariableDeclarator(binding.path.node) && core.types.isObjectExpression(binding.path.node.init)) {
|
|
533
|
+
const propertyInSpread = binding.path.node.init.properties.some(
|
|
534
|
+
(p) => core.types.isObjectProperty(p) && core.types.isIdentifier(p.key) && p.key.name === key || core.types.isObjectProperty(p) && core.types.isStringLiteral(p.key) && p.key.value === key
|
|
535
|
+
);
|
|
536
|
+
if (propertyInSpread) {
|
|
537
|
+
propertyIsFound = true;
|
|
538
|
+
break;
|
|
539
|
+
}
|
|
540
|
+
} else {
|
|
541
|
+
hasUnresolvableSpread = true;
|
|
542
|
+
break;
|
|
543
|
+
}
|
|
544
|
+
} else {
|
|
545
|
+
hasUnresolvableSpread = true;
|
|
546
|
+
break;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
if (!propertyIsFound && !hasUnresolvableSpread) {
|
|
551
|
+
path.node.attributes.push(core.types.jsxAttribute(core.types.jsxIdentifier(key), core.types.jsxExpressionContainer(value)));
|
|
552
|
+
}
|
|
553
|
+
};
|
|
193
554
|
const buildPropertiesFromAttributes = (attributes) => {
|
|
194
555
|
const arguments_ = [];
|
|
195
556
|
for (const attribute of attributes) {
|
|
@@ -255,7 +616,54 @@ const hasAccessibilityProperty = (path, attributes) => {
|
|
|
255
616
|
}
|
|
256
617
|
return false;
|
|
257
618
|
};
|
|
258
|
-
|
|
619
|
+
function extractStyleAttribute(attributes) {
|
|
620
|
+
for (const attribute of attributes) {
|
|
621
|
+
if (core.types.isJSXAttribute(attribute) && core.types.isJSXIdentifier(attribute.name, { name: "style" })) {
|
|
622
|
+
if (attribute.value && core.types.isJSXExpressionContainer(attribute.value) && !core.types.isJSXEmptyExpression(attribute.value.expression)) {
|
|
623
|
+
return {
|
|
624
|
+
styleAttribute: attribute,
|
|
625
|
+
styleExpr: attribute.value.expression
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
return { styleAttribute: attribute };
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return {};
|
|
632
|
+
}
|
|
633
|
+
function extractSelectableAndUpdateStyle(styleExpr) {
|
|
634
|
+
const handleObjectExpression = (objectExpr) => {
|
|
635
|
+
let selectableValue;
|
|
636
|
+
objectExpr.properties = objectExpr.properties.filter((property) => {
|
|
637
|
+
if (!core.types.isObjectProperty(property) || !core.types.isIdentifier(property.key, { name: "userSelect" }) && !(core.types.isStringLiteral(property.key) && property.key.value === "userSelect")) {
|
|
638
|
+
return true;
|
|
639
|
+
}
|
|
640
|
+
if (core.types.isStringLiteral(property.value)) {
|
|
641
|
+
const mapped = USER_SELECT_STYLE_TO_SELECTABLE_PROP[property.value.value];
|
|
642
|
+
if (mapped !== void 0) {
|
|
643
|
+
selectableValue = mapped;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
return false;
|
|
647
|
+
});
|
|
648
|
+
return selectableValue;
|
|
649
|
+
};
|
|
650
|
+
if (core.types.isObjectExpression(styleExpr)) {
|
|
651
|
+
return handleObjectExpression(styleExpr);
|
|
652
|
+
}
|
|
653
|
+
if (core.types.isArrayExpression(styleExpr)) {
|
|
654
|
+
let selectableValue;
|
|
655
|
+
for (const element of styleExpr.elements) {
|
|
656
|
+
if (element && core.types.isObjectExpression(element)) {
|
|
657
|
+
const value = handleObjectExpression(element);
|
|
658
|
+
if (value !== void 0) {
|
|
659
|
+
selectableValue = value;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
return selectableValue;
|
|
664
|
+
}
|
|
665
|
+
return void 0;
|
|
666
|
+
}
|
|
259
667
|
const isStringNode = (path, child) => {
|
|
260
668
|
if (core.types.isJSXText(child) || core.types.isStringLiteral(child)) return true;
|
|
261
669
|
if (core.types.isJSXExpressionContainer(child)) {
|
|
@@ -272,63 +680,40 @@ const isStringNode = (path, child) => {
|
|
|
272
680
|
return false;
|
|
273
681
|
};
|
|
274
682
|
|
|
275
|
-
function
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
if (skipComponents.includes(ancestorComponentName)) {
|
|
289
|
-
return false;
|
|
290
|
-
}
|
|
291
|
-
if (ancestorComponentName[0] === ancestorComponentName[0].toLowerCase()) {
|
|
292
|
-
return false;
|
|
293
|
-
}
|
|
294
|
-
const binding = parentPath.scope.getBinding(ancestorComponentName);
|
|
295
|
-
if (!binding) return false;
|
|
296
|
-
if (core.types.isVariableDeclarator(binding.path.node)) {
|
|
297
|
-
const init = binding.path.node.init;
|
|
298
|
-
if (core.types.isArrowFunctionExpression(init) || core.types.isFunctionExpression(init)) {
|
|
299
|
-
return core.types.isBlockStatement(init.body) ? hasComponentInReturnStatement(init.body, componentName) : hasComponentInExpression(init.body, componentName);
|
|
300
|
-
}
|
|
301
|
-
} else if (core.types.isFunctionDeclaration(binding.path.node)) {
|
|
302
|
-
return hasComponentInReturnStatement(binding.path.node.body, componentName);
|
|
303
|
-
}
|
|
304
|
-
return false;
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
function hasComponentInReturnStatement(blockStatement, componentName) {
|
|
308
|
-
for (const statement of blockStatement.body) {
|
|
309
|
-
if (core.types.isReturnStatement(statement) && statement.argument && hasComponentInExpression(statement.argument, componentName)) {
|
|
310
|
-
return true;
|
|
311
|
-
}
|
|
683
|
+
function addFileImportHint({
|
|
684
|
+
file,
|
|
685
|
+
nameHint,
|
|
686
|
+
path,
|
|
687
|
+
importName,
|
|
688
|
+
moduleName,
|
|
689
|
+
importType = "named"
|
|
690
|
+
}) {
|
|
691
|
+
var _a;
|
|
692
|
+
if (!((_a = file.__hasImports) == null ? void 0 : _a[nameHint])) {
|
|
693
|
+
file.__hasImports = file.__hasImports || {};
|
|
694
|
+
file.__hasImports[nameHint] = importType === "default" ? helperModuleImports.addDefault(path, moduleName, { nameHint }) : helperModuleImports.addNamed(path, importName, moduleName, { nameHint });
|
|
312
695
|
}
|
|
313
|
-
return
|
|
696
|
+
return file.__hasImports[nameHint];
|
|
314
697
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
698
|
+
const replaceWithNativeComponent = (path, parent, file, nativeComponentName) => {
|
|
699
|
+
const nativeIdentifier = addFileImportHint({
|
|
700
|
+
file,
|
|
701
|
+
nameHint: nativeComponentName,
|
|
702
|
+
path,
|
|
703
|
+
importName: nativeComponentName,
|
|
704
|
+
moduleName: RUNTIME_MODULE_NAME,
|
|
705
|
+
importType: "named"
|
|
706
|
+
});
|
|
707
|
+
const currentName = path.node.name.name;
|
|
708
|
+
const jsxName = path.node.name;
|
|
709
|
+
jsxName.name = nativeIdentifier.name;
|
|
710
|
+
if (!path.node.selfClosing && parent.closingElement && core.types.isJSXIdentifier(parent.closingElement.name) && parent.closingElement.name.name === currentName) {
|
|
711
|
+
parent.closingElement.name.name = nativeIdentifier.name;
|
|
325
712
|
}
|
|
326
|
-
return
|
|
327
|
-
}
|
|
713
|
+
return nativeIdentifier;
|
|
714
|
+
};
|
|
328
715
|
|
|
329
716
|
const textBlacklistedProperties = /* @__PURE__ */ new Set([
|
|
330
|
-
"allowFontScaling",
|
|
331
|
-
"ellipsizeMode",
|
|
332
717
|
"id",
|
|
333
718
|
"nativeID",
|
|
334
719
|
"onLongPress",
|
|
@@ -343,8 +728,8 @@ const textBlacklistedProperties = /* @__PURE__ */ new Set([
|
|
|
343
728
|
"onStartShouldSetResponder",
|
|
344
729
|
"pressRetentionOffset",
|
|
345
730
|
"suppressHighlighting",
|
|
346
|
-
"selectable",
|
|
347
731
|
"selectionColor"
|
|
732
|
+
// TODO: we can use react-native's internal `processColor` to process this at runtime
|
|
348
733
|
]);
|
|
349
734
|
const textOptimizer = (path, log = () => {
|
|
350
735
|
}) => {
|
|
@@ -353,6 +738,7 @@ const textOptimizer = (path, log = () => {
|
|
|
353
738
|
if (!isValidJSXComponent(path, "Text")) return;
|
|
354
739
|
if (!isReactNativeImport(path, "Text")) return;
|
|
355
740
|
if (hasBlacklistedProperty(path, textBlacklistedProperties)) return;
|
|
741
|
+
if (hasExpoRouterLinkParentWithAsChild(path)) return;
|
|
356
742
|
const parent = path.parent;
|
|
357
743
|
if (hasInvalidChildren(path, parent)) return;
|
|
358
744
|
const hub = path.hub;
|
|
@@ -363,9 +749,10 @@ const textOptimizer = (path, log = () => {
|
|
|
363
749
|
const filename = ((_a = file.opts) == null ? void 0 : _a.filename) || "unknown file";
|
|
364
750
|
const lineNumber = (_c = (_b = path.node.loc) == null ? void 0 : _b.start.line) != null ? _c : "unknown line";
|
|
365
751
|
log(`Optimizing Text component in ${filename}:${lineNumber}`);
|
|
366
|
-
const originalAttributes = [...path.node.attributes];
|
|
367
752
|
fixNegativeNumberOfLines({ path, log });
|
|
368
|
-
|
|
753
|
+
addDefaultProperty(path, "allowFontScaling", core.types.booleanLiteral(true));
|
|
754
|
+
addDefaultProperty(path, "ellipsizeMode", core.types.stringLiteral("tail"));
|
|
755
|
+
processProps(path, file);
|
|
369
756
|
replaceWithNativeComponent(path, parent, file, "NativeText");
|
|
370
757
|
};
|
|
371
758
|
function hasInvalidChildren(path, parent) {
|
|
@@ -399,27 +786,16 @@ function fixNegativeNumberOfLines({
|
|
|
399
786
|
}
|
|
400
787
|
}
|
|
401
788
|
}
|
|
402
|
-
function
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
return {};
|
|
415
|
-
}
|
|
416
|
-
function processProps(path, file, originalAttributes) {
|
|
417
|
-
const { styleExpr } = extractStyleAttribute(originalAttributes);
|
|
418
|
-
const hasA11y = hasAccessibilityProperty(path, originalAttributes);
|
|
419
|
-
if (styleExpr && hasA11y) {
|
|
420
|
-
const accessibilityAttributes = originalAttributes.filter(
|
|
421
|
-
(attribute) => !(core.types.isJSXAttribute(attribute) && core.types.isJSXIdentifier(attribute.name, { name: "style" }))
|
|
422
|
-
);
|
|
789
|
+
function processProps(path, file) {
|
|
790
|
+
const currentAttributes = [...path.node.attributes];
|
|
791
|
+
const { styleExpr, styleAttribute } = extractStyleAttribute(currentAttributes);
|
|
792
|
+
const hasA11y = hasAccessibilityProperty(path, currentAttributes);
|
|
793
|
+
const spreadAttributes = [];
|
|
794
|
+
if (hasA11y) {
|
|
795
|
+
const accessibilityAttributes = currentAttributes.filter((attribute) => {
|
|
796
|
+
if (!core.types.isJSXAttribute(attribute)) return false;
|
|
797
|
+
return core.types.isJSXIdentifier(attribute.name) && ACCESSIBILITY_PROPERTIES.has(attribute.name.name);
|
|
798
|
+
});
|
|
423
799
|
const normalizeIdentifier = addFileImportHint({
|
|
424
800
|
file,
|
|
425
801
|
nameHint: "processAccessibilityProps",
|
|
@@ -429,6 +805,17 @@ function processProps(path, file, originalAttributes) {
|
|
|
429
805
|
});
|
|
430
806
|
const accessibilityObject = buildPropertiesFromAttributes(accessibilityAttributes);
|
|
431
807
|
const accessibilityExpr = core.types.callExpression(core.types.identifier(normalizeIdentifier.name), [accessibilityObject]);
|
|
808
|
+
spreadAttributes.push(core.types.jsxSpreadAttribute(accessibilityExpr));
|
|
809
|
+
}
|
|
810
|
+
let selectableAttribute;
|
|
811
|
+
if (styleExpr) {
|
|
812
|
+
const selectableValue = extractSelectableAndUpdateStyle(styleExpr);
|
|
813
|
+
if (selectableValue != null) {
|
|
814
|
+
selectableAttribute = core.types.jsxAttribute(
|
|
815
|
+
core.types.jsxIdentifier("selectable"),
|
|
816
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(selectableValue))
|
|
817
|
+
);
|
|
818
|
+
}
|
|
432
819
|
const flattenIdentifier = addFileImportHint({
|
|
433
820
|
file,
|
|
434
821
|
nameHint: "processTextStyle",
|
|
@@ -437,29 +824,19 @@ function processProps(path, file, originalAttributes) {
|
|
|
437
824
|
moduleName: RUNTIME_MODULE_NAME
|
|
438
825
|
});
|
|
439
826
|
const flattenedStyleExpr = core.types.callExpression(core.types.identifier(flattenIdentifier.name), [styleExpr]);
|
|
440
|
-
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
const flattened = core.types.callExpression(core.types.identifier(flattenIdentifier.name), [styleExpr]);
|
|
450
|
-
path.node.attributes = [core.types.jsxSpreadAttribute(flattened)];
|
|
451
|
-
} else if (hasA11y) {
|
|
452
|
-
const normalizeIdentifier = addFileImportHint({
|
|
453
|
-
file,
|
|
454
|
-
nameHint: "processAccessibilityProps",
|
|
455
|
-
path,
|
|
456
|
-
importName: "processAccessibilityProps",
|
|
457
|
-
moduleName: RUNTIME_MODULE_NAME
|
|
458
|
-
});
|
|
459
|
-
const propsObject = buildPropertiesFromAttributes(originalAttributes);
|
|
460
|
-
const normalized = core.types.callExpression(core.types.identifier(normalizeIdentifier.name), [propsObject]);
|
|
461
|
-
path.node.attributes = [core.types.jsxSpreadAttribute(normalized)];
|
|
827
|
+
spreadAttributes.push(core.types.jsxSpreadAttribute(flattenedStyleExpr));
|
|
828
|
+
}
|
|
829
|
+
const remainingAttributes = [];
|
|
830
|
+
for (const attribute of currentAttributes) {
|
|
831
|
+
if (styleAttribute && attribute === styleAttribute) continue;
|
|
832
|
+
if (hasA11y && core.types.isJSXAttribute(attribute) && core.types.isJSXIdentifier(attribute.name) && ACCESSIBILITY_PROPERTIES.has(attribute.name.name)) {
|
|
833
|
+
continue;
|
|
834
|
+
}
|
|
835
|
+
remainingAttributes.push(attribute);
|
|
462
836
|
}
|
|
837
|
+
path.node.attributes = [...spreadAttributes, selectableAttribute, ...remainingAttributes].filter(
|
|
838
|
+
(attribute) => attribute !== void 0
|
|
839
|
+
);
|
|
463
840
|
}
|
|
464
841
|
|
|
465
842
|
const log = (message) => {
|
|
@@ -467,46 +844,29 @@ const log = (message) => {
|
|
|
467
844
|
};
|
|
468
845
|
|
|
469
846
|
const viewBlacklistedProperties = /* @__PURE__ */ new Set([
|
|
847
|
+
// TODO: process a11y props at runtime
|
|
470
848
|
"accessible",
|
|
471
849
|
"accessibilityLabel",
|
|
472
850
|
"accessibilityState",
|
|
473
|
-
"allowFontScaling",
|
|
474
851
|
"aria-busy",
|
|
475
852
|
"aria-checked",
|
|
476
853
|
"aria-disabled",
|
|
477
854
|
"aria-expanded",
|
|
478
855
|
"aria-label",
|
|
479
856
|
"aria-selected",
|
|
480
|
-
"ellipsizeMode",
|
|
481
|
-
"disabled",
|
|
482
857
|
"id",
|
|
483
858
|
"nativeID",
|
|
484
|
-
"numberOfLines",
|
|
485
|
-
"onLongPress",
|
|
486
|
-
"onPress",
|
|
487
|
-
"onPressIn",
|
|
488
|
-
"onPressOut",
|
|
489
|
-
"onResponderGrant",
|
|
490
|
-
"onResponderMove",
|
|
491
|
-
"onResponderRelease",
|
|
492
|
-
"onResponderTerminate",
|
|
493
|
-
"onResponderTerminationRequest",
|
|
494
|
-
"onStartShouldSetResponder",
|
|
495
|
-
"pressRetentionOffset",
|
|
496
|
-
"selectable",
|
|
497
|
-
"selectionColor",
|
|
498
|
-
"suppressHighlighting",
|
|
499
859
|
"style"
|
|
860
|
+
// TODO: process style at runtime
|
|
500
861
|
]);
|
|
501
|
-
const skipComponents = ["View", "Fragment", "ScrollView", "FlatList"];
|
|
502
862
|
const viewOptimizer = (path, log = () => {
|
|
503
|
-
}) => {
|
|
863
|
+
}, options) => {
|
|
504
864
|
var _a, _b, _c;
|
|
505
865
|
if (isIgnoredLine(path)) return;
|
|
506
866
|
if (!isValidJSXComponent(path, "View")) return;
|
|
507
867
|
if (!isReactNativeImport(path, "View")) return;
|
|
508
868
|
if (hasBlacklistedProperty(path, viewBlacklistedProperties)) return;
|
|
509
|
-
if (
|
|
869
|
+
if (hasUnsafeViewAncestor(path, (options == null ? void 0 : options.dangerouslyOptimizeViewWithUnknownAncestors) === true)) return;
|
|
510
870
|
const hub = path.hub;
|
|
511
871
|
const file = typeof hub === "object" && hub !== null && "file" in hub ? hub.file : void 0;
|
|
512
872
|
if (!file) {
|
|
@@ -531,7 +891,7 @@ var index = helperPluginUtils.declare((api) => {
|
|
|
531
891
|
};
|
|
532
892
|
if (isIgnoredFile(path, (_b = options.ignores) != null ? _b : [])) return;
|
|
533
893
|
if (((_c = options.optimizations) == null ? void 0 : _c.text) !== false) textOptimizer(path, logger);
|
|
534
|
-
if (((_d = options.optimizations) == null ? void 0 : _d.view) !== false) viewOptimizer(path, logger);
|
|
894
|
+
if (((_d = options.optimizations) == null ? void 0 : _d.view) !== false) viewOptimizer(path, logger, options);
|
|
535
895
|
}
|
|
536
896
|
}
|
|
537
897
|
};
|