Skip to content

Commit

Permalink
fix(linter): noUselessFragments deal html escapes under fragements wrong
Browse files Browse the repository at this point in the history
  • Loading branch information
fireairforce committed Sep 27, 2024
1 parent 011a709 commit cc4cb88
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 2 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,17 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b

- [noUselessFragments](https://biomejs.dev/linter/rules/no-useless-fragments/) don't create invaild JSX code when Fragments children contains JSX Expression and in a LogicalExpression. Contributed by @fireairforce

- [noUselessFragments](https://biomejs.dev/linter/rules/no-useless-fragments/) Fragments containing HTML escapes (e.g.  ) inside expression escapes `{ ... }` should not be considered useless.
The following code is no longer reported:

```jsx
function Component() {
return (
<div key={index}>{line || <>&nbsp;</>}</div>
)
}
```

### Parser

#### Bug fixes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use biome_js_factory::make::{
use biome_js_syntax::{
AnyJsxChild, AnyJsxElementName, AnyJsxTag, JsLanguage, JsLogicalExpression,
JsParenthesizedExpression, JsSyntaxKind, JsxChildList, JsxElement, JsxExpressionAttributeValue,
JsxFragment, JsxTagExpression, JsxText, T,
JsxExpressionChild, JsxFragment, JsxTagExpression, JsxText, T,
};
use biome_rowan::{declare_node_union, AstNode, AstNodeList, BatchMutation, BatchMutationExt};

Expand Down Expand Up @@ -124,6 +124,7 @@ impl Rule for NoUselessFragments {
let model = ctx.model();
let mut in_jsx_attr_expr = false;
let mut in_js_logical_expr = false;
let mut in_jsx_expr = false;
match node {
NoUselessFragmentsQuery::JsxFragment(fragment) => {
let parents_where_fragments_must_be_preserved = node.syntax().parent().map_or(
Expand All @@ -139,6 +140,9 @@ impl Rule for NoUselessFragments {
if JsLogicalExpression::can_cast(parent.kind()) {
in_js_logical_expr = true;
}
if JsxExpressionChild::can_cast(parent.kind()) {
in_jsx_expr = true;
}
match JsParenthesizedExpression::try_cast(parent) {
Ok(parenthesized_expression) => {
parenthesized_expression.syntax().parent()
Expand Down Expand Up @@ -190,7 +194,17 @@ impl Rule for NoUselessFragments {
}
}
JsSyntaxKind::JSX_TEXT => {
if !child.syntax().text().to_string().trim().is_empty() {
let child_text =
child.syntax().text().to_string().trim().to_string();

if (in_jsx_expr || in_js_logical_expr)
&& contains_html_entity(&child_text)
{
children_where_fragments_must_preserved = true;
break;
}

if !child_text.is_empty() {
significant_children += 1;
if first_significant_child.is_none() {
first_significant_child = Some(child);
Expand Down Expand Up @@ -401,3 +415,7 @@ impl Rule for NoUselessFragments {
}))
}
}

fn contains_html_entity(s: &str) -> bool {
s.contains("&") && s.contains(";")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
function MyComponent() {
return (
<div key={index}>{line || <>&nbsp;</>}</div>
)
}

function MyComponent2() {
return (
<div key={index}>{<>&nbsp;</>}</div>
)
}

function MyComponent3() {
return (
<div key={index}>{value ?? <>&nbsp;</>}</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
source: crates/biome_js_analyze/tests/spec_tests.rs
expression: issue_4059.jsx
---
# Input
```jsx
function MyComponent() {
return (
<div key={index}>{line || <>&nbsp;</>}</div>
)
}

function MyComponent2() {
return (
<div key={index}>{<>&nbsp;</>}</div>
)
}

function MyComponent3() {
return (
<div key={index}>{value ?? <>&nbsp;</>}</div>
)
}
```

0 comments on commit cc4cb88

Please sign in to comment.