diff --git a/packages/eslint-plugin/src/configs/recommended.ts b/packages/eslint-plugin/src/configs/recommended.ts index bd375d3e1a..40b689862d 100644 --- a/packages/eslint-plugin/src/configs/recommended.ts +++ b/packages/eslint-plugin/src/configs/recommended.ts @@ -20,6 +20,7 @@ const recommendedRules: Record = { '@builder.io/mitosis/use-state-var-declarator': 'error', '@builder.io/mitosis/static-control-flow': 'error', '@builder.io/mitosis/no-var-name-same-as-prop-name': 'error', + '@builder.io/mitosis/no-map-function-in-jsx-return-body': 'warning', }; export default { diff --git a/packages/eslint-plugin/src/rules/__tests__/no-map-function-in-jsx-return-body.ts b/packages/eslint-plugin/src/rules/__tests__/no-map-function-in-jsx-return-body.ts new file mode 100644 index 0000000000..225fd69f4c --- /dev/null +++ b/packages/eslint-plugin/src/rules/__tests__/no-map-function-in-jsx-return-body.ts @@ -0,0 +1,68 @@ +import { RuleTester } from 'eslint'; +import rule from '../no-map-function-in-jsx-return-body'; + +const opts = { + filename: 'component.lite.tsx', + parserOptions: { + ecmaVersion: 2018, + sourceType: 'module', + ecmaFeatures: { + jsx: true, + }, + }, +} as const; + +var ruleTester = new RuleTester(); + +ruleTester.run('no-map-function-in-jsx-return-body', rule, { + valid: [ + { + ...opts, + code: ` + import { useStore, For, onMount } from '@builder.io/mitosis'; + + export default function MyBasicForComponent() { + const state = useStore({ + name: 'Decadef20', + names: ['Steve', 'Decadef20'], + }); + + onMount(() => { + console.log('onMount code'); + }); + + return ( +
+ + {(person) => ( + <> + { + state.name = event.target.value + ' and ' + person; + }} + /> + Hello {person}! I can run in Qwik, Web Component, React, Vue, Solid, or Liquid! + + )} + +
+ ); + } + + `, + }, + ], + invalid: [ + { + ...opts, + code: ` + export default function MyComponent() { + + return
{[].map()}
+ } + `, + errors: ['No map function in jsx return body. Please use component instead.'], + }, + ], +}); diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index d21993c5e2..b400a438b8 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -12,6 +12,7 @@ import noVarNameSameAsStateProperty from './no-var-name-same-as-state-property'; import onlyDefaultFunctionAndImports from './only-default-function-and-imports'; import noConditionalLogicInComponentRender from './no-conditional-logic-in-component-render'; import noVarDeclarationOrAssignmentInComponent from './no-var-declaration-or-assignment-in-component'; +import noMapFunctionInJsxReturnBody from './no-map-function-in-jsx-return-body'; import { staticControlFlow } from './static-control-flow'; export const rules = { @@ -30,4 +31,5 @@ export const rules = { 'only-default-function-and-imports': onlyDefaultFunctionAndImports, 'no-conditional-logic-in-component-render': noConditionalLogicInComponentRender, 'no-var-declaration-or-assignment-in-component': noVarDeclarationOrAssignmentInComponent, + 'no-map-function-in-jsx-return-body': noMapFunctionInJsxReturnBody, }; diff --git a/packages/eslint-plugin/src/rules/no-map-function-in-jsx-return-body.ts b/packages/eslint-plugin/src/rules/no-map-function-in-jsx-return-body.ts new file mode 100644 index 0000000000..dd91e87198 --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-map-function-in-jsx-return-body.ts @@ -0,0 +1,39 @@ +import { Rule } from 'eslint'; +import * as types from '@babel/types'; +import isMitosisPath from '../helpers/isMitosisPath'; + +const rule: Rule.RuleModule = { + meta: { + type: 'problem', + docs: { + description: 'no map function in jsx return body', + recommended: true, + }, + }, + + create(context) { + if (!isMitosisPath(context.getFilename())) return {}; + + return { + JSXExpressionContainer(node) { + if (types.isJSXExpressionContainer(node)) { + if (types.isCallExpression(node.expression)) { + if ( + types.isMemberExpression(node.expression.callee) && + types.isIdentifier(node.expression.callee.property) && + node.expression.callee.property.name === 'map' + ) { + context.report({ + node: node as any, + message: + 'No map function in jsx return body. Please use component instead.', + }); + } + } + } + }, + }; + }, +}; + +export default rule;