refactor(linter): remove Regex and change error position (#2188)

This commit is contained in:
Wenzhe Wang 2024-01-28 11:48:23 +08:00 committed by GitHub
parent f32228e0b7
commit 1de3518046
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 97 additions and 81 deletions

View file

@ -423,6 +423,17 @@ impl<'a> GetSpan for JSXAttributeName<'a> {
} }
} }
impl<'a> GetSpan for JSXAttributeValue<'a> {
fn span(&self) -> Span {
match &self {
JSXAttributeValue::StringLiteral(literal) => literal.span,
JSXAttributeValue::ExpressionContainer(container) => container.span,
JSXAttributeValue::Fragment(fragment) => fragment.span,
JSXAttributeValue::Element(element) => element.span,
}
}
}
impl<'a> GetSpan for JSXMemberExpressionObject<'a> { impl<'a> GetSpan for JSXMemberExpressionObject<'a> {
fn span(&self) -> Span { fn span(&self) -> Span {
match &self { match &self {

View file

@ -1,4 +1,3 @@
use lazy_static::lazy_static;
use oxc_ast::{ use oxc_ast::{
ast::{ ast::{
Expression, JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXElementName, Expression, JSXAttributeItem, JSXAttributeName, JSXAttributeValue, JSXElementName,
@ -11,8 +10,7 @@ use oxc_diagnostics::{
thiserror::Error, thiserror::Error,
}; };
use oxc_macros::declare_oxc_lint; use oxc_macros::declare_oxc_lint;
use oxc_span::{Atom, Span}; use oxc_span::{Atom, GetSpan, Span};
use regex::Regex;
use std::ops::Deref; use std::ops::Deref;
use crate::{context::LintContext, rule::Rule, AstNode}; use crate::{context::LintContext, rule::Rule, AstNode};
@ -21,11 +19,15 @@ use crate::{context::LintContext, rule::Rule, AstNode};
enum JsxNoTargetBlankDiagnostic { enum JsxNoTargetBlankDiagnostic {
#[error("eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations")] #[error("eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations")]
#[diagnostic(severity(warning), help("add rel=`noreferrer` to the element"))] #[diagnostic(severity(warning), help("add rel=`noreferrer` to the element"))]
NoTargetBlankWithoutNoreferrer(#[label] Span), TargetBlankWithoutNoreferrer(#[label] Span),
#[error("eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` or rel=`noopener` (the former implies the latter and is preferred due to wider support) is a security risk: see https://mathiasbynens.github.io/rel-noopener/#recommendations")] #[error("eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` or rel=`noopener` (the former implies the latter and is preferred due to wider support) is a security risk: see https://mathiasbynens.github.io/rel-noopener/#recommendations")]
#[diagnostic(severity(warning), help("add rel=`noreferrer` or rel=`noopener` to the element"))] #[diagnostic(severity(warning), help("add rel=`noreferrer` or rel=`noopener` to the element"))]
NoTargetBlankWithoutNoopener(#[label] Span), TargetBlankWithoutNoopener(#[label] Span),
#[error("eslint-plugin-react(jsx-no-target-blank): all spread attributes are treated as if they contain an unsafe combination of props, unless specifically overridden by props after the last spread attribute prop.")]
#[diagnostic(severity(warning), help("add rel=`noreferrer` to the element"))]
ExplicitPropsInSpreadAttributes(#[label] Span),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -58,9 +60,9 @@ impl Default for JsxNoTargetBlank {
impl JsxNoTargetBlank { impl JsxNoTargetBlank {
fn diagnostic(&self, span: Span, ctx: &LintContext) { fn diagnostic(&self, span: Span, ctx: &LintContext) {
if self.allow_referrer { if self.allow_referrer {
ctx.diagnostic(JsxNoTargetBlankDiagnostic::NoTargetBlankWithoutNoopener(span)); ctx.diagnostic(JsxNoTargetBlankDiagnostic::TargetBlankWithoutNoopener(span));
} else { } else {
ctx.diagnostic(JsxNoTargetBlankDiagnostic::NoTargetBlankWithoutNoreferrer(span)); ctx.diagnostic(JsxNoTargetBlankDiagnostic::TargetBlankWithoutNoreferrer(span));
} }
} }
} }
@ -113,6 +115,8 @@ impl Rule for JsxNoTargetBlank {
let mut is_href_valid = true; let mut is_href_valid = true;
let mut has_href_value = false; let mut has_href_value = false;
let mut is_warn_on_spread_attributes = false; let mut is_warn_on_spread_attributes = false;
let mut target_span = None;
let mut spread_span = Span::default();
jsx_ele.attributes.iter().for_each(|attribute| match attribute { jsx_ele.attributes.iter().for_each(|attribute| match attribute {
JSXAttributeItem::Attribute(attribute) => { JSXAttributeItem::Attribute(attribute) => {
@ -120,6 +124,7 @@ impl Rule for JsxNoTargetBlank {
if identifier.name.as_str() == "target" { if identifier.name.as_str() == "target" {
if let Some(val) = attribute.deref().value.as_ref() { if let Some(val) = attribute.deref().value.as_ref() {
target_blank_tuple = check_target(val); target_blank_tuple = check_target(val);
target_span = attribute.value.as_ref().map(GetSpan::span);
} }
} else if identifier.name.as_str() == "href" } else if identifier.name.as_str() == "href"
|| identifier.name.as_str() == "to" || identifier.name.as_str() == "to"
@ -139,6 +144,7 @@ impl Rule for JsxNoTargetBlank {
JSXAttributeItem::SpreadAttribute(_) => { JSXAttributeItem::SpreadAttribute(_) => {
if self.warn_on_spread_attributes { if self.warn_on_spread_attributes {
is_warn_on_spread_attributes = true; is_warn_on_spread_attributes = true;
spread_span = attribute.span();
target_blank_tuple = (false, "", false, false); target_blank_tuple = (false, "", false, false);
rel_valid_tuple = (false, "", false, false); rel_valid_tuple = (false, "", false, false);
is_href_valid = false; is_href_valid = false;
@ -151,22 +157,25 @@ impl Rule for JsxNoTargetBlank {
if (has_href_value && is_href_valid) || rel_valid_tuple.0 { if (has_href_value && is_href_valid) || rel_valid_tuple.0 {
return; return;
} }
self.diagnostic(jsx_ele.span, ctx); ctx.diagnostic(JsxNoTargetBlankDiagnostic::ExplicitPropsInSpreadAttributes(
spread_span,
));
return; return;
} }
let span = target_span.unwrap_or(jsx_ele.span);
if !is_href_valid { if !is_href_valid {
if !target_blank_tuple.1.is_empty() && target_blank_tuple.1 == rel_valid_tuple.1 { if !target_blank_tuple.1.is_empty() && target_blank_tuple.1 == rel_valid_tuple.1 {
if (target_blank_tuple.2 && !rel_valid_tuple.2) if (target_blank_tuple.2 && !rel_valid_tuple.2)
|| (target_blank_tuple.3 && !rel_valid_tuple.3) || (target_blank_tuple.3 && !rel_valid_tuple.3)
{ {
self.diagnostic(jsx_ele.span, ctx); self.diagnostic(span, ctx);
} }
return; return;
} }
if target_blank_tuple.0 && !rel_valid_tuple.0 { if target_blank_tuple.0 && !rel_valid_tuple.0 {
self.diagnostic(jsx_ele.span, ctx); self.diagnostic(span, ctx);
} }
} }
} }
@ -204,11 +213,7 @@ impl Rule for JsxNoTargetBlank {
} }
fn check_is_external_link(link: &Atom) -> bool { fn check_is_external_link(link: &Atom) -> bool {
// TODO It may hurt performance. replace Regex with something else more efficient link.as_str().contains("//")
lazy_static! {
static ref CTL_PAT: Regex = Regex::new(r"(?:\w+:|\/\/)",).unwrap();
}
CTL_PAT.is_match(link.as_str())
} }
fn match_href_expression( fn match_href_expression(

View file

@ -6,7 +6,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href="https://example.com/1"></a> 1 │ <a target="_blank" href="https://example.com/1"></a>
· ──────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -14,7 +14,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" rel="" href="https://example.com/2"></a> 1 │ <a target="_blank" rel="" href="https://example.com/2"></a>
· ─────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -22,7 +22,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" rel={0} href="https://example.com/3"></a> 1 │ <a target="_blank" rel={0} href="https://example.com/3"></a>
· ──────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -30,7 +30,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" rel={1} href="https://example.com/3"></a> 1 │ <a target="_blank" rel={1} href="https://example.com/3"></a>
· ──────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -38,7 +38,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" rel={false} href="https://example.com/4"></a> 1 │ <a target="_blank" rel={false} href="https://example.com/4"></a>
· ──────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -46,7 +46,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" rel={null} href="https://example.com/5"></a> 1 │ <a target="_blank" rel={null} href="https://example.com/5"></a>
· ─────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -54,7 +54,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" rel="noopenernoreferrer" href="https://example.com/6"></a> 1 │ <a target="_blank" rel="noopenernoreferrer" href="https://example.com/6"></a>
· ───────────────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -62,7 +62,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" rel="no referrer" href="https://example.com/7"></a> 1 │ <a target="_blank" rel="no referrer" href="https://example.com/7"></a>
· ────────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -70,7 +70,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_BLANK" href="https://example.com/8"></a> 1 │ <a target="_BLANK" href="https://example.com/8"></a>
· ──────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -78,7 +78,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href="//example.com/9"></a> 1 │ <a target="_blank" href="//example.com/9"></a>
· ────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -86,7 +86,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href="//example.com/10" rel={true}></a> 1 │ <a target="_blank" href="//example.com/10" rel={true}></a>
· ────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -94,7 +94,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href="//example.com/11" rel={3}></a> 1 │ <a target="_blank" href="//example.com/11" rel={3}></a>
· ─────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -102,7 +102,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href="//example.com/12" rel={null}></a> 1 │ <a target="_blank" href="//example.com/12" rel={null}></a>
· ────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -110,7 +110,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href="//example.com/13" rel={getRel()}></a> 1 │ <a target="_blank" href="//example.com/13" rel={getRel()}></a>
· ────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -118,7 +118,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href="//example.com/14" rel={"noopenernoreferrer"}></a> 1 │ <a target="_blank" href="//example.com/14" rel={"noopenernoreferrer"}></a>
· ────────────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -126,7 +126,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target={"_blank"} href={"//example.com/15"} rel={"noopenernoreferrer"}></a> 1 │ <a target={"_blank"} href={"//example.com/15"} rel={"noopenernoreferrer"}></a>
· ────────────────────────────────────────────────────────────────────────── · ──────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -134,7 +134,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target={"_blank"} href={"//example.com/16"} rel={"noopenernoreferrernoreferrernoreferrernoreferrernoreferrer"}></a> 1 │ <a target={"_blank"} href={"//example.com/16"} rel={"noopenernoreferrernoreferrernoreferrernoreferrernoreferrer"}></a>
· ────────────────────────────────────────────────────────────────────────────────────────────────────────────────── · ──────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -142,7 +142,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href="//example.com/17" rel></a> 1 │ <a target="_blank" href="//example.com/17" rel></a>
· ─────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -150,7 +150,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href={ dynamicLink }></a> 1 │ <a target="_blank" href={ dynamicLink }></a>
· ──────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -158,7 +158,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target={'_blank'} href="//example.com/18"></a> 1 │ <a target={'_blank'} href="//example.com/18"></a>
· ───────────────────────────────────────────── · ──────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -166,7 +166,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target={"_blank"} href="//example.com/19"></a> 1 │ <a target={"_blank"} href="//example.com/19"></a>
· ───────────────────────────────────────────── · ──────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -174,7 +174,7 @@ expression: jsx_no_target_blank
│ risk: see https://mathiasbynens.github.io/rel-noopener/#recommendations │ risk: see https://mathiasbynens.github.io/rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href="https://example.com/20" target="_blank" rel></a> 1 │ <a href="https://example.com/20" target="_blank" rel></a>
· ───────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` or rel=`noopener` to the element help: add rel=`noreferrer` or rel=`noopener` to the element
@ -182,7 +182,7 @@ expression: jsx_no_target_blank
│ risk: see https://mathiasbynens.github.io/rel-noopener/#recommendations │ risk: see https://mathiasbynens.github.io/rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href="https://example.com/20" target="_blank"></a> 1 │ <a href="https://example.com/20" target="_blank"></a>
· ───────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` or rel=`noopener` to the element help: add rel=`noreferrer` or rel=`noopener` to the element
@ -190,47 +190,47 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href={ dynamicLink }></a> 1 │ <a target="_blank" href={ dynamicLink }></a>
· ──────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
⚠ eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/ ⚠ eslint-plugin-react(jsx-no-target-blank): all spread attributes are treated as if they contain an unsafe combination of props, unless specifically overridden by props after the last spread
rel-noopener/#recommendations attribute prop.
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a {...someObject}></a> 1 │ <a {...someObject}></a>
· ─────────────────── · ───────────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
⚠ eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/ ⚠ eslint-plugin-react(jsx-no-target-blank): all spread attributes are treated as if they contain an unsafe combination of props, unless specifically overridden by props after the last spread
rel-noopener/#recommendations attribute prop.
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a {...someObject} target="_blank"></a> 1 │ <a {...someObject} target="_blank"></a>
· ─────────────────────────────────── · ───────────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
⚠ eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/ ⚠ eslint-plugin-react(jsx-no-target-blank): all spread attributes are treated as if they contain an unsafe combination of props, unless specifically overridden by props after the last spread
rel-noopener/#recommendations attribute prop.
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href="foobar" {...someObject} target="_blank"></a> 1 │ <a href="foobar" {...someObject} target="_blank"></a>
· ───────────────────────────────────────────────── · ───────────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
⚠ eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/ ⚠ eslint-plugin-react(jsx-no-target-blank): all spread attributes are treated as if they contain an unsafe combination of props, unless specifically overridden by props after the last spread
rel-noopener/#recommendations attribute prop.
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href="foobar" target="_blank" rel="noreferrer" {...someObject}></a> 1 │ <a href="foobar" target="_blank" rel="noreferrer" {...someObject}></a>
· ────────────────────────────────────────────────────────────────── · ───────────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
⚠ eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/ ⚠ eslint-plugin-react(jsx-no-target-blank): all spread attributes are treated as if they contain an unsafe combination of props, unless specifically overridden by props after the last spread
rel-noopener/#recommendations attribute prop.
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href="foobar" target="_blank" {...someObject}></a> 1 │ <a href="foobar" target="_blank" {...someObject}></a>
· ───────────────────────────────────────────────── · ───────────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -238,7 +238,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <Link target="_blank" href={ dynamicLink }></Link> 1 │ <Link target="_blank" href={ dynamicLink }></Link>
· ─────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -246,23 +246,23 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <Link target="_blank" to={ dynamicLink }></Link> 1 │ <Link target="_blank" to={ dynamicLink }></Link>
· ───────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
⚠ eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/ ⚠ eslint-plugin-react(jsx-no-target-blank): all spread attributes are treated as if they contain an unsafe combination of props, unless specifically overridden by props after the last spread
rel-noopener/#recommendations attribute prop.
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href="some-link" {...otherProps} target="some-non-blank-target"></a> 1 │ <a href="some-link" {...otherProps} target="some-non-blank-target"></a>
· ─────────────────────────────────────────────────────────────────── · ───────────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
⚠ eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/ ⚠ eslint-plugin-react(jsx-no-target-blank): all spread attributes are treated as if they contain an unsafe combination of props, unless specifically overridden by props after the last spread
rel-noopener/#recommendations attribute prop.
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href="some-link" target="some-non-blank-target" {...otherProps}></a> 1 │ <a href="some-link" target="some-non-blank-target" {...otherProps}></a>
· ─────────────────────────────────────────────────────────────────── · ───────────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -270,7 +270,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href="//example.com" rel></a> 1 │ <a target="_blank" href="//example.com" rel></a>
· ──────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -278,7 +278,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href="//example.com" rel></a> 1 │ <a target="_blank" href="//example.com" rel></a>
· ──────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -286,7 +286,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a target="_blank" href="//example.com" rel></a> 1 │ <a target="_blank" href="//example.com" rel></a>
· ──────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -294,7 +294,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <form method="POST" action="https://example.com" target="_blank"></form> 1 │ <form method="POST" action="https://example.com" target="_blank"></form>
· ───────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -302,7 +302,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <form method="POST" action="https://example.com" rel="" target="_blank"></form> 1 │ <form method="POST" action="https://example.com" rel="" target="_blank"></form>
· ──────────────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -310,7 +310,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <form method="POST" action="https://example.com" rel="noopenernoreferrer" target="_blank"></form> 1 │ <form method="POST" action="https://example.com" rel="noopenernoreferrer" target="_blank"></form>
· ────────────────────────────────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -318,7 +318,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <form method="POST" action="https://example.com" rel="noopenernoreferrer" target="_blank"></form> 1 │ <form method="POST" action="https://example.com" rel="noopenernoreferrer" target="_blank"></form>
· ────────────────────────────────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -326,7 +326,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href={href} target="_blank" rel={isExternal ? "undefined" : "undefined"} /> 1 │ <a href={href} target="_blank" rel={isExternal ? "undefined" : "undefined"} />
· ────────────────────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -334,7 +334,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href={href} target="_blank" rel={isExternal ? "noopener" : undefined} /> 1 │ <a href={href} target="_blank" rel={isExternal ? "noopener" : undefined} />
· ─────────────────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -342,7 +342,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href={href} target="_blank" rel={isExternal ? "undefined" : "noopener"} /> 1 │ <a href={href} target="_blank" rel={isExternal ? "undefined" : "noopener"} />
· ───────────────────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -350,7 +350,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href={href} target={isExternal ? "_blank" : undefined} rel={isExternal ? undefined : "noopener noreferrer"} /> 1 │ <a href={href} target={isExternal ? "_blank" : undefined} rel={isExternal ? undefined : "noopener noreferrer"} />
· ───────────────────────────────────────────────────────────────────────────────────────────────────────────────── · ───────────────────────────────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -358,7 +358,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href={href} target="_blank" rel={isExternal ? 3 : "noopener noreferrer"} /> 1 │ <a href={href} target="_blank" rel={isExternal ? 3 : "noopener noreferrer"} />
· ────────────────────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -366,7 +366,7 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href={href} target="_blank" rel={isExternal ? "noopener noreferrer" : "3"} /> 1 │ <a href={href} target="_blank" rel={isExternal ? "noopener noreferrer" : "3"} />
· ──────────────────────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
@ -374,7 +374,7 @@ expression: jsx_no_target_blank
│ risk: see https://mathiasbynens.github.io/rel-noopener/#recommendations │ risk: see https://mathiasbynens.github.io/rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <a href={href} target="_blank" rel={isExternal ? "noopener" : "2"} /> 1 │ <a href={href} target="_blank" rel={isExternal ? "noopener" : "2"} />
· ───────────────────────────────────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` or rel=`noopener` to the element help: add rel=`noreferrer` or rel=`noopener` to the element
@ -382,7 +382,7 @@ expression: jsx_no_target_blank
│ risk: see https://mathiasbynens.github.io/rel-noopener/#recommendations │ risk: see https://mathiasbynens.github.io/rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <form action={action} target="_blank" /> 1 │ <form action={action} target="_blank" />
· ──────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` or rel=`noopener` to the element help: add rel=`noreferrer` or rel=`noopener` to the element
@ -390,15 +390,15 @@ expression: jsx_no_target_blank
│ rel-noopener/#recommendations │ rel-noopener/#recommendations
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <form action={action} target="_blank" /> 1 │ <form action={action} target="_blank" />
· ──────────────────────────────────────── · ────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element
⚠ eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/ ⚠ eslint-plugin-react(jsx-no-target-blank): all spread attributes are treated as if they contain an unsafe combination of props, unless specifically overridden by props after the last spread
rel-noopener/#recommendations attribute prop.
╭─[jsx_no_target_blank.tsx:1:1] ╭─[jsx_no_target_blank.tsx:1:1]
1 │ <form action={action} {...spread} /> 1 │ <form action={action} {...spread} />
· ──────────────────────────────────── · ───────────
╰──── ╰────
help: add rel=`noreferrer` to the element help: add rel=`noreferrer` to the element