Skip to content

Commit da4d535

Browse files
authored
feat: add svelte/no-svelte-internal rule (#749)
`svelte/internal` is deprecated in Svelte 5 and will be removed in Svelte 6 according to our current plan. The Svelte compiler only compiles `.svelte` files and `.svelte.[jt]s` files, so the compiler can not check normal `.[jt]s` files. Therefore, the ESLint plugin checks this.
1 parent bb245f1 commit da4d535

23 files changed

+193
-0
lines changed

.changeset/chilly-bats-allow.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-svelte-internal` rule

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ These rules relate to better ways of doing things to help you avoid problems:
385385
| [svelte/no-inline-styles](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-inline-styles/) | disallow attributes and directives that produce inline styles | |
386386
| [svelte/no-reactive-functions](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-reactive-functions/) | it's not necessary to define functions in reactive statements | :bulb: |
387387
| [svelte/no-reactive-literals](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-reactive-literals/) | don't assign literal values in reactive statements | :bulb: |
388+
| [svelte/no-svelte-internal](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-svelte-internal/) | svelte/internal will be removed in Svelte 6. | |
388389
| [svelte/no-unused-class-name](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unused-class-name/) | disallow the use of a class in the template without a corresponding style | |
389390
| [svelte/no-unused-svelte-ignore](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unused-svelte-ignore/) | disallow unused svelte-ignore comments | :star: |
390391
| [svelte/no-useless-mustaches](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-useless-mustaches/) | disallow unnecessary mustache interpolations | :wrench: |

docs/rules.md

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ These rules relate to better ways of doing things to help you avoid problems:
5858
| [svelte/no-inline-styles](./rules/no-inline-styles.md) | disallow attributes and directives that produce inline styles | |
5959
| [svelte/no-reactive-functions](./rules/no-reactive-functions.md) | it's not necessary to define functions in reactive statements | :bulb: |
6060
| [svelte/no-reactive-literals](./rules/no-reactive-literals.md) | don't assign literal values in reactive statements | :bulb: |
61+
| [svelte/no-svelte-internal](./rules/no-svelte-internal.md) | svelte/internal will be removed in Svelte 6. | |
6162
| [svelte/no-unused-class-name](./rules/no-unused-class-name.md) | disallow the use of a class in the template without a corresponding style | |
6263
| [svelte/no-unused-svelte-ignore](./rules/no-unused-svelte-ignore.md) | disallow unused svelte-ignore comments | :star: |
6364
| [svelte/no-useless-mustaches](./rules/no-useless-mustaches.md) | disallow unnecessary mustache interpolations | :wrench: |

docs/rules/no-svelte-internal.md

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
pageClass: 'rule-details'
3+
sidebarDepth: 0
4+
title: 'svelte/no-svelte-internal'
5+
description: 'svelte/internal will be removed in Svelte 6.'
6+
---
7+
8+
# svelte/no-svelte-internal
9+
10+
> svelte/internal will be removed in Svelte 6.
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 the use of the deprecated API `svelte/internal` and `svelte/internal/xxx`. `svelte/internal` is deprecated in Svelte 5. And it will be deleted in Svelte 6. These APIs can change in breaking ways at any time without notice.
17+
18+
<ESLintCodeBlock>
19+
20+
<!--eslint-skip-->
21+
22+
```svelte
23+
<script>
24+
/* eslint svelte/no-svelte-internal: "error" */
25+
// ✓ GOOD
26+
import { mount } from 'svelte';
27+
28+
// ✗ BAD
29+
import { get_current_component } from 'svelte/internal';
30+
import { inspect } from 'svelte/internal/client';
31+
import('svelte/internal');
32+
import('svelte/internal/disclose-version');
33+
34+
export * from 'svelte/internal';
35+
export { listen } from 'svelte/internal';
36+
export * from 'svelte/internal/server';
37+
</script>
38+
```
39+
40+
</ESLintCodeBlock>
41+
42+
## :wrench: Options
43+
44+
Nothing.
45+
46+
## :books: Further Reading
47+
48+
<!--TODO: update here when relevant statements are added in Svelte 5 documentation -->
49+
50+
Nothing.
51+
52+
## :mag: Implementation
53+
54+
- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/src/rules/no-svelte-internal.ts)
55+
- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/tests/src/rules/no-svelte-internal.ts)

src/rule-types.ts

+5
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,11 @@ export interface RuleOptions {
209209
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-store-async/
210210
*/
211211
'svelte/no-store-async'?: Linter.RuleEntry<[]>
212+
/**
213+
* svelte/internal will be removed in Svelte 6.
214+
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-svelte-internal/
215+
*/
216+
'svelte/no-svelte-internal'?: Linter.RuleEntry<[]>
212217
/**
213218
* disallow `target="_blank"` attribute without `rel="noopener noreferrer"`
214219
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-target-blank/

src/rules/no-svelte-internal.ts

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { createRule } from '../utils';
2+
import type { TSESTree } from '@typescript-eslint/types';
3+
4+
export default createRule('no-svelte-internal', {
5+
meta: {
6+
docs: {
7+
description: 'svelte/internal will be removed in Svelte 6.',
8+
category: 'Best Practices',
9+
// TODO Switch to recommended in the major version.
10+
// recommended: true,
11+
recommended: false
12+
},
13+
schema: [],
14+
messages: {
15+
unexpected: 'Using svelte/internal is prohibited. This will be removed in Svelte 6.'
16+
},
17+
type: 'problem'
18+
},
19+
create(context) {
20+
function report(node: TSESTree.Node) {
21+
context.report({
22+
node,
23+
messageId: 'unexpected'
24+
});
25+
}
26+
27+
function isSvelteInternal(value: string) {
28+
return value === 'svelte/internal' || value.startsWith('svelte/internal/');
29+
}
30+
31+
return {
32+
ImportDeclaration(node) {
33+
if (node.source && isSvelteInternal(node.source.value)) {
34+
report(node);
35+
}
36+
},
37+
ImportExpression(node) {
38+
if (
39+
node.source &&
40+
node.source.type === 'Literal' &&
41+
typeof node.source.value === 'string' &&
42+
isSvelteInternal(node.source.value)
43+
) {
44+
report(node);
45+
}
46+
},
47+
ExportNamedDeclaration(node) {
48+
if (node.source && isSvelteInternal(node.source.value)) {
49+
report(node);
50+
}
51+
},
52+
ExportAllDeclaration(node) {
53+
if (node.source && isSvelteInternal(node.source.value)) {
54+
report(node);
55+
}
56+
}
57+
};
58+
}
59+
});

src/utils/rules.ts

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import noRestrictedHtmlElements from '../rules/no-restricted-html-elements';
4141
import noShorthandStylePropertyOverrides from '../rules/no-shorthand-style-property-overrides';
4242
import noSpacesAroundEqualSignsInAttribute from '../rules/no-spaces-around-equal-signs-in-attribute';
4343
import noStoreAsync from '../rules/no-store-async';
44+
import noSvelteInternal from '../rules/no-svelte-internal';
4445
import noTargetBlank from '../rules/no-target-blank';
4546
import noTrailingSpaces from '../rules/no-trailing-spaces';
4647
import noUnknownStyleDirectiveProperty from '../rules/no-unknown-style-directive-property';
@@ -105,6 +106,7 @@ export const rules = [
105106
noShorthandStylePropertyOverrides,
106107
noSpacesAroundEqualSignsInAttribute,
107108
noStoreAsync,
109+
noSvelteInternal,
108110
noTargetBlank,
109111
noTrailingSpaces,
110112
noUnknownStyleDirectiveProperty,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- message: Using svelte/internal is prohibited. This will be removed in Svelte 6.
2+
line: 3
3+
column: 2
4+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<script>
2+
// eslint-disable-next-line camelcase -- this is a test
3+
import { get_current_component } from 'svelte/internal';
4+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- message: Using svelte/internal is prohibited. This will be removed in Svelte 6.
2+
line: 2
3+
column: 2
4+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<script>
2+
import { inspect } from 'svelte/internal/client';
3+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- message: Using svelte/internal is prohibited. This will be removed in Svelte 6.
2+
line: 2
3+
column: 2
4+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<script>
2+
import * as svelteInternal from 'svelte/internal';
3+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- message: Using svelte/internal is prohibited. This will be removed in Svelte 6.
2+
line: 2
3+
column: 2
4+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<script>
2+
export * from 'svelte/internal';
3+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- message: Using svelte/internal is prohibited. This will be removed in Svelte 6.
2+
line: 2
3+
column: 2
4+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<script>
2+
export * from 'svelte/internal/client';
3+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- message: Using svelte/internal is prohibited. This will be removed in Svelte 6.
2+
line: 2
3+
column: 2
4+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<script>
2+
export { inspect } from 'svelte/internal/client';
3+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- message: Using svelte/internal is prohibited. This will be removed in Svelte 6.
2+
line: 2
3+
column: 2
4+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<script>
2+
import('svelte/internal');
3+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<script>
2+
import { mount } from 'svelte';
3+
</script>

tests/src/rules/no-svelte-internal.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { RuleTester } from '../../utils/eslint-compat';
2+
import rule from '../../../src/rules/no-svelte-internal';
3+
import { loadTestCases } from '../../utils/utils';
4+
5+
const tester = new RuleTester({
6+
languageOptions: {
7+
ecmaVersion: 2020,
8+
sourceType: 'module'
9+
}
10+
});
11+
12+
tester.run('no-svelte-internal', rule as any, loadTestCases('no-svelte-internal'));

0 commit comments

Comments
 (0)