Skip to content

Commit 4759b47

Browse files
authored
Generalized no-goto-without-base into no-navigation-without-base (#900)
1 parent cc16c97 commit 4759b47

File tree

62 files changed

+865
-7
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+865
-7
lines changed

.changeset/cold-starfishes-doubt.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-svelte': minor
3+
---
4+
5+
feat: added the no-navigation-without-base rule

.changeset/olive-melons-explain.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-svelte': major
3+
---
4+
5+
chore: deprecated the no-goto-without-base rule

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ These rules relate to SvelteKit and its best Practices.
415415

416416
| Rule ID | Description | |
417417
|:--------|:------------|:---|
418-
| [svelte/no-goto-without-base](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-goto-without-base/) | disallow using goto() without the base path | |
418+
| [svelte/no-navigation-without-base](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-navigation-without-base/) | disallow using navigation (links, goto, pushState, replaceState) without the base path | |
419419

420420
## Experimental
421421

@@ -443,6 +443,7 @@ These rules relate to this plugin works:
443443
| Rule ID | Replaced by |
444444
|:--------|:------------|
445445
| [svelte/@typescript-eslint/no-unnecessary-condition](https://sveltejs.github.io/eslint-plugin-svelte/rules/@typescript-eslint/no-unnecessary-condition/) | This rule is no longer needed when using svelte-eslint-parser>=v0.19.0. |
446+
| [svelte/no-goto-without-base](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-goto-without-base/) | [svelte/no-navigation-without-base](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-navigation-without-base/) |
446447

447448
<!--RULES_TABLE_END-->
448449
<!--RULES_SECTION_END-->

docs/rules.md

+7-6
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ These rules extend the rules provided by ESLint itself, or other plugins to work
110110

111111
These rules relate to SvelteKit and its best Practices.
112112

113-
| Rule ID | Description | |
114-
| :------------------------------------------------------------- | :------------------------------------------ | :-- |
115-
| [svelte/no-goto-without-base](./rules/no-goto-without-base.md) | disallow using goto() without the base path | |
113+
| Rule ID | Description | |
114+
| :------------------------------------------------------------------------- | :------------------------------------------------------------------------------------- | :-- |
115+
| [svelte/no-navigation-without-base](./rules/no-navigation-without-base.md) | disallow using navigation (links, goto, pushState, replaceState) without the base path | |
116116

117117
## Experimental
118118

@@ -137,6 +137,7 @@ These rules relate to this plugin works:
137137
- :warning: We're going to remove deprecated rules in the next major release. Please migrate to successor/new rules.
138138
- :innocent: We don't fix bugs which are in deprecated rules since we don't have enough resources.
139139

140-
| Rule ID | Replaced by |
141-
| :----------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------- |
142-
| [svelte/@typescript-eslint/no-unnecessary-condition](./rules/@typescript-eslint/no-unnecessary-condition.md) | This rule is no longer needed when using svelte-eslint-parser>=v0.19.0. |
140+
| Rule ID | Replaced by |
141+
| :----------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------- |
142+
| [svelte/@typescript-eslint/no-unnecessary-condition](./rules/@typescript-eslint/no-unnecessary-condition.md) | This rule is no longer needed when using svelte-eslint-parser>=v0.19.0. |
143+
| [svelte/no-goto-without-base](./rules/no-goto-without-base.md) | [svelte/no-navigation-without-base](./rules/no-navigation-without-base.md) |

docs/rules/no-goto-without-base.md

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ since: 'v2.36.0-next.9'
1010

1111
> disallow using goto() without the base path
1212
13+
- :warning: This rule was **deprecated** and replaced by [svelte/no-navigation-without-base](no-navigation-without-base.md) rule.
14+
1315
## :book: Rule Details
1416

1517
This rule reports navigation using SvelteKit's `goto()` function without prefixing a relative URL with the base path. If a non-prefixed relative URL is used for navigation, the `goto` function navigates away from the base path, which is usually not what you wanted to do (for external URLs, `window.location = url` should be used instead).
+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
---
2+
pageClass: 'rule-details'
3+
sidebarDepth: 0
4+
title: 'svelte/no-navigation-without-base'
5+
description: 'disallow using navigation (links, goto, pushState, replaceState) without the base path'
6+
since: 'v2.36.0-next.9'
7+
---
8+
9+
# svelte/no-navigation-without-base
10+
11+
> disallow using navigation (links, goto, pushState, replaceState) without the base path
12+
13+
## :book: Rule Details
14+
15+
This rule reports navigation using HTML `<a>` tags, SvelteKit's `goto()`, `pushState()` and `replaceState()` functions without prefixing a relative URL with the base path. All four of these may be used for navigation, with `goto()`, `pushState()` and `replaceState()` being intended solely for iternal navigation (i.e. not leaving the site), while `<a>` tags may be used for both internal and external navigation. When using any way of internal navigation, the base path must be prepended, otherwise the site may break. For programmatic navigation to external URLs, using `window.location` is advised.
16+
17+
This rule checks all 4 navigation options for the presence of the base path, with an exception for `<a>` links to absolute URLs, which are assumed to be used for external navigation and so do not require the base path, and for shallow outing functions with an empty string as the path, which keeps the current URL.
18+
19+
<!--eslint-skip-->
20+
21+
```svelte
22+
<script>
23+
/* eslint svelte/no-navigation-without-base: "error" */
24+
25+
import { goto, pushState, replaceState } from '$app/navigation';
26+
import { base } from '$app/paths';
27+
28+
// ✓ GOOD
29+
goto(base + '/foo/');
30+
goto(`${base}/foo/`);
31+
32+
pushState(base + '/foo/', {});
33+
pushState(`${base}/foo/`, {});
34+
pushState('', {});
35+
36+
replaceState(base + '/foo/', {});
37+
replaceState(`${base}/foo/`, {});
38+
replaceState('', {});
39+
40+
// ✗ BAD
41+
goto('/foo');
42+
goto('/foo/' + base);
43+
44+
pushState('/foo', {});
45+
replaceState('/foo', {});
46+
</script>
47+
48+
<!-- ✓ GOOD -->
49+
<a href={base + '/foo/'}>Click me!</a>
50+
<a href={`${base}/foo/`}>Click me!</a>
51+
<a href="https://svelte.dev">Click me!</a>
52+
53+
<!-- ✗ BAD -->
54+
<a href="/foo">Click me!</a>
55+
<a href={'/foo'}>Click me!</a>
56+
```
57+
58+
## :wrench: Options
59+
60+
```json
61+
{
62+
"svelte/no-navigation-without-base": [
63+
"error",
64+
{
65+
"ignoreGoto": false,
66+
"ignoreLinks": false,
67+
"ignorePushState": false,
68+
"ignoreReplaceState": false
69+
}
70+
]
71+
}
72+
```
73+
74+
- `ignoreGoto` ... Whether to ignore all `goto()` calls. Default `false`.
75+
- `ignoreLinks` ... Whether to ignore all `<a>` tags. Default `false`.
76+
- `ignorePushState` ... Whether to ignore all `pushState()` calls. Default `false`.
77+
- `ignoreReplaceState` ... Whether to ignore all `replaceState()` calls. Default `false`.
78+
79+
## :books: Further Reading
80+
81+
- [`base` documentation](https://svelte.dev/docs/kit/$app-paths#base)
82+
- [Shallow routing](https://svelte.dev/docs/kit/shallow-routing)
83+
- [`goto()` documentation](https://svelte.dev/docs/kit/$app-navigation#goto)
84+
- [`pushState()` documentation](https://svelte.dev/docs/kit/$app-navigation#pushState)
85+
- [`replaceState()` documentation](https://svelte.dev/docs/kit/$app-navigation#replaceState)
86+
87+
## :rocket: Version
88+
89+
This rule was introduced in eslint-plugin-svelte v2.36.0-next.9
90+
91+
## :mag: Implementation
92+
93+
- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/src/rules/no-navigation-without-base.ts)
94+
- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/tests/src/rules/no-navigation-without-base.ts)

packages/eslint-plugin-svelte/src/rule-types.ts

+13
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ export interface RuleOptions {
152152
/**
153153
* disallow using goto() without the base path
154154
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-goto-without-base/
155+
* @deprecated
155156
*/
156157
'svelte/no-goto-without-base'?: Linter.RuleEntry<[]>
157158
/**
@@ -179,6 +180,11 @@ export interface RuleOptions {
179180
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-inspect/
180181
*/
181182
'svelte/no-inspect'?: Linter.RuleEntry<[]>
183+
/**
184+
* disallow using navigation (links, goto, pushState, replaceState) without the base path
185+
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-navigation-without-base/
186+
*/
187+
'svelte/no-navigation-without-base'?: Linter.RuleEntry<SvelteNoNavigationWithoutBase>
182188
/**
183189
* disallow use of not function in event handler
184190
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-not-function-handler/
@@ -447,6 +453,13 @@ type SvelteNoInlineStyles = []|[{
447453
type SvelteNoInnerDeclarations = []|[("functions" | "both")]|[("functions" | "both"), {
448454
blockScopedFunctions?: ("allow" | "disallow")
449455
}]
456+
// ----- svelte/no-navigation-without-base -----
457+
type SvelteNoNavigationWithoutBase = []|[{
458+
ignoreGoto?: boolean
459+
ignoreLinks?: boolean
460+
ignorePushState?: boolean
461+
ignoreReplaceState?: boolean
462+
}]
450463
// ----- svelte/no-reactive-reassign -----
451464
type SvelteNoReactiveReassign = []|[{
452465
props?: boolean

packages/eslint-plugin-svelte/src/rules/no-goto-without-base.ts

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import type { RuleContext } from '../types.js';
77

88
export default createRule('no-goto-without-base', {
99
meta: {
10+
deprecated: true,
11+
replacedBy: ['no-navigation-without-base'],
1012
docs: {
1113
description: 'disallow using goto() without the base path',
1214
category: 'SvelteKit',

0 commit comments

Comments
 (0)