From 6a83d67842b79e472fdb301f567b66218df53f66 Mon Sep 17 00:00:00 2001 From: akulsr0 Date: Fri, 21 Jun 2024 11:50:26 +0530 Subject: [PATCH] [New] `jsx-handler-names`: support ignoring component names --- CHANGELOG.md | 2 ++ docs/rules/jsx-handler-names.md | 4 ++- lib/rules/jsx-handler-names.js | 36 ++++++++++++++++++++++ tests/lib/rules/jsx-handler-names.js | 46 ++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54b106d9ba..d138fc53d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,10 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange * export flat configs from plugin root and fix flat config crash ([#3694][] @bradzacher @mdjermanovic) * add [`jsx-props-no-spread-multi`] ([#3724][] @SimonSchick) * [`forbid-component-props`]: add `propNamePattern` to allow / disallow prop name patterns ([#3774][] @akulsr0) +* [`jsx-handler-names`]: support ignoring component names ([#3772][] @akulsr0) [#3774]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3774 +[#3772]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3772 [#3759]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3759 [#3724]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3724 [#3694]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3694 diff --git a/docs/rules/jsx-handler-names.md b/docs/rules/jsx-handler-names.md index ced349f374..8e93a1679f 100644 --- a/docs/rules/jsx-handler-names.md +++ b/docs/rules/jsx-handler-names.md @@ -34,7 +34,8 @@ Examples of **correct** code for this rule: "eventHandlerPrefix": , "eventHandlerPropPrefix": , "checkLocalVariables": , - "checkInlineFunction": + "checkInlineFunction": , + "ignoreComponentNames": Array }] ... ``` @@ -43,6 +44,7 @@ Examples of **correct** code for this rule: - `eventHandlerPropPrefix`: Prefix for props that are used as event handlers. Defaults to `on` - `checkLocalVariables`: Determines whether event handlers stored as local variables are checked. Defaults to `false` - `checkInlineFunction`: Determines whether event handlers set as inline functions are checked. Defaults to `false` +- `ignoreComponentNames`: Array of glob strings, when matched with component name, ignores the rule on that component. Defaults to `[]` ## When Not To Use It diff --git a/lib/rules/jsx-handler-names.js b/lib/rules/jsx-handler-names.js index d839073a52..652e125d6e 100644 --- a/lib/rules/jsx-handler-names.js +++ b/lib/rules/jsx-handler-names.js @@ -5,6 +5,7 @@ 'use strict'; +const minimatch = require('minimatch'); const docsUrl = require('../util/docsUrl'); const getText = require('../util/eslint').getText; const report = require('../util/report'); @@ -39,6 +40,11 @@ module.exports = { eventHandlerPropPrefix: { type: 'string' }, checkLocalVariables: { type: 'boolean' }, checkInlineFunction: { type: 'boolean' }, + ignoreComponentNames: { + type: 'array', + uniqueItems: true, + items: { type: 'string' }, + }, }, additionalProperties: false, }, { @@ -51,6 +57,11 @@ module.exports = { }, checkLocalVariables: { type: 'boolean' }, checkInlineFunction: { type: 'boolean' }, + ignoreComponentNames: { + type: 'array', + uniqueItems: true, + items: { type: 'string' }, + }, }, additionalProperties: false, }, { @@ -63,6 +74,11 @@ module.exports = { eventHandlerPropPrefix: { type: 'string' }, checkLocalVariables: { type: 'boolean' }, checkInlineFunction: { type: 'boolean' }, + ignoreComponentNames: { + type: 'array', + uniqueItems: true, + items: { type: 'string' }, + }, }, additionalProperties: false, }, { @@ -78,6 +94,16 @@ module.exports = { }, additionalProperties: false, }, + { + type: 'object', + properties: { + ignoreComponentNames: { + type: 'array', + uniqueItems: true, + items: { type: 'string' }, + }, + }, + }, ], }], }, @@ -111,8 +137,17 @@ module.exports = { const checkInlineFunction = !!configuration.checkInlineFunction; + const ignoreComponentNames = configuration.ignoreComponentNames || []; + return { JSXAttribute(node) { + const componentName = node.parent.name.name; + + const isComponentNameIgnored = ignoreComponentNames.some((ignoredComponentNamePattern) => { + const isIgnored = minimatch(componentName, ignoredComponentNamePattern); + return isIgnored; + }); + if ( !node.value || !node.value.expression @@ -124,6 +159,7 @@ module.exports = { : !node.value.expression.object ) ) + || isComponentNameIgnored ) { return; } diff --git a/tests/lib/rules/jsx-handler-names.js b/tests/lib/rules/jsx-handler-names.js index 47adbe85ae..3ad3378abf 100644 --- a/tests/lib/rules/jsx-handler-names.js +++ b/tests/lib/rules/jsx-handler-names.js @@ -181,6 +181,24 @@ ruleTester.run('jsx-handler-names', rule, { code: '', options: [{ eventHandlerPropPrefix: false }], }, + { + code: ';', + options: [{ checkLocalVariables: true, ignoreComponentNames: ['ComponentFromOtherLibraryBar'] }], + }, + { + code: ` + function App() { + return ( +
+ ; + ; + ; +
+ ) + } + `, + options: [{ checkLocalVariables: true, ignoreComponentNames: ['MyLib*'] }], + }, ]), invalid: parsers.all([ @@ -369,5 +387,33 @@ ruleTester.run('jsx-handler-names', rule, { }, ], }, + { + code: ` + function App() { + return ( +
+ ; + ; + ; +
+ ) + } + `, + options: [{ checkLocalVariables: true, ignoreComponentNames: ['MyLibrary*'] }], + errors: [ + { + messageId: 'badPropKey', + data: { propValue: 'handleInput', handlerPropPrefix: 'on' }, + }, + { + messageId: 'badPropKey', + data: { propValue: 'handleCheckbox', handlerPropPrefix: 'on' }, + }, + { + messageId: 'badPropKey', + data: { propValue: 'handleButton', handlerPropPrefix: 'on' }, + }, + ], + }, ]), });