diff --git a/CHANGELOG.md b/CHANGELOG.md
index 90bc4e80e5..05bc33652e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [`jsx-key`]: avoid a crash on a non-array node.body from [#3320][] ([#3328][] @ljharb)
* [`display-name`]: fix false positive for assignment of function returning null ([#3331][] @apbarrero)
* [`display-name`]: fix identifying `_` as a capital letter ([#3335][] @apbarrero)
+* [`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)
@@ -25,6 +26,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
[#3339]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3339
[#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..e957fb509a 100644
--- a/lib/rules/jsx-no-target-blank.js
+++ b/lib/rules/jsx-no-target-blank.js
@@ -74,6 +74,29 @@ function getStringFromValue(value) {
if (value.expression.type === 'TemplateLiteral') {
return value.expression.quasis[0].value.cooked;
}
+ const expr = value.expression;
+ if (expr.type === 'ConditionalExpression') {
+ if (
+ typeof expr.consequent.value === 'string'
+ && (
+ (expr.consequent.value && expr.consequent.value.toLowerCase() === 'noreferrer')
+ || (expr.consequent.value && expr.consequent.value.toLowerCase() === 'noopener noreferrer')
+ || (expr.consequent.value && expr.consequent.value.toLowerCase() === 'noreferrer noopener')
+ )
+ ) {
+ return expr.consequent.value;
+ }
+ if (
+ typeof expr.alternate.value === 'string'
+ && (
+ (expr.alternate.value && expr.alternate.value.toLowerCase() === 'noreferrer')
+ || (expr.alternate.value && expr.alternate.value.toLowerCase() === 'noopener noreferrer')
+ || (expr.consequent.value && expr.consequent.value.toLowerCase() === 'noreferrer noopener')
+ )
+ ) {
+ return expr.alternate.value;
+ }
+ }
return value.expression && value.expression.value;
}
}
diff --git a/tests/lib/rules/jsx-no-target-blank.js b/tests/lib/rules/jsx-no-target-blank.js
index 27a63cb09d..aad51048d4 100644
--- a/tests/lib/rules/jsx-no-target-blank.js
+++ b/tests/lib/rules/jsx-no-target-blank.js
@@ -141,6 +141,21 @@ ruleTester.run('jsx-no-target-blank', rule, {
{
code: '',
},
+ {
+ code: '',
+ },
+ {
+ code: '',
+ },
+ {
+ code: '',
+ },
+ {
+ code: '',
+ },
+ {
+ code: '',
+ },
]),
invalid: parsers.all([
{
@@ -352,5 +367,17 @@ ruleTester.run('jsx-no-target-blank', rule, {
options: [{ forms: true, links: false }],
errors: defaultErrors,
},
+ {
+ code: '',
+ errors: defaultErrors,
+ },
+ {
+ code: '',
+ errors: defaultErrors,
+ },
+ {
+ code: '',
+ errors: defaultErrors,
+ },
]),
});