Skip to content

Commit

Permalink
refactor(useFilenamingConvention): support dynamic route filenames
Browse files Browse the repository at this point in the history
  • Loading branch information
Conaclos committed Jul 18, 2024
1 parent 3aeedd4 commit 1f28423
Show file tree
Hide file tree
Showing 25 changed files with 213 additions and 63 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,15 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b

Contributed by @Conaclos

- [useFilenamingConvention](https://biomejs.dev/linter/rules/use-filenaming-convention) now supports Next/Nuxt/Astro dynamic routes ([#3465](https://github.com/biomejs/biome/issues/3465)).

[Next](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#catch-all-segments), [Nuxt](https://nuxt.com/docs/guide/directory-structure/server#catch-all-route), and [Astro](https://docs.astro.build/en/guides/routing/#rest-parameters) support dynamic routes such as `[...slug].js` and `[[...slug]].js`.

Biome now recognizes this syntax.
`slug` must contain only alphanumeric characters.

Contributed by @Conaclos

#### Bug fixes

- Don't request alt text for elements hidden from assistive technologies ([#3316](https://github.com/biomejs/biome/issues/3316)). Contributed by @robintown
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ declare_lint_rule! {
/// The convention of prefixing a filename with a plus sign is used by
/// [Sveltekit](https://kit.svelte.dev/docs/routing#page) and [Vike](https://vike.dev/route).
///
/// Also, the rule supports dynamic route syntaxes of [Next](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#catch-all-segments), [Nuxt](https://nuxt.com/docs/guide/directory-structure/server#catch-all-route), and [Astro](https://docs.astro.build/en/guides/routing/#rest-parameters).
/// For example `[...slug].js` and `[[...slug]].js` are valid filenames.
///
/// By default, the rule ensures that the filename is either in [`camelCase`], [`kebab-case`], [`snake_case`],
/// or equal to the name of one export in the file.
///
Expand Down Expand Up @@ -128,24 +131,43 @@ impl Rule for UseFilenamingConvention {
}
let allowed_cases = options.filename_cases.cases();
let mut splitted = file_name.split('.');
let name = splitted.next()?;
let name = if name.is_empty() {
let first = splitted.next()?;
let name = if first.is_empty() {
// The filename starts with a dot
splitted.next()?
} else if let Some(stripped_name) = name.strip_prefix('+') {
} else if let Some(stripped_name) = first.strip_prefix('+') {
// Support [Sveltekit](https://kit.svelte.dev/docs/routing#page) and
// [Vike](https://vike.dev/route) routing conventions
// where page name starts with `+`.
stripped_name
} else if first == "[" || first == "[[" {
// Support [Next](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#catch-all-segments),
// [Nuxt](https://nuxt.com/docs/guide/directory-structure/server#catch-all-route),
// and [Astro](https://docs.astro.build/en/guides/routing/#rest-parameters)
// dynamic routes. Some examples:
//
// - `[...slug].js`
// - `[[...slug]].js`
let ending = if first == "[" { "]" } else { "]]" };
return if splitted.next() == Some("")
&& splitted.next() == Some("")
&& splitted.next().is_some_and(|last| {
last.ends_with(ending)
&& last[..last.len() - 2].chars().all(|c| c.is_alphanumeric())
}) {
// Check extension case
splitted
.any(|extension| Case::identify(extension, true) != Case::Lower)
.then_some(FileNamingConventionState::Extension)
} else {
Some(FileNamingConventionState::Filename)
};
} else {
name
first
};
// Check extension case
for extension in splitted {
let case = Case::identify(extension, true);
if case != Case::Lower {
return Some(FileNamingConventionState::Extension);
}
if splitted.any(|extension| Case::identify(extension, true) != Case::Lower) {
return Some(FileNamingConventionState::Extension);
}
// Check filename case
if !allowed_cases.is_empty() {
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
source: crates/biome_js_analyze/tests/spec_tests.rs
expression: "[...slug2].js"
---
# Input
```jsx

```
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
source: crates/biome_js_analyze/tests/spec_tests.rs
assertion_line: 84
expression: "[[...slug3]].js"
---
# Input
```jsx

```
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
source: crates/biome_json_parser/tests/spec_test.rs
expression: snapshot
---

## Input

```json
Expand Down Expand Up @@ -48,7 +47,7 @@ JsonRoot {
## Diagnostics

```
number_0.3e+.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
number_0.3e_plus.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× Missing exponent
Expand All @@ -61,5 +60,3 @@ number_0.3e+.json:1:2 parse ━━━━━━━━━━━━━━━━━
│ ^
```


Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
source: crates/biome_json_parser/tests/spec_test.rs
expression: snapshot
---

## Input

```json
Expand Down Expand Up @@ -48,7 +47,7 @@ JsonRoot {
## Diagnostics

```
number_0_capital_E+.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
number_0_capital_E_plus.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× Missing exponent
Expand All @@ -61,5 +60,3 @@ number_0_capital_E+.json:1:2 parse ━━━━━━━━━━━━━━━
│ ^
```


Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
source: crates/biome_json_parser/tests/spec_test.rs
expression: snapshot
---

## Input

```json
Expand Down Expand Up @@ -48,7 +47,7 @@ JsonRoot {
## Diagnostics

```
number_0e+.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
number_0e+_missing_digit.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× Missing exponent
Expand All @@ -61,5 +60,3 @@ number_0e+.json:1:2 parse ━━━━━━━━━━━━━━━━━━
│ ^
```


Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
source: crates/biome_json_parser/tests/spec_test.rs
expression: snapshot
---

## Input

```json
Expand Down Expand Up @@ -48,7 +47,7 @@ JsonRoot {
## Diagnostics

```
number_1.0e-.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
number_1.0e-_missing_digit.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× Missing exponent
Expand All @@ -61,5 +60,3 @@ number_1.0e-.json:1:2 parse ━━━━━━━━━━━━━━━━━
│ ^
```


Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
source: crates/biome_json_parser/tests/spec_test.rs
expression: snapshot
---
## Input

```json
[1.0e-]
```


## AST

```
JsonRoot {
bom_token: missing (optional),
value: JsonArrayValue {
l_brack_token: L_BRACK@0..1 "[" [] [],
elements: JsonArrayElementList [
JsonBogusValue {
items: [
ERROR_TOKEN@1..6 "1.0e-" [] [],
],
},
],
r_brack_token: R_BRACK@6..7 "]" [] [],
},
eof_token: EOF@7..7 "" [] [],
}
```

## CST

```
0: [email protected]
0: (empty)
1: [email protected]
0: [email protected] "[" [] []
1: [email protected]
0: [email protected]
0: [email protected] "1.0e-" [] []
2: [email protected] "]" [] []
2: [email protected] "" [] []
```

## Diagnostics

```
number_1.0e_minus.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× Missing exponent
> 1 │ [1.0e-]
│ ^^^^^
i Expected a digit as the exponent
> 1 │ [1.0e-]
│ ^
```
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ JsonRoot {
## Diagnostics

```
number_-NaN.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
number_neg_NaN.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× Minus must be followed by a digit
> 1 │ [-NaN]
│ ^
number_-NaN.json:1:3 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
number_neg_NaN.json:1:3 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× expected `,` but instead found `NaN`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
source: crates/biome_json_parser/tests/spec_test.rs
expression: snapshot
---

## Input

```json
Expand Down Expand Up @@ -55,14 +54,14 @@ JsonRoot {
## Diagnostics

```
number_+1.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
number_plus_1.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× unexpected character `+`
> 1 │ [+1]
│ ^
number_+1.json:1:3 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
number_plus_1.json:1:3 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× expected `,` but instead found `1`
Expand All @@ -72,5 +71,3 @@ number_+1.json:1:3 parse ━━━━━━━━━━━━━━━━━━
i Remove 1
```


Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
source: crates/biome_json_parser/tests/spec_test.rs
expression: snapshot
---
## Input

```json
[+Inf]
```


## AST

```
JsonRoot {
bom_token: missing (optional),
value: JsonArrayValue {
l_brack_token: L_BRACK@0..1 "[" [] [],
elements: JsonArrayElementList [
JsonBogusValue {
items: [
ERROR_TOKEN@1..2 "+" [] [],
],
},
missing separator,
JsonBogusValue {
items: [
IDENT@2..5 "Inf" [] [],
],
},
],
r_brack_token: R_BRACK@5..6 "]" [] [],
},
eof_token: EOF@6..6 "" [] [],
}
```

## CST

```
0: [email protected]
0: (empty)
1: [email protected]
0: [email protected] "[" [] []
1: [email protected]
0: [email protected]
0: [email protected] "+" [] []
1: (empty)
2: [email protected]
0: [email protected] "Inf" [] []
2: [email protected] "]" [] []
2: [email protected] "" [] []
```

## Diagnostics

```
number_plus_Inf.json:1:2 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× unexpected character `+`
> 1 │ [+Inf]
│ ^
number_plus_Inf.json:1:3 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
× expected `,` but instead found `Inf`
> 1 │ [+Inf]
│ ^^^
i Remove Inf
```
Loading

0 comments on commit 1f28423

Please sign in to comment.