oxlint-plugin-react-doctor 0.2.17-dev.5614b32 → 0.2.18-dev.8d13ba3
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/index.js +32 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7346,6 +7346,13 @@ const isImportedFromModule = (contextNode, localIdentifierName, moduleSource) =>
|
|
|
7346
7346
|
if (!info) return false;
|
|
7347
7347
|
return info.source === moduleSource;
|
|
7348
7348
|
};
|
|
7349
|
+
const isNamespaceImportFromModule = (contextNode, localIdentifierName, moduleSource) => {
|
|
7350
|
+
const lookup = getImportLookup(contextNode);
|
|
7351
|
+
if (!lookup) return false;
|
|
7352
|
+
const info = lookup.get(localIdentifierName);
|
|
7353
|
+
if (!info) return false;
|
|
7354
|
+
return info.isNamespace && info.source === moduleSource;
|
|
7355
|
+
};
|
|
7349
7356
|
const getImportedNameFromModule = (contextNode, localIdentifierName, moduleSource) => {
|
|
7350
7357
|
const lookup = getImportLookup(contextNode);
|
|
7351
7358
|
if (!lookup) return null;
|
|
@@ -27048,6 +27055,11 @@ const LEGACY_EXPO_PACKAGE_REPLACEMENTS = new Map([
|
|
|
27048
27055
|
["expo-linear-gradient", "the `backgroundImage` CSS gradient style prop (New Architecture) or expo-linear-gradient's successor"],
|
|
27049
27056
|
["react-native-fast-image", "expo-image (drop-in with caching, placeholders, and crossfades)"]
|
|
27050
27057
|
]);
|
|
27058
|
+
const EXPO_UI_MODULE_SOURCES = new Set([
|
|
27059
|
+
"@expo/ui",
|
|
27060
|
+
"@expo/ui/swift-ui",
|
|
27061
|
+
"@expo/ui/jetpack-compose"
|
|
27062
|
+
]);
|
|
27051
27063
|
const REACT_NATIVE_LIST_COMPONENTS = new Set([
|
|
27052
27064
|
"FlatList",
|
|
27053
27065
|
"SectionList",
|
|
@@ -27859,6 +27871,24 @@ const collectTextWrapperComponents = (programNode, isTextHandlingRoot) => {
|
|
|
27859
27871
|
return wrappers;
|
|
27860
27872
|
};
|
|
27861
27873
|
//#endregion
|
|
27874
|
+
//#region src/plugin/rules/react-native/utils/is-expo-ui-component-element.ts
|
|
27875
|
+
const isNamedImportOf = (contextNode, localName, componentName) => {
|
|
27876
|
+
for (const moduleSource of EXPO_UI_MODULE_SOURCES) if (getImportedNameFromModule(contextNode, localName, moduleSource) === componentName) return true;
|
|
27877
|
+
return false;
|
|
27878
|
+
};
|
|
27879
|
+
const isExpoUiNamespaceImport = (contextNode, localName) => {
|
|
27880
|
+
for (const moduleSource of EXPO_UI_MODULE_SOURCES) if (isNamespaceImportFromModule(contextNode, localName, moduleSource)) return true;
|
|
27881
|
+
return false;
|
|
27882
|
+
};
|
|
27883
|
+
const isExpoUiComponentElement = (openingElement, contextNode, componentName) => {
|
|
27884
|
+
if (!openingElement.name) return false;
|
|
27885
|
+
const dottedName = flattenJsxName(openingElement.name);
|
|
27886
|
+
if (!dottedName) return false;
|
|
27887
|
+
const [rootLocalName, secondName] = dottedName.split(".");
|
|
27888
|
+
if (isNamedImportOf(contextNode, rootLocalName, componentName)) return true;
|
|
27889
|
+
return secondName === componentName && isExpoUiNamespaceImport(contextNode, rootLocalName);
|
|
27890
|
+
};
|
|
27891
|
+
//#endregion
|
|
27862
27892
|
//#region src/plugin/rules/react-native/rn-no-raw-text.ts
|
|
27863
27893
|
const truncateText = (text) => text.length > 30 ? `${text.slice(0, 30)}...` : text;
|
|
27864
27894
|
const isRawTextContent = (child) => {
|
|
@@ -27918,6 +27948,7 @@ const rnNoRawText = defineRule({
|
|
|
27918
27948
|
if (isDomComponentFile) return;
|
|
27919
27949
|
const elementName = resolveTextBoundaryName(node.openingElement);
|
|
27920
27950
|
if (elementName && (isTextHandlingComponent(elementName) || autoDetectedWrappers.has(elementName))) return;
|
|
27951
|
+
if (isExpoUiComponentElement(node.openingElement, node, "ListItem")) return;
|
|
27921
27952
|
if (isInsidePlatformOsWebBranch(node)) return;
|
|
27922
27953
|
if (isTransparentTextWrapper(elementName) && isInsideTextHandlingComponent(node)) return;
|
|
27923
27954
|
for (const child of node.children ?? []) {
|
|
@@ -28081,6 +28112,7 @@ const rnNoScrollviewMappedList = defineRule({
|
|
|
28081
28112
|
create: (context) => ({ JSXElement(node) {
|
|
28082
28113
|
const elementName = resolveJsxElementName(node.openingElement);
|
|
28083
28114
|
if (!elementName || !NON_VIRTUALIZED_SCROLL_CONTAINERS.has(elementName)) return;
|
|
28115
|
+
if (isExpoUiComponentElement(node.openingElement, node, "ScrollView")) return;
|
|
28084
28116
|
for (const child of node.children ?? []) {
|
|
28085
28117
|
if (!isNodeOfType(child, "JSXExpressionContainer")) continue;
|
|
28086
28118
|
const expression = child.expression;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oxlint-plugin-react-doctor",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.18-dev.8d13ba3",
|
|
4
4
|
"description": "oxlint plugin for React Doctor: diagnose React codebases for security, performance, correctness, accessibility, bundle-size, and architecture issues",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"accessibility",
|