Skip to content

feat: replaced no-navigation-without-base with no-navigation-without-resolve #1289

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/huge-taxis-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'eslint-plugin-svelte': minor
---

feat: added the no-navigation-without-resolve rule
5 changes: 5 additions & 0 deletions .changeset/loud-rockets-lay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'eslint-plugin-svelte': minor
---

chore: deprecated the no-navigation-without-base rule
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ These rules relate to SvelteKit and its best Practices.
| Rule ID | Description | |
|:--------|:------------|:---|
| [svelte/no-export-load-in-svelte-module-in-kit-pages](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-export-load-in-svelte-module-in-kit-pages/) | disallow exporting load functions in `*.svelte` module in SvelteKit page components. | :star: |
| [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 | |
| [svelte/no-navigation-without-resolve](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-navigation-without-resolve/) | disallow using navigation (links, goto, pushState, replaceState) without a resolve() | |
| [svelte/valid-prop-names-in-kit-pages](https://sveltejs.github.io/eslint-plugin-svelte/rules/valid-prop-names-in-kit-pages/) | disallow props other than data or errors in SvelteKit page components. | :star: |

## Experimental
Expand Down Expand Up @@ -393,7 +393,8 @@ These rules relate to this plugin works:
|:--------|:------------|
| [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. |
| [svelte/no-dynamic-slot-name](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-dynamic-slot-name/) | Now Svelte compiler itself throws an compile error. |
| [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/) |
| [svelte/no-goto-without-base](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-goto-without-base/) | [svelte/no-navigation-without-resolve](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-navigation-without-resolve/) |
| [svelte/no-navigation-without-base](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-navigation-without-base/) | [svelte/no-navigation-without-resolve](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-navigation-without-resolve/) |

<!--RULES_TABLE_END-->
<!--RULES_SECTION_END-->
Expand Down
21 changes: 11 additions & 10 deletions docs/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@ These rules extend the rules provided by ESLint itself, or other plugins to work

These rules relate to SvelteKit and its best Practices.

| Rule ID | Description | |
| :------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------- | :----- |
| [svelte/no-export-load-in-svelte-module-in-kit-pages](./rules/no-export-load-in-svelte-module-in-kit-pages.md) | disallow exporting load functions in `*.svelte` module in SvelteKit page components. | :star: |
| [svelte/no-navigation-without-base](./rules/no-navigation-without-base.md) | disallow using navigation (links, goto, pushState, replaceState) without the base path | |
| [svelte/valid-prop-names-in-kit-pages](./rules/valid-prop-names-in-kit-pages.md) | disallow props other than data or errors in SvelteKit page components. | :star: |
| Rule ID | Description | |
| :------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------- | :----- |
| [svelte/no-export-load-in-svelte-module-in-kit-pages](./rules/no-export-load-in-svelte-module-in-kit-pages.md) | disallow exporting load functions in `*.svelte` module in SvelteKit page components. | :star: |
| [svelte/no-navigation-without-resolve](./rules/no-navigation-without-resolve.md) | disallow using navigation (links, goto, pushState, replaceState) without a resolve() | |
| [svelte/valid-prop-names-in-kit-pages](./rules/valid-prop-names-in-kit-pages.md) | disallow props other than data or errors in SvelteKit page components. | :star: |

## Experimental

Expand All @@ -146,8 +146,9 @@ These rules relate to this plugin works:
- :warning: We're going to remove deprecated rules in the next major release. Please migrate to successor/new rules.
- :innocent: We don't fix bugs which are in deprecated rules since we don't have enough resources.

| Rule ID | Replaced by |
| :----------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------- |
| [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. |
| [svelte/no-dynamic-slot-name](./rules/no-dynamic-slot-name.md) | Now Svelte compiler itself throws an compile error. |
| [svelte/no-goto-without-base](./rules/no-goto-without-base.md) | [svelte/no-navigation-without-base](./rules/no-navigation-without-base.md) |
| Rule ID | Replaced by |
| :----------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------- |
| [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. |
| [svelte/no-dynamic-slot-name](./rules/no-dynamic-slot-name.md) | Now Svelte compiler itself throws an compile error. |
| [svelte/no-goto-without-base](./rules/no-goto-without-base.md) | [svelte/no-navigation-without-resolve](./rules/no-navigation-without-resolve.md) |
| [svelte/no-navigation-without-base](./rules/no-navigation-without-base.md) | [svelte/no-navigation-without-resolve](./rules/no-navigation-without-resolve.md) |
2 changes: 1 addition & 1 deletion docs/rules/no-goto-without-base.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ since: 'v2.36.0-next.9'

> disallow using goto() without the base path

- :warning: This rule was **deprecated** and replaced by [svelte/no-navigation-without-base](no-navigation-without-base.md) rule.
- :warning: This rule was **deprecated** and replaced by [svelte/no-navigation-without-resolve](no-navigation-without-resolve.md) rule.

## :book: Rule Details

Expand Down
2 changes: 2 additions & 0 deletions docs/rules/no-navigation-without-base.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ since: 'v2.36.0-next.9'

> disallow using navigation (links, goto, pushState, replaceState) without the base path

- :warning: This rule was **deprecated** and replaced by [svelte/no-navigation-without-resolve](no-navigation-without-resolve.md) rule.

## :book: Rule Details

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.
Expand Down
91 changes: 91 additions & 0 deletions docs/rules/no-navigation-without-resolve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
pageClass: 'rule-details'
sidebarDepth: 0
title: 'svelte/no-navigation-without-resolve'
description: 'disallow using navigation (links, goto, pushState, replaceState) without a resolve()'
since: 'v2.36.0-next.9'
---

# svelte/no-navigation-without-resolve

> disallow using navigation (links, goto, pushState, replaceState) without a resolve()

## :book: Rule Details

This rule reports navigation using HTML `<a>` tags, SvelteKit's `goto()`, `pushState()` and `replaceState()` functions without resolving a relative URL. 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 URL must be resolved using SvelteKit's `resolve()`, otherwise the site may break. For programmatic navigation to external URLs, using `window.location` is advised.

This rule checks all 4 navigation options for the presence of the `resolve()` fucntion call, with an exception for `<a>` links to absolute URLs (and fragment URLs), which are assumed to be used for external navigation and so do not require the `resolve()` function, and for shallow outing functions with an empty string as the path, which keeps the current URL.

<!--eslint-skip-->

```svelte
<script>
/* eslint svelte/no-navigation-without-resolve: "error" */

import { goto, pushState, replaceState } from '$app/navigation';
import { resolve } from '$app/paths';

// ✓ GOOD
goto(resolve('/foo/'));

pushState(resolve('/foo/'), {});
pushState('', {});

replaceState(resolve('/foo/'), {});
replaceState('', {});

// ✗ BAD
goto('/foo');
goto('/foo' + resolve('/bar'));
goto(resolve('/foo') + '/bar');

pushState('/foo', {});
replaceState('/foo', {});
</script>

<!-- ✓ GOOD -->
<a href={resolve('/foo/')}>Click me!</a>
<a href="https://svelte.dev">Click me!</a>

<!-- ✗ BAD -->
<a href="/foo">Click me!</a>
<a href={'/foo'}>Click me!</a>
```

## :wrench: Options

```json
{
"svelte/no-navigation-without-resolve": [
"error",
{
"ignoreGoto": false,
"ignoreLinks": false,
"ignorePushState": false,
"ignoreReplaceState": false
}
]
}
```

- `ignoreGoto` ... Whether to ignore all `goto()` calls. Default `false`.
- `ignoreLinks` ... Whether to ignore all `<a>` tags. Default `false`.
- `ignorePushState` ... Whether to ignore all `pushState()` calls. Default `false`.
- `ignoreReplaceState` ... Whether to ignore all `replaceState()` calls. Default `false`.

## :books: Further Reading

- [`resolve()` documentation](https://svelte.dev/docs/kit/$app-paths#resolve)
- [Shallow routing](https://svelte.dev/docs/kit/shallow-routing)
- [`goto()` documentation](https://svelte.dev/docs/kit/$app-navigation#goto)
- [`pushState()` documentation](https://svelte.dev/docs/kit/$app-navigation#pushState)
- [`replaceState()` documentation](https://svelte.dev/docs/kit/$app-navigation#replaceState)

## :rocket: Version

This rule was introduced in eslint-plugin-svelte v2.36.0-next.9

## :mag: Implementation

- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/src/rules/no-navigation-without-resolve.ts)
- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/tests/src/rules/no-navigation-without-resolve.ts)
13 changes: 13 additions & 0 deletions packages/eslint-plugin-svelte/src/rule-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,14 @@ export interface RuleOptions {
/**
* disallow using navigation (links, goto, pushState, replaceState) without the base path
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-navigation-without-base/
* @deprecated
*/
'svelte/no-navigation-without-base'?: Linter.RuleEntry<SvelteNoNavigationWithoutBase>
/**
* disallow using navigation (links, goto, pushState, replaceState) without a resolve()
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-navigation-without-resolve/
*/
'svelte/no-navigation-without-resolve'?: Linter.RuleEntry<SvelteNoNavigationWithoutResolve>
/**
* disallow use of not function in event handler
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-not-function-handler/
Expand Down Expand Up @@ -518,6 +524,13 @@ type SvelteNoNavigationWithoutBase = []|[{
ignorePushState?: boolean
ignoreReplaceState?: boolean
}]
// ----- svelte/no-navigation-without-resolve -----
type SvelteNoNavigationWithoutResolve = []|[{
ignoreGoto?: boolean
ignoreLinks?: boolean
ignorePushState?: boolean
ignoreReplaceState?: boolean
}]
// ----- svelte/no-reactive-reassign -----
type SvelteNoReactiveReassign = []|[{
props?: boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { RuleContext } from '../types.js';
export default createRule('no-goto-without-base', {
meta: {
deprecated: true,
replacedBy: ['no-navigation-without-base'],
replacedBy: ['no-navigation-without-resolve'],
docs: {
description: 'disallow using goto() without the base path',
category: 'SvelteKit',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import type { AST } from 'svelte-eslint-parser';

export default createRule('no-navigation-without-base', {
meta: {
deprecated: true,
replacedBy: ['no-navigation-without-resolve'],
docs: {
description:
'disallow using navigation (links, goto, pushState, replaceState) without the base path',
Expand Down
Loading
Loading