Skip to content

Commit 0f0a658

Browse files
authored
feat(analyze): implement noSyncScripts (#8108)
1 parent f4433b3 commit 0f0a658

File tree

23 files changed

+511
-68
lines changed

23 files changed

+511
-68
lines changed

.changeset/icy-bags-sleep.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
"@biomejs/biome": patch
3+
---
4+
5+
Added the nursery rule [`noSyncScripts`](https://biomejs.dev/linter/rules/no-sync-scripts/). Prevent the usage of synchronous scripts.
6+
7+
**Invalid:**
8+
9+
```jsx
10+
<script src="https://third-party-script.js" />
11+
```
12+
13+
**Valid:**
14+
15+
```jsx
16+
<script src="https://third-party-script.js" async />
17+
<script src="https://third-party-script.js" defer />
18+
```

crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/biome_configuration/src/analyzer/linter/rules.rs

Lines changed: 85 additions & 64 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/biome_configuration/src/generated/domain_selector.rs

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/biome_diagnostics_categories/src/categories.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ define_categories! {
181181
"lint/nursery/noParametersOnlyUsedInRecursion": "https://biomejs.dev/linter/rules/no-parameters-only-used-in-recursion",
182182
"lint/nursery/noReactForwardRef": "https://biomejs.dev/linter/rules/no-react-forward-ref",
183183
"lint/nursery/noShadow": "https://biomejs.dev/linter/rules/no-shadow",
184+
"lint/nursery/noSyncScripts": "https://biomejs.dev/linter/rules/no-sync-scripts",
184185
"lint/nursery/noUnknownAttribute": "https://biomejs.dev/linter/rules/no-unknown-attribute",
185186
"lint/nursery/noUnnecessaryConditions": "https://biomejs.dev/linter/rules/no-unnecessary-conditions",
186187
"lint/nursery/noUnresolvedImports": "https://biomejs.dev/linter/rules/no-unresolved-imports",

crates/biome_html_analyze/src/lint/nursery.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
//! Generated file, do not edit by hand, see `xtask/codegen`
44
55
use biome_analyze::declare_lint_group;
6+
pub mod no_sync_scripts;
67
pub mod use_vue_valid_v_bind;
78
pub mod use_vue_valid_v_else;
89
pub mod use_vue_valid_v_else_if;
910
pub mod use_vue_valid_v_html;
1011
pub mod use_vue_valid_v_if;
1112
pub mod use_vue_valid_v_on;
12-
declare_lint_group! { pub Nursery { name : "nursery" , rules : [self :: use_vue_valid_v_bind :: UseVueValidVBind , self :: use_vue_valid_v_else :: UseVueValidVElse , self :: use_vue_valid_v_else_if :: UseVueValidVElseIf , self :: use_vue_valid_v_html :: UseVueValidVHtml , self :: use_vue_valid_v_if :: UseVueValidVIf , self :: use_vue_valid_v_on :: UseVueValidVOn ,] } }
13+
declare_lint_group! { pub Nursery { name : "nursery" , rules : [self :: no_sync_scripts :: NoSyncScripts , self :: use_vue_valid_v_bind :: UseVueValidVBind , self :: use_vue_valid_v_else :: UseVueValidVElse , self :: use_vue_valid_v_else_if :: UseVueValidVElseIf , self :: use_vue_valid_v_html :: UseVueValidVHtml , self :: use_vue_valid_v_if :: UseVueValidVIf , self :: use_vue_valid_v_on :: UseVueValidVOn ,] } }
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use biome_analyze::{
2+
Ast, Rule, RuleDiagnostic, RuleSource, context::RuleContext, declare_lint_rule,
3+
};
4+
use biome_console::markup;
5+
use biome_html_syntax::HtmlOpeningElement;
6+
use biome_rowan::AstNode;
7+
use biome_rule_options::no_sync_scripts::NoSyncScriptsOptions;
8+
9+
declare_lint_rule! {
10+
/// Prevent the usage of synchronous scripts.
11+
///
12+
/// A synchronous script can impact your webpage performance, read more on how to [Efficiently load third-party JavaScript](https://web.dev/articles/efficiently-load-third-party-javascript).
13+
///
14+
/// ## Examples
15+
///
16+
/// ### Invalid
17+
///
18+
/// ```html,expect_diagnostic
19+
/// <script src=""></script>
20+
/// ```
21+
///
22+
/// ### Valid
23+
///
24+
/// ```html
25+
/// <script src="" async></script>
26+
/// <script src="" defer></script>
27+
/// ```
28+
///
29+
pub NoSyncScripts {
30+
version: "next",
31+
name: "noSyncScripts",
32+
language: "html",
33+
recommended: false,
34+
sources: &[RuleSource::EslintNext("no-sync-scripts").same()],
35+
}
36+
}
37+
38+
impl Rule for NoSyncScripts {
39+
type Query = Ast<HtmlOpeningElement>;
40+
type State = ();
41+
type Signals = Option<Self::State>;
42+
type Options = NoSyncScriptsOptions;
43+
44+
fn run(ctx: &RuleContext<Self>) -> Option<Self::State> {
45+
let binding = ctx.query();
46+
47+
let name = binding.name().ok()?;
48+
let value_token = name.value_token().ok()?;
49+
if value_token.text_trimmed() != "script" {
50+
return None;
51+
}
52+
53+
let attributes = binding.attributes();
54+
if attributes.find_by_name("src").is_none()
55+
|| attributes.find_by_name("async").is_some()
56+
|| attributes.find_by_name("defer").is_some()
57+
{
58+
return None;
59+
}
60+
61+
Some(())
62+
}
63+
64+
fn diagnostic(ctx: &RuleContext<Self>, _state: &Self::State) -> Option<RuleDiagnostic> {
65+
let node = ctx.query();
66+
Some(
67+
RuleDiagnostic::new(
68+
rule_category!(),
69+
node.range(),
70+
markup! {
71+
"Unexpected synchronous script."
72+
},
73+
)
74+
.note(markup! {
75+
"Synchronous scripts can impact your webpage performance. Add the \"async\" or \"defer\" attribute."
76+
}),
77+
)
78+
}
79+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<script src=""></script>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
source: crates/biome_html_analyze/tests/spec_tests.rs
3+
expression: invalid.html
4+
---
5+
# Input
6+
```html
7+
<script src=""></script>
8+
9+
```
10+
11+
# Diagnostics
12+
```
13+
invalid.html:1:1 lint/nursery/noSyncScripts ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
14+
15+
i Unexpected synchronous script.
16+
17+
> 1 │ <script src=""></script>
18+
│ ^^^^^^^^^^^^^^^
19+
2 │
20+
21+
i Synchronous scripts can impact your webpage performance. Add the "async" or "defer" attribute.
22+
23+
24+
```
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/* should not generate diagnostics */
2+
<noscript></noscript>
3+
4+
<script></script>
5+
6+
<script src="" async></script>
7+
8+
<script src="" defer></script>

0 commit comments

Comments
 (0)