@skapxd/eslint-opinionated 0.5.0 → 0.6.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/README.md +17 -0
- package/dist/{chunk-QNSHGNVQ.mjs → chunk-5BA4KA37.mjs} +55 -2
- package/dist/{chunk-QNSHGNVQ.mjs.map → chunk-5BA4KA37.mjs.map} +1 -1
- package/dist/index.js +55 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/shared/index.js +54 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -764,6 +764,23 @@ function Card() {
|
|
|
764
764
|
helper en minúscula **sí** pueden tener funciones dentro — ahí es donde se mueve
|
|
765
765
|
la lógica.
|
|
766
766
|
|
|
767
|
+
**Opciones** (desde v0.6.0) para permitir los dos patrones React idiomáticos
|
|
768
|
+
que la versión estricta bloqueaba — forzarlos a salir del componente producía
|
|
769
|
+
workarounds peores que el problema (`.bind(null, ...)`, adapters artificiales):
|
|
770
|
+
|
|
771
|
+
```js
|
|
772
|
+
"skapxd/no-functions-inside-components": ["error", {
|
|
773
|
+
allowJsxCallbacks: true, // <button onClick={() => onSelect(id)} />
|
|
774
|
+
allowArrayMapCallbacks: true, // {entries.map((entry) => <Entry key={entry.id} />)}
|
|
775
|
+
}]
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
Ambas exenciones aplican **solo a funciones anónimas inline en esa posición
|
|
779
|
+
exacta**: el valor directo de una prop JSX, o el primer argumento de `.map(...)`.
|
|
780
|
+
Un handler con nombre en el cuerpo (`const onClick = () => ...`), un callback de
|
|
781
|
+
`useEffect` o un `.forEach` siguen reportándose — la lógica con peso sigue
|
|
782
|
+
viviendo fuera del componente.
|
|
783
|
+
|
|
767
784
|
### `skapxd/no-try-catch`
|
|
768
785
|
|
|
769
786
|
Prohíbe `try/catch`. La intención es que los errores se modelen como `Result` en
|
|
@@ -1337,6 +1337,37 @@ var noDeepRelativeImports = {
|
|
|
1337
1337
|
}
|
|
1338
1338
|
};
|
|
1339
1339
|
|
|
1340
|
+
// src/utils/get-no-functions-inside-components-options.ts
|
|
1341
|
+
function getNoFunctionsInsideComponentsOptions(options = {}) {
|
|
1342
|
+
return {
|
|
1343
|
+
allowArrayMapCallbacks: options.allowArrayMapCallbacks ?? false,
|
|
1344
|
+
allowJsxCallbacks: options.allowJsxCallbacks ?? false
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
// src/utils/is-anonymous-inline-function.ts
|
|
1349
|
+
function isAnonymousInlineFunction(node) {
|
|
1350
|
+
if (node.type === "ArrowFunctionExpression") {
|
|
1351
|
+
return true;
|
|
1352
|
+
}
|
|
1353
|
+
return node.type === "FunctionExpression" && !node.id;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
// src/utils/is-array-map-callback.ts
|
|
1357
|
+
function isArrayMapCallback(node) {
|
|
1358
|
+
const parent = node.parent;
|
|
1359
|
+
if (parent?.type !== "CallExpression" || parent.arguments[0] !== node) {
|
|
1360
|
+
return false;
|
|
1361
|
+
}
|
|
1362
|
+
const callee = parent.callee;
|
|
1363
|
+
return callee?.type === "MemberExpression" && !callee.computed && callee.property?.type === "Identifier" && callee.property.name === "map";
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
// src/utils/is-jsx-attribute-callback.ts
|
|
1367
|
+
function isJsxAttributeCallback(node) {
|
|
1368
|
+
return node.parent?.type === "JSXExpressionContainer" && node.parent.parent?.type === "JSXAttribute";
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1340
1371
|
// src/rules/no-functions-inside-components.ts
|
|
1341
1372
|
var noFunctionsInsideComponents = {
|
|
1342
1373
|
meta: {
|
|
@@ -1347,17 +1378,39 @@ var noFunctionsInsideComponents = {
|
|
|
1347
1378
|
messages: {
|
|
1348
1379
|
functionInsideComponent: "No definas funciones dentro del componente `{{component}}`: se recrean en cada render. Muevela a un hook (`useX`) o a un helper fuera del componente."
|
|
1349
1380
|
},
|
|
1350
|
-
schema: [
|
|
1381
|
+
schema: [
|
|
1382
|
+
{
|
|
1383
|
+
additionalProperties: false,
|
|
1384
|
+
properties: {
|
|
1385
|
+
allowArrayMapCallbacks: { type: "boolean" },
|
|
1386
|
+
allowJsxCallbacks: { type: "boolean" }
|
|
1387
|
+
},
|
|
1388
|
+
type: "object"
|
|
1389
|
+
}
|
|
1390
|
+
]
|
|
1351
1391
|
},
|
|
1352
1392
|
create(context) {
|
|
1393
|
+
const options = getNoFunctionsInsideComponentsOptions(context.options[0]);
|
|
1353
1394
|
function isComponentFunction(node) {
|
|
1354
1395
|
return isFunctionNode(node) && isPascalCaseName(getFunctionName(node));
|
|
1355
1396
|
}
|
|
1397
|
+
function isAllowedInlineCallback(node) {
|
|
1398
|
+
if (!isAnonymousInlineFunction(node)) {
|
|
1399
|
+
return false;
|
|
1400
|
+
}
|
|
1401
|
+
if (options.allowJsxCallbacks && isJsxAttributeCallback(node)) {
|
|
1402
|
+
return true;
|
|
1403
|
+
}
|
|
1404
|
+
return options.allowArrayMapCallbacks && isArrayMapCallback(node);
|
|
1405
|
+
}
|
|
1356
1406
|
function reportIfInsideComponent(node) {
|
|
1357
1407
|
const enclosingFunction = getContainingFunction(node);
|
|
1358
1408
|
if (!enclosingFunction || !isComponentFunction(enclosingFunction)) {
|
|
1359
1409
|
return;
|
|
1360
1410
|
}
|
|
1411
|
+
if (isAllowedInlineCallback(node)) {
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1361
1414
|
context.report({
|
|
1362
1415
|
data: {
|
|
1363
1416
|
component: getFunctionName(enclosingFunction)
|
|
@@ -1556,4 +1609,4 @@ var rules = {
|
|
|
1556
1609
|
export {
|
|
1557
1610
|
rules
|
|
1558
1611
|
};
|
|
1559
|
-
//# sourceMappingURL=chunk-
|
|
1612
|
+
//# sourceMappingURL=chunk-5BA4KA37.mjs.map
|