diff --git a/CHANGELOG.md b/CHANGELOG.md index aeeae53a8e..b264f6356c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange * [`no-unknown-property`]: allow `onLoad` on `source` (@ljharb) * [`jsx-first-prop-new-line`]: ensure autofix preserves generics in component name ([#3546][] @ljharb) * [`no-unknown-property`]: allow `fill` prop on `` ([#3555][] @stefanprobst) +* [`display-name`], [`prop-types`]: when checking for a capitalized name, ignore underscores entirely ([#3560][] @ljharb) +[#3560]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3560 [#3555]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3555 [#3548]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3548 [#3546]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3546 diff --git a/lib/util/isFirstLetterCapitalized.js b/lib/util/isFirstLetterCapitalized.js index 819edc8860..bc55a1970b 100644 --- a/lib/util/isFirstLetterCapitalized.js +++ b/lib/util/isFirstLetterCapitalized.js @@ -6,10 +6,10 @@ * @returns {Boolean} True if first letter is capitalized. */ function isFirstLetterCapitalized(word) { - if (!word || word.charAt(0) === '_') { + if (!word) { return false; } - const firstLetter = word.charAt(0); + const firstLetter = word.replace(/^_+/, '').charAt(0); return firstLetter.toUpperCase() === firstLetter; } diff --git a/tests/lib/rules/prop-types.js b/tests/lib/rules/prop-types.js index 51afd582e8..e17d63661c 100644 --- a/tests/lib/rules/prop-types.js +++ b/tests/lib/rules/prop-types.js @@ -8199,6 +8199,55 @@ ruleTester.run('prop-types', rule, { data: { name: 'foo' }, }, ], + }, + { + code: ` + function _EventsList({ prop_ }) { + return ( +
+ {prop_.events.map((event) => ( + + ))} +
+ ); + } + + function $EventsList({ prop$ }) { + return ( +
+ {prop$.events.map((event) => ( + + ))} +
+ ); + } + `, + errors: [ + { + messageId: 'missingPropType', + data: { name: 'prop_' }, + }, + { + messageId: 'missingPropType', + data: { name: 'prop_.events' }, + }, + { + messageId: 'missingPropType', + data: { name: 'prop_.events.map' }, + }, + { + messageId: 'missingPropType', + data: { name: 'prop$' }, + }, + { + messageId: 'missingPropType', + data: { name: 'prop$.events' }, + }, + { + messageId: 'missingPropType', + data: { name: 'prop$.events.map' }, + }, + ], } )), }); diff --git a/tests/util/isFirstLetterCapitalized.js b/tests/util/isFirstLetterCapitalized.js index 85bdffd1bc..96eaf510c3 100644 --- a/tests/util/isFirstLetterCapitalized.js +++ b/tests/util/isFirstLetterCapitalized.js @@ -15,11 +15,15 @@ describe('isFirstLetterCapitalized', () => { assert.equal(isFirstLetterCapitalized('isCapitalized'), false); assert.equal(isFirstLetterCapitalized('lowercase'), false); assert.equal(isFirstLetterCapitalized('_startsWithUnderscore'), false); - assert.equal(isFirstLetterCapitalized('_StartsWithUnderscore'), false); + assert.equal(isFirstLetterCapitalized('__startsWithUnderscore'), false); }); - it('should return true for capitalized string', () => { + it('should return true for capitalized string, with or without leading underscores', () => { assert.equal(isFirstLetterCapitalized('IsCapitalized'), true); + assert.equal(isFirstLetterCapitalized('_IsCapitalized'), true); + assert.equal(isFirstLetterCapitalized('__IsCapitalized'), true); assert.equal(isFirstLetterCapitalized('UPPERCASE'), true); + assert.equal(isFirstLetterCapitalized('_UPPERCASE'), true); + assert.equal(isFirstLetterCapitalized('__UPPERCASE'), true); }); });