From b7f388b4128b689c4902ab0d659ba48f1c1d4f62 Mon Sep 17 00:00:00 2001 From: Vividha Date: Wed, 13 Jul 2022 02:30:26 +0000 Subject: [PATCH] [Fix] `jsx-no-target-blank`: False negative when rel attribute is assigned using ConditionalExpression --- CHANGELOG.md | 2 + lib/rules/jsx-no-target-blank.js | 22 +++++++---- tests/lib/rules/jsx-no-target-blank.js | 51 +++++++++++++++++++++++++- 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4491394d8a..77b987055c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange * [`display-name`], component detection: fix HOF returning null as Components ([#3347][] @jxm-math) * [`forbid-prop-types`]: Ignore objects that are not of type React.PropTypes ([#3326][] @TildaDares) * [`display-name`], component detection: fix false positive for HOF returning only nulls and literals ([#3305][] @golopot) +* [`jsx-no-target-blank`]: False negative when rel attribute is assigned using ConditionalExpression ([#3332][] @V2dha) ### Changed * [Refactor] [`jsx-indent-props`]: improved readability of the checkNodesIndent function ([#3315][] @caroline223) @@ -39,6 +40,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange [#3339]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3339 [#3338]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3338 [#3335]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3335 +[#3332]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3332 [#3331]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3331 [#3328]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3328 [#3327]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3327 diff --git a/lib/rules/jsx-no-target-blank.js b/lib/rules/jsx-no-target-blank.js index 1f6edc9e07..01dedf7207 100644 --- a/lib/rules/jsx-no-target-blank.js +++ b/lib/rules/jsx-no-target-blank.js @@ -74,7 +74,12 @@ function getStringFromValue(value) { if (value.expression.type === 'TemplateLiteral') { return value.expression.quasis[0].value.cooked; } - return value.expression && value.expression.value; + const expr = value.expression; + return expr && ( + expr.type === 'ConditionalExpression' + ? [expr.consequent.value, expr.alternate.value] + : expr.value + ); } } return null; @@ -88,12 +93,15 @@ function hasSecureRel(node, allowReferrer, warnOnSpreadAttributes, spreadAttribu const relAttribute = node.attributes[relIndex]; const value = getStringFromValue(relAttribute.value); - const tags = value && typeof value === 'string' && value.toLowerCase().split(' '); - const noreferrer = tags && tags.indexOf('noreferrer') >= 0; - if (noreferrer) { - return true; - } - return allowReferrer && tags && tags.indexOf('noopener') >= 0; + return [].concat(value).every((item) => { + const tags = typeof item === 'string' ? item.toLowerCase().split(' ') : false; + const noreferrer = tags && tags.indexOf('noreferrer') >= 0; + if (noreferrer) { + return true; + } + const noopener = tags && tags.indexOf('noopener') >= 0; + return allowReferrer && noopener; + }); } const messages = { diff --git a/tests/lib/rules/jsx-no-target-blank.js b/tests/lib/rules/jsx-no-target-blank.js index 27a63cb09d..2208e371dc 100644 --- a/tests/lib/rules/jsx-no-target-blank.js +++ b/tests/lib/rules/jsx-no-target-blank.js @@ -28,6 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); const defaultErrors = [{ messageId: 'noTargetBlankWithoutNoreferrer' }]; +const allowReferrerErrors = [{ messageId: 'noTargetBlankWithoutNoopener' }]; ruleTester.run('jsx-no-target-blank', rule, { valid: parsers.all([ @@ -141,6 +142,19 @@ ruleTester.run('jsx-no-target-blank', rule, { { code: '', }, + { + code: '', + }, + { + code: '', + }, + { + code: '', + }, + { + code: '', + options: [{ allowReferrer: true }], + }, ]), invalid: parsers.all([ { @@ -251,13 +265,13 @@ ruleTester.run('jsx-no-target-blank', rule, { code: '', output: '', options: [{ allowReferrer: true }], - errors: [{ messageId: 'noTargetBlankWithoutNoopener' }], + errors: allowReferrerErrors, }, { code: '', output: '', options: [{ allowReferrer: true }], - errors: [{ messageId: 'noTargetBlankWithoutNoopener' }], + errors: allowReferrerErrors, }, { code: '', @@ -352,5 +366,38 @@ ruleTester.run('jsx-no-target-blank', rule, { options: [{ forms: true, links: false }], errors: defaultErrors, }, + { + code: '', + errors: defaultErrors, + }, + { + code: '', + errors: defaultErrors, + }, + { + code: '', + errors: defaultErrors, + }, + { + code: '', + errors: defaultErrors, + }, + { + code: '', + errors: defaultErrors, + }, + { + code: '', + errors: defaultErrors, + }, + { + code: '', + errors: defaultErrors, + }, + { + code: '', + options: [{ allowReferrer: true }], + errors: allowReferrerErrors, + }, ]), });