Skip to content

Commit a11babd

Browse files
committed
feat: add no-add-event-listener rule
1 parent 924d4af commit a11babd

File tree

12 files changed

+448
-0
lines changed

12 files changed

+448
-0
lines changed

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ These rules relate to better ways of doing things to help you avoid problems:
294294
|:--------|:------------|:---|
295295
| [svelte/block-lang](https://sveltejs.github.io/eslint-plugin-svelte/rules/block-lang/) | disallows the use of languages other than those specified in the configuration for the lang attribute of `<script>` and `<style>` blocks. | :bulb: |
296296
| [svelte/button-has-type](https://sveltejs.github.io/eslint-plugin-svelte/rules/button-has-type/) | disallow usage of button without an explicit type attribute | |
297+
| [svelte/no-add-event-listener](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-add-event-listener/) | Warns against the use of `addEventListener` | :bulb: |
297298
| [svelte/no-at-debug-tags](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-at-debug-tags/) | disallow the use of `{@debug}` | :star::bulb: |
298299
| [svelte/no-ignored-unsubscribe](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-ignored-unsubscribe/) | disallow ignoring the unsubscribe method returned by the `subscribe()` on Svelte stores. | |
299300
| [svelte/no-immutable-reactive-statements](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-immutable-reactive-statements/) | disallow reactive statements that don't reference reactive values. | :star: |

Diff for: docs/rules.md

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ These rules relate to better ways of doing things to help you avoid problems:
5151
| :--------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- | :------------- |
5252
| [svelte/block-lang](./rules/block-lang.md) | disallows the use of languages other than those specified in the configuration for the lang attribute of `<script>` and `<style>` blocks. | :bulb: |
5353
| [svelte/button-has-type](./rules/button-has-type.md) | disallow usage of button without an explicit type attribute | |
54+
| [svelte/no-add-event-listener](./rules/no-add-event-listener.md) | Warns against the use of `addEventListener` | :bulb: |
5455
| [svelte/no-at-debug-tags](./rules/no-at-debug-tags.md) | disallow the use of `{@debug}` | :star::bulb: |
5556
| [svelte/no-ignored-unsubscribe](./rules/no-ignored-unsubscribe.md) | disallow ignoring the unsubscribe method returned by the `subscribe()` on Svelte stores. | |
5657
| [svelte/no-immutable-reactive-statements](./rules/no-immutable-reactive-statements.md) | disallow reactive statements that don't reference reactive values. | :star: |

Diff for: docs/rules/no-add-event-listener.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
pageClass: 'rule-details'
3+
sidebarDepth: 0
4+
title: 'svelte/no-add-event-listener'
5+
description: 'Warns against the use of `addEventListener`'
6+
---
7+
8+
# svelte/no-add-event-listener
9+
10+
> Warns against the use of `addEventListener`
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+
- :bulb: Some problems reported by this rule are manually fixable by editor [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).
14+
15+
## :book: Rule Details
16+
17+
This rule reports usages of `addEventListener`:
18+
19+
<!--eslint-skip-->
20+
21+
```svelte
22+
<script>
23+
/* eslint svelte/no-add-event-listener: "error" */
24+
addEventListener(window, 'resize', handler);
25+
</script>
26+
```
27+
28+
## :mag: Implementation
29+
30+
- [Rule source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/src/rules/no-add-event-listener.ts)
31+
- [Test source](https://github.com/sveltejs/eslint-plugin-svelte/blob/main/packages/eslint-plugin-svelte/tests/src/rules/no-add-event-listener.ts)

Diff for: packages/eslint-plugin-svelte/src/rule-types.ts

+5
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ export interface RuleOptions {
9999
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/mustache-spacing/
100100
*/
101101
'svelte/mustache-spacing'?: Linter.RuleEntry<SvelteMustacheSpacing>
102+
/**
103+
* Warns against the use of `addEventListener`
104+
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-add-event-listener/
105+
*/
106+
'svelte/no-add-event-listener'?: Linter.RuleEntry<[]>
102107
/**
103108
* disallow the use of `{@debug}`
104109
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/no-at-debug-tags/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import type { TSESTree } from '@typescript-eslint/types';
2+
3+
import { createRule } from '../utils/index.js';
4+
import type { SuggestionReportDescriptor } from '../types.js';
5+
6+
export default createRule('no-add-event-listener', {
7+
meta: {
8+
docs: {
9+
description: 'Warns against the use of `addEventListener`',
10+
category: 'Best Practices',
11+
recommended: false,
12+
default: 'warn'
13+
},
14+
hasSuggestions: true,
15+
schema: [],
16+
messages: {
17+
unexpected:
18+
'Do not use `addEventListener`. Use the `on` function from `svelte/events` instead.'
19+
},
20+
type: 'suggestion',
21+
conditions: [
22+
{
23+
svelteVersions: ['5']
24+
}
25+
]
26+
},
27+
create(context) {
28+
return {
29+
CallExpression(node: TSESTree.CallExpression) {
30+
const { callee, arguments: args } = node;
31+
let target: string | null = null;
32+
33+
if (args.length !== 2) {
34+
return;
35+
}
36+
37+
if (
38+
callee.type === 'MemberExpression' &&
39+
callee.property.type === 'Identifier' &&
40+
callee.property.name === 'addEventListener'
41+
) {
42+
target = context.sourceCode.getText(callee.object);
43+
} else if (callee.type === 'Identifier' && callee.name === 'addEventListener') {
44+
target = 'window';
45+
}
46+
47+
if (target === null) {
48+
return;
49+
}
50+
51+
const openParen = context.sourceCode.getTokenAfter(callee);
52+
const suggest: SuggestionReportDescriptor[] = [];
53+
54+
if (openParen !== null) {
55+
suggest.push({
56+
desc: 'Use `on` from `svelte/events` instead',
57+
fix(fixer) {
58+
return [
59+
fixer.replaceText(callee, 'on'),
60+
fixer.insertTextAfter(openParen, `${target}, `)
61+
];
62+
}
63+
});
64+
}
65+
66+
context.report({
67+
node,
68+
messageId: 'unexpected',
69+
suggest
70+
});
71+
}
72+
};
73+
}
74+
});

Diff for: packages/eslint-plugin-svelte/src/utils/rules.ts

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import indent from '../rules/indent.js';
1919
import infiniteReactiveLoop from '../rules/infinite-reactive-loop.js';
2020
import maxAttributesPerLine from '../rules/max-attributes-per-line.js';
2121
import mustacheSpacing from '../rules/mustache-spacing.js';
22+
import noAddEventListener from '../rules/no-add-event-listener.js';
2223
import noAtDebugTags from '../rules/no-at-debug-tags.js';
2324
import noAtHtmlTags from '../rules/no-at-html-tags.js';
2425
import noDomManipulating from '../rules/no-dom-manipulating.js';
@@ -94,6 +95,7 @@ export const rules = [
9495
infiniteReactiveLoop,
9596
maxAttributesPerLine,
9697
mustacheSpacing,
98+
noAddEventListener,
9799
noAtDebugTags,
98100
noAtHtmlTags,
99101
noDomManipulating,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"svelte": ">=5.0.0-0"
3+
}

0 commit comments

Comments
 (0)