Skip to content

Commit 9cffd3b

Browse files
authored
feat: add svelte/no-top-level-browser-globals rule (#1210)
1 parent 2fa75f1 commit 9cffd3b

Some content is hidden

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

55 files changed

+1251
-26
lines changed

.changeset/popular-jokes-tell.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"eslint-plugin-svelte": minor
3+
---
4+
5+
feat: add `svelte/no-top-level-browser-globals` rule

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ These rules relate to possible syntax or logic errors in Svelte code:
271271
| [svelte/no-reactive-reassign](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-reactive-reassign/) | disallow reassigning reactive values | :star: |
272272
| [svelte/no-shorthand-style-property-overrides](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-shorthand-style-property-overrides/) | disallow shorthand style properties that override related longhand properties | :star: |
273273
| [svelte/no-store-async](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-store-async/) | disallow using async/await inside svelte stores because it causes issues with the auto-unsubscribing features | :star: |
274+
| [svelte/no-top-level-browser-globals](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-top-level-browser-globals/) | disallow using top-level browser global variables | |
274275
| [svelte/no-unknown-style-directive-property](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unknown-style-directive-property/) | disallow unknown `style:property` | :star: |
275276
| [svelte/require-store-callbacks-use-set-param](https://sveltejs.github.io/eslint-plugin-svelte/rules/require-store-callbacks-use-set-param/) | store callbacks must use `set` param | :bulb: |
276277
| [svelte/require-store-reactive-access](https://sveltejs.github.io/eslint-plugin-svelte/rules/require-store-reactive-access/) | disallow to use of the store itself as an operand. Need to use $ prefix or get function. | :star::wrench: |

docs/rules.md

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ These rules relate to possible syntax or logic errors in Svelte code:
2828
| [svelte/no-reactive-reassign](./rules/no-reactive-reassign.md) | disallow reassigning reactive values | :star: |
2929
| [svelte/no-shorthand-style-property-overrides](./rules/no-shorthand-style-property-overrides.md) | disallow shorthand style properties that override related longhand properties | :star: |
3030
| [svelte/no-store-async](./rules/no-store-async.md) | disallow using async/await inside svelte stores because it causes issues with the auto-unsubscribing features | :star: |
31+
| [svelte/no-top-level-browser-globals](./rules/no-top-level-browser-globals.md) | disallow using top-level browser global variables | |
3132
| [svelte/no-unknown-style-directive-property](./rules/no-unknown-style-directive-property.md) | disallow unknown `style:property` | :star: |
3233
| [svelte/require-store-callbacks-use-set-param](./rules/require-store-callbacks-use-set-param.md) | store callbacks must use `set` param | :bulb: |
3334
| [svelte/require-store-reactive-access](./rules/require-store-reactive-access.md) | disallow to use of the store itself as an operand. Need to use $ prefix or get function. | :star::wrench: |
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
---
2+
pageClass: 'rule-details'
3+
sidebarDepth: 0
4+
title: 'svelte/no-top-level-browser-globals'
5+
description: 'disallow using top-level browser global variables'
6+
---
7+
8+
# svelte/no-top-level-browser-globals
9+
10+
> disallow using top-level browser global variables
11+
12+
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> **_This rule has not been released yet._** </badge>
13+
14+
## :book: Rule Details
15+
16+
This rule reports top-level browser global variables in Svelte components.
17+
This rule helps prevent the use of browser global variables that can cause errors in SSR (Server Side Rendering).
18+
19+
<!--eslint-skip-->
20+
21+
```svelte
22+
<script>
23+
/* eslint svelte/no-top-level-browser-globals: "error" */
24+
import { onMount } from 'svelte';
25+
import { browser } from '$app/environment';
26+
27+
/* ✓ GOOD */
28+
onMount(() => {
29+
const a = localStorage.getItem('myCat');
30+
console.log(a);
31+
});
32+
33+
/* ✓ GOOD */
34+
if (browser) {
35+
const a = localStorage.getItem('myCat');
36+
console.log(a);
37+
}
38+
39+
/* ✓ GOOD */
40+
if (typeof localStorage !== 'undefined') {
41+
const a = localStorage.getItem('myCat');
42+
console.log(a);
43+
}
44+
45+
/* ✗ BAD */
46+
const a = localStorage.getItem('myCat');
47+
console.log(a);
48+
</script>
49+
```
50+
51+
## :wrench: Options
52+
53+
Nothing.
54+
55+
## :books: Further Reading
56+
57+
- [`$app/environment` documentation > browser](https://svelte.dev/docs/kit/$app-environment#browser)
58+
59+
## :mag: Implementation
60+
61+
- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/src/rules/no-top-level-browser-globals.ts)
62+
- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/tests/src/rules/no-top-level-browser-globals.ts)

packages/eslint-plugin-svelte/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@
5656
}
5757
},
5858
"dependencies": {
59-
"@eslint-community/eslint-utils": "^4.4.1",
59+
"@eslint-community/eslint-utils": "^4.6.1",
6060
"@jridgewell/sourcemap-codec": "^1.5.0",
6161
"esutils": "^2.0.3",
62+
"globals": "^16.0.0",
6263
"known-css-properties": "^0.36.0",
6364
"postcss": "^8.4.49",
6465
"postcss-load-config": "^3.1.4",

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

+5
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,11 @@ export interface RuleOptions {
251251
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-target-blank/
252252
*/
253253
'svelte/no-target-blank'?: Linter.RuleEntry<SvelteNoTargetBlank>
254+
/**
255+
* disallow using top-level browser global variables
256+
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-top-level-browser-globals/
257+
*/
258+
'svelte/no-top-level-browser-globals'?: Linter.RuleEntry<[]>
254259
/**
255260
* disallow trailing whitespace at the end of lines
256261
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-trailing-spaces/

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ function extractGotoReferences(referenceTracker: ReferenceTracker): TSESTree.Cal
106106
}
107107
}
108108
}),
109-
({ node }) => node
109+
({ node }) => node as TSESTree.CallExpression
110110
);
111111
}
112112

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,13 @@ function extractFunctionCallReferences(referenceTracker: ReferenceTracker): {
171171
return {
172172
goto: rawReferences
173173
.filter(({ path }) => path[path.length - 1] === 'goto')
174-
.map(({ node }) => node),
174+
.map(({ node }) => node as TSESTree.CallExpression),
175175
pushState: rawReferences
176176
.filter(({ path }) => path[path.length - 1] === 'pushState')
177-
.map(({ node }) => node),
177+
.map(({ node }) => node as TSESTree.CallExpression),
178178
replaceState: rawReferences
179179
.filter(({ path }) => path[path.length - 1] === 'replaceState')
180-
.map(({ node }) => node)
180+
.map(({ node }) => node as TSESTree.CallExpression)
181181
};
182182
}
183183

0 commit comments

Comments
 (0)