Skip to content

Commit c0a5bb1

Browse files
committed
fix: feedback
1 parent b76cace commit c0a5bb1

File tree

3 files changed

+42
-28
lines changed

3 files changed

+42
-28
lines changed

.changeset/evil-houses-hide.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,15 @@
44

55
Added the nursery rule [`useInlineScriptId`](https://biomejs.dev/linter/rules/use-inline-script-id/) to the Next.js domain.
66
This rule enforces `id` attribute on `next/script` components with inline content or `dangerouslySetInnerHTML`.
7+
8+
The following code is invalid:
9+
10+
```jsx
11+
import Script from 'next/script';
12+
13+
export default function Page() {
14+
return (
15+
<Script>{`console.log('Hello');`}</Script> // must have `id` attribute
16+
);
17+
}
18+
```

crates/biome_js_analyze/src/lint/nursery/use_inline_script_id.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ declare_lint_rule! {
2525
///
2626
/// ### Invalid
2727
///
28-
/// ```js,expect_diagnostic
28+
/// ```jsx,expect_diagnostic
2929
/// import Script from 'next/script'
3030
///
3131
/// export default function Page() {
@@ -35,7 +35,7 @@ declare_lint_rule! {
3535
/// }
3636
/// ```
3737
///
38-
/// ```js,expect_diagnostic
38+
/// ```jsx,expect_diagnostic
3939
/// import Script from 'next/script'
4040
///
4141
/// export default function Page() {
@@ -46,7 +46,7 @@ declare_lint_rule! {
4646
/// ```
4747
///
4848
/// ### Valid
49-
/// ```js
49+
/// ```jsx
5050
/// import Script from 'next/script'
5151
///
5252
/// export default function Page() {
@@ -56,7 +56,7 @@ declare_lint_rule! {
5656
/// }
5757
/// ```
5858
///
59-
/// ```js
59+
/// ```jsx
6060
/// import Script from 'next/script'
6161
///
6262
/// export default function Page() {
@@ -107,7 +107,6 @@ impl Rule for UseInlineScriptId {
107107
match argument {
108108
AnyJsExpression::JsObjectExpression(obj_expr) => {
109109
collect_property_names(&obj_expr, &mut attribute_names)?;
110-
continue;
111110
}
112111
AnyJsExpression::JsIdentifierExpression(ident_expr) => {
113112
let reference = ident_expr.name().ok()?;
@@ -121,25 +120,24 @@ impl Rule for UseInlineScriptId {
121120
if let AnyJsExpression::JsObjectExpression(obj_expr) = expression {
122121
collect_property_names(&obj_expr, &mut attribute_names)?;
123122
}
124-
continue;
125-
}
126-
_ => {
127-
continue;
128123
}
124+
_ => {}
129125
}
130126
}
131-
_ => continue,
127+
_ => {}
132128
}
133129
}
134130

135-
let has_children = !jsx_element.parent::<JsxElement>()?.children().is_empty();
136-
if has_children || attribute_names.contains("dangerouslySetInnerHTML") {
137-
if !attribute_names.contains("id") {
138-
return Some(jsx_element.syntax().text_range_with_trivia());
139-
}
131+
let has_children = jsx_element
132+
.parent::<JsxElement>()
133+
.is_some_and(|parent| !parent.children().is_empty());
134+
if (has_children || attribute_names.contains("dangerouslySetInnerHTML"))
135+
&& !attribute_names.contains("id")
136+
{
137+
return Some(jsx_element.syntax().text_range_with_trivia());
140138
}
141139

142-
return None;
140+
None
143141
}
144142

145143
fn diagnostic(ctx: &RuleContext<Self>, _state: &Self::State) -> Option<RuleDiagnostic> {
@@ -165,9 +163,15 @@ fn collect_property_names(
165163
) -> Option<()> {
166164
for member in obj_expr.members() {
167165
let member = member.ok()?;
168-
let property_member = member.as_js_property_object_member()?;
169-
let name = property_member.name().ok()?.name()?;
170-
set.insert(name.to_string());
166+
if let Some(property_member) = member.as_js_property_object_member()
167+
&& let Some(name) = property_member.name().ok().and_then(|n| n.name())
168+
{
169+
set.insert(name.to_string());
170+
} else if let Some(shorthand) = member.as_js_shorthand_property_object_member()
171+
&& let Some(name) = shorthand.name().ok().and_then(|n| n.name().ok())
172+
{
173+
set.insert(name.to_string());
174+
}
171175
}
172176
Some(())
173177
}

crates/biome_js_analyze/tests/specs/nursery/useInlineScriptId/invalid-02.jsx.snap

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,24 @@ import Script from 'next/script'
99
1010
export default function Page() {
1111
return (
12-
<>
13-
<Script dangerouslySetInnerHTML={{ __html: `console.log('Hello world!');` }}></Script>
14-
</>
12+
<Script dangerouslySetInnerHTML={{ __html: `console.log('Hello world!');` }} />
1513
)
1614
}
1715
1816
```
1917

2018
# Diagnostics
2119
```
22-
invalid-02.jsx:7:7 lint/nursery/useInlineScriptId ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
20+
invalid-02.jsx:6:5 lint/nursery/useInlineScriptId ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2321
2422
! next/script components with inline content or `dangerouslySetInnerHTML` must specify id attribute.
2523
24+
4 │ export default function Page() {
2625
5return (
27-
6 │ <>
28-
> 7 │ <Script dangerouslySetInnerHTML={{ __html: `console.log('Hello world!');` }}></Script>
29-
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30-
8 │ </>
31-
9 │ )
26+
> 6<Script dangerouslySetInnerHTML={{ __html: `console.log('Hello world!');` }} />
27+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
28+
7 │ )
29+
8}
3230
3331
i See the Next.js docs for more details.
3432

0 commit comments

Comments
 (0)