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