eslint-plugin-svelte 2.13.0 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -300,7 +300,9 @@ These rules relate to possible syntax or logic errors in Svelte code:
300
300
  |:--------|:------------|:---|
301
301
  | [svelte/no-dom-manipulating](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dom-manipulating/) | disallow DOM manipulating | |
302
302
  | [svelte/no-dupe-else-if-blocks](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dupe-else-if-blocks/) | disallow duplicate conditions in `{#if}` / `{:else if}` chains | :star: |
303
+ | [svelte/no-dupe-on-directives](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dupe-on-directives/) | disallow duplicate `on:` directives | |
303
304
  | [svelte/no-dupe-style-properties](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dupe-style-properties/) | disallow duplicate style properties | :star: |
305
+ | [svelte/no-dupe-use-directives](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dupe-use-directives/) | disallow duplicate `use:` directives | |
304
306
  | [svelte/no-dynamic-slot-name](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dynamic-slot-name/) | disallow dynamic slot name | :star::wrench: |
305
307
  | [svelte/no-export-load-in-svelte-module-in-kit-pages](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-export-load-in-svelte-module-in-kit-pages/) | disallow exporting load functions in `*.svelte` module in Svelte Kit page components. | |
306
308
  | [svelte/no-not-function-handler](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-not-function-handler/) | disallow use of not function in event handler | :star: |
@@ -1,6 +1,6 @@
1
1
  import type { AST } from "svelte-eslint-parser";
2
2
  import type { TSESTree } from "@typescript-eslint/types";
3
- declare type AnyToken = AST.Token | AST.Comment;
3
+ type AnyToken = AST.Token | AST.Comment;
4
4
  export declare function isWhitespace(token: AnyToken | TSESTree.Comment | null | undefined): boolean;
5
5
  export declare function isNotWhitespace(token: AnyToken | TSESTree.Comment | null | undefined): boolean;
6
6
  export {};
@@ -1,13 +1,13 @@
1
1
  import type { ASTNode, SourceCode } from "../../types";
2
2
  import type { AST } from "svelte-eslint-parser";
3
3
  import type { OffsetContext } from "./offset-context";
4
- export declare type AnyToken = AST.Token | AST.Comment;
5
- export declare type MaybeNode = {
4
+ export type AnyToken = AST.Token | AST.Comment;
5
+ export type MaybeNode = {
6
6
  type: string;
7
7
  range: [number, number];
8
8
  loc: AST.SourceLocation;
9
9
  };
10
- export declare type IndentOptions = {
10
+ export type IndentOptions = {
11
11
  indentChar: " " | "\t";
12
12
  indentScript: boolean;
13
13
  indentSize: number;
@@ -15,7 +15,7 @@ export declare type IndentOptions = {
15
15
  alignAttributesVertically: boolean;
16
16
  ignoredNodes: string[];
17
17
  };
18
- export declare type IndentContext = {
18
+ export type IndentContext = {
19
19
  sourceCode: SourceCode;
20
20
  options: IndentOptions;
21
21
  offsets: OffsetContext;
@@ -1,5 +1,5 @@
1
1
  import type { IndentContext } from "./commons";
2
2
  import type { ESNodeListener } from "../../types-for-node";
3
- declare type NodeListener = ESNodeListener;
3
+ type NodeListener = ESNodeListener;
4
4
  export declare function defineVisitor(context: IndentContext): NodeListener;
5
5
  export {};
@@ -111,12 +111,15 @@ function defineVisitor(context) {
111
111
  },
112
112
  CallExpression(node) {
113
113
  const firstToken = sourceCode.getFirstToken(node);
114
- const leftParenToken = sourceCode.getTokenAfter(node.callee, {
114
+ const leftParenToken = sourceCode.getTokenAfter(node.typeParameters || node.callee, {
115
115
  filter: eslint_utils_1.isOpeningParenToken,
116
116
  includeComments: false,
117
117
  });
118
118
  const rightParenToken = sourceCode.getLastToken(node);
119
- for (const optionalToken of sourceCode.getTokensBetween(sourceCode.getLastToken(node.callee), leftParenToken, { filter: isOptionalToken, includeComments: false })) {
119
+ if (node.typeParameters) {
120
+ offsets.setOffsetToken(sourceCode.getFirstToken(node.typeParameters), 1, firstToken);
121
+ }
122
+ for (const optionalToken of sourceCode.getTokensBetween(sourceCode.getLastToken(node.typeParameters || node.callee), leftParenToken, { filter: isOptionalToken, includeComments: false })) {
120
123
  offsets.setOffsetToken(optionalToken, 1, firstToken);
121
124
  }
122
125
  offsets.setOffsetToken(leftParenToken, 1, firstToken);
@@ -543,10 +546,13 @@ function defineVisitor(context) {
543
546
  const newToken = sourceCode.getFirstToken(node);
544
547
  const calleeTokens = (0, commons_1.getFirstAndLastTokens)(sourceCode, node.callee);
545
548
  offsets.setOffsetToken(calleeTokens.firstToken, 1, newToken);
546
- if (node.arguments.length ||
547
- calleeTokens.lastToken.range[1] < node.range[1]) {
549
+ if (node.typeParameters) {
550
+ offsets.setOffsetToken(sourceCode.getFirstToken(node.typeParameters), 1, calleeTokens.firstToken);
551
+ }
552
+ const leftParenBefore = node.typeParameters || calleeTokens.lastToken;
553
+ if (node.arguments.length || leftParenBefore.range[1] < node.range[1]) {
548
554
  const rightParenToken = sourceCode.getLastToken(node);
549
- const leftParenToken = sourceCode.getTokenAfter(calleeTokens.lastToken);
555
+ const leftParenToken = sourceCode.getTokenAfter(leftParenBefore);
550
556
  offsets.setOffsetToken(leftParenToken, 1, calleeTokens.firstToken);
551
557
  offsets.setOffsetElementList(node.arguments, leftParenToken, rightParenToken, 1);
552
558
  }
@@ -5,7 +5,7 @@ declare const enum OffsetDataType {
5
5
  align = 1,
6
6
  start = 2
7
7
  }
8
- declare type OffsetData = {
8
+ type OffsetData = {
9
9
  type: OffsetDataType.normal;
10
10
  base: number;
11
11
  offset: number;
@@ -1,5 +1,5 @@
1
1
  import type { SvelteNodeListener } from "../../types-for-node";
2
2
  import type { IndentContext } from "./commons";
3
- declare type NodeListener = SvelteNodeListener;
3
+ type NodeListener = SvelteNodeListener;
4
4
  export declare function defineVisitor(context: IndentContext): NodeListener;
5
5
  export {};
@@ -1,5 +1,5 @@
1
1
  import type { IndentContext } from "./commons";
2
2
  import type { TSNodeListener } from "../../types-for-node";
3
- declare type NodeListener = TSNodeListener;
3
+ type NodeListener = TSNodeListener;
4
4
  export declare function defineVisitor(context: IndentContext): NodeListener;
5
5
  export {};
@@ -21,18 +21,24 @@ function defineVisitor(context) {
21
21
  },
22
22
  TSAsExpression(node) {
23
23
  const expressionTokens = (0, commons_2.getFirstAndLastTokens)(sourceCode, node.expression);
24
- const asToken = sourceCode.getTokenAfter(expressionTokens.lastToken);
24
+ const asOrSatisfiesToken = sourceCode.getTokenAfter(expressionTokens.lastToken);
25
25
  offsets.setOffsetToken([
26
- asToken,
26
+ asOrSatisfiesToken,
27
27
  (0, commons_2.getFirstAndLastTokens)(sourceCode, node.typeAnnotation).firstToken,
28
28
  ], 1, expressionTokens.firstToken);
29
29
  },
30
+ TSSatisfiesExpression(node) {
31
+ visitor.TSAsExpression(node);
32
+ },
30
33
  TSTypeReference(node) {
31
34
  if (node.typeParameters) {
32
- const typeNameTokens = (0, commons_2.getFirstAndLastTokens)(sourceCode, node.typeName);
33
- offsets.setOffsetToken(sourceCode.getFirstToken(node.typeParameters), 1, typeNameTokens.firstToken);
35
+ const firstToken = sourceCode.getFirstToken(node);
36
+ offsets.setOffsetToken(sourceCode.getFirstToken(node.typeParameters), 1, firstToken);
34
37
  }
35
38
  },
39
+ TSInstantiationExpression(node) {
40
+ visitor.TSTypeReference(node);
41
+ },
36
42
  TSTypeParameterInstantiation(node) {
37
43
  offsets.setOffsetElementList(node.params, sourceCode.getFirstToken(node), sourceCode.getLastToken(node), 1);
38
44
  },
@@ -433,6 +439,9 @@ function defineVisitor(context) {
433
439
  TSEnumMember(node) {
434
440
  visitor.TSAbstractMethodDefinition(node);
435
441
  },
442
+ TSAbstractAccessorProperty(node) {
443
+ visitor.TSAbstractMethodDefinition(node);
444
+ },
436
445
  TSOptionalType(node) {
437
446
  offsets.setOffsetToken(sourceCode.getLastToken(node), 1, sourceCode.getFirstToken(node));
438
447
  },
@@ -559,6 +568,32 @@ function defineVisitor(context) {
559
568
  offsets.setOffsetToken(atToken, 0, sourceCode.getFirstToken(decorators[0]));
560
569
  }
561
570
  },
571
+ AccessorProperty(node) {
572
+ const keyNode = node.key;
573
+ const valueNode = node.value;
574
+ const firstToken = sourceCode.getFirstToken(node);
575
+ const keyTokens = (0, commons_2.getFirstAndLastTokens)(sourceCode, keyNode);
576
+ const prefixTokens = sourceCode.getTokensBetween(firstToken, keyTokens.firstToken);
577
+ if (node.computed) {
578
+ prefixTokens.pop();
579
+ }
580
+ offsets.setOffsetToken(prefixTokens, 0, firstToken);
581
+ let lastKeyToken;
582
+ if (node.computed) {
583
+ const leftBracketToken = sourceCode.getTokenBefore(keyTokens.firstToken);
584
+ const rightBracketToken = (lastKeyToken = sourceCode.getTokenAfter(keyTokens.lastToken));
585
+ offsets.setOffsetToken(leftBracketToken, 0, firstToken);
586
+ offsets.setOffsetElementList([keyNode], leftBracketToken, rightBracketToken, 1);
587
+ }
588
+ else {
589
+ offsets.setOffsetToken(keyTokens.firstToken, 0, firstToken);
590
+ lastKeyToken = keyTokens.lastToken;
591
+ }
592
+ if (valueNode != null) {
593
+ const initToken = sourceCode.getFirstToken(valueNode);
594
+ offsets.setOffsetToken([...sourceCode.getTokensBetween(lastKeyToken, initToken), initToken], 1, lastKeyToken);
595
+ }
596
+ },
562
597
  StaticBlock(node) {
563
598
  const firstToken = sourceCode.getFirstToken(node);
564
599
  let next = sourceCode.getTokenAfter(firstToken);
@@ -632,7 +667,7 @@ function defineVisitor(context) {
632
667
  };
633
668
  const commonsVisitor = {
634
669
  ["TSTypeAliasDeclaration, TSCallSignatureDeclaration, TSConstructSignatureDeclaration, TSImportEqualsDeclaration," +
635
- "TSAbstractMethodDefinition, TSAbstractPropertyDefinition, TSEnumMember," +
670
+ "TSAbstractMethodDefinition, TSAbstractPropertyDefinition, AccessorProperty, TSAbstractAccessorProperty, TSEnumMember," +
636
671
  "TSPropertySignature, TSIndexSignature, TSMethodSignature," +
637
672
  "TSAbstractClassProperty, ClassProperty"](node) {
638
673
  const firstToken = sourceCode.getFirstToken(node);
@@ -0,0 +1,2 @@
1
+ declare const _default: import("../types").RuleModule;
2
+ export default _default;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("../utils");
4
+ const ast_utils_1 = require("../utils/ast-utils");
5
+ exports.default = (0, utils_1.createRule)("no-dupe-on-directives", {
6
+ meta: {
7
+ docs: {
8
+ description: "disallow duplicate `on:` directives",
9
+ category: "Possible Errors",
10
+ recommended: false,
11
+ },
12
+ schema: [],
13
+ messages: {
14
+ duplication: "This `on:{{type}}` directive is the same and duplicate directives in L{{lineNo}}.",
15
+ },
16
+ type: "problem",
17
+ },
18
+ create(context) {
19
+ const sourceCode = context.getSourceCode();
20
+ const directiveDataMap = new Map();
21
+ return {
22
+ SvelteDirective(node) {
23
+ if (node.kind !== "EventHandler")
24
+ return;
25
+ const directiveDataList = directiveDataMap.get(node.key.name.name);
26
+ if (!directiveDataList) {
27
+ directiveDataMap.set(node.key.name.name, [
28
+ {
29
+ expression: node.expression,
30
+ nodes: [node],
31
+ },
32
+ ]);
33
+ return;
34
+ }
35
+ const directiveData = directiveDataList.find((data) => {
36
+ if (!data.expression || !node.expression) {
37
+ return data.expression === node.expression;
38
+ }
39
+ return (0, ast_utils_1.equalTokens)(data.expression, node.expression, sourceCode);
40
+ });
41
+ if (!directiveData) {
42
+ directiveDataList.push({
43
+ expression: node.expression,
44
+ nodes: [node],
45
+ });
46
+ return;
47
+ }
48
+ directiveData.nodes.push(node);
49
+ },
50
+ "SvelteStartTag:exit"() {
51
+ for (const [type, directiveDataList] of directiveDataMap) {
52
+ for (const { nodes } of directiveDataList) {
53
+ if (nodes.length < 2) {
54
+ continue;
55
+ }
56
+ for (const node of nodes) {
57
+ context.report({
58
+ node,
59
+ messageId: "duplication",
60
+ data: {
61
+ type,
62
+ lineNo: String((nodes[0] !== node ? nodes[0] : nodes[1]).loc.start.line),
63
+ },
64
+ });
65
+ }
66
+ }
67
+ }
68
+ directiveDataMap.clear();
69
+ },
70
+ };
71
+ },
72
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("../types").RuleModule;
2
+ export default _default;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("../utils");
4
+ const ast_utils_1 = require("../utils/ast-utils");
5
+ exports.default = (0, utils_1.createRule)("no-dupe-use-directives", {
6
+ meta: {
7
+ docs: {
8
+ description: "disallow duplicate `use:` directives",
9
+ category: "Possible Errors",
10
+ recommended: false,
11
+ },
12
+ schema: [],
13
+ messages: {
14
+ duplication: "This `{{keyText}}` directive is the same and duplicate directives in L{{lineNo}}.",
15
+ },
16
+ type: "problem",
17
+ },
18
+ create(context) {
19
+ const sourceCode = context.getSourceCode();
20
+ const directiveDataMap = new Map();
21
+ return {
22
+ SvelteDirective(node) {
23
+ if (node.kind !== "Action")
24
+ return;
25
+ const keyText = (0, ast_utils_1.getAttributeKeyText)(node, context);
26
+ const directiveDataList = directiveDataMap.get(keyText);
27
+ if (!directiveDataList) {
28
+ directiveDataMap.set(keyText, [
29
+ {
30
+ expression: node.expression,
31
+ nodes: [node],
32
+ },
33
+ ]);
34
+ return;
35
+ }
36
+ const directiveData = directiveDataList.find((data) => {
37
+ if (!data.expression || !node.expression) {
38
+ return data.expression === node.expression;
39
+ }
40
+ return (0, ast_utils_1.equalTokens)(data.expression, node.expression, sourceCode);
41
+ });
42
+ if (!directiveData) {
43
+ directiveDataList.push({
44
+ expression: node.expression,
45
+ nodes: [node],
46
+ });
47
+ return;
48
+ }
49
+ directiveData.nodes.push(node);
50
+ },
51
+ "SvelteStartTag:exit"() {
52
+ for (const [keyText, directiveDataList] of directiveDataMap) {
53
+ for (const { nodes } of directiveDataList) {
54
+ if (nodes.length < 2) {
55
+ continue;
56
+ }
57
+ for (const node of nodes) {
58
+ context.report({
59
+ node,
60
+ messageId: "duplication",
61
+ data: {
62
+ keyText,
63
+ lineNo: String((nodes[0] !== node ? nodes[0] : nodes[1]).loc.start.line),
64
+ },
65
+ });
66
+ }
67
+ }
68
+ }
69
+ directiveDataMap.clear();
70
+ },
71
+ };
72
+ },
73
+ });
@@ -1,11 +1,11 @@
1
1
  import type { TSESTree } from "@typescript-eslint/types";
2
2
  import type { RuleContext } from "../../types";
3
- declare type StoreName = "writable" | "readable" | "derived";
3
+ type StoreName = "writable" | "readable" | "derived";
4
4
  export declare function extractStoreReferences(context: RuleContext, storeNames?: StoreName[]): Generator<{
5
5
  node: TSESTree.CallExpression;
6
6
  name: string;
7
7
  }, void>;
8
- export declare type StoreChecker = (node: TSESTree.Expression, options?: {
8
+ export type StoreChecker = (node: TSESTree.Expression, options?: {
9
9
  consistent?: boolean;
10
10
  }) => boolean;
11
11
  export declare function createStoreChecker(context: RuleContext): StoreChecker;
@@ -176,7 +176,7 @@ exports.default = (0, utils_1.createRule)("sort-attributes", {
176
176
  const k = cacheKeyText.get(node);
177
177
  if (k != null)
178
178
  return k;
179
- const result = (0, ast_utils_1.getAttributeKeyText)(node);
179
+ const result = (0, ast_utils_1.getAttributeKeyText)(node, context);
180
180
  cacheKeyText.set(node, result);
181
181
  return result;
182
182
  }
@@ -1,6 +1,6 @@
1
1
  import type { AST } from "svelte-eslint-parser";
2
2
  import type { Linter } from "eslint";
3
- declare type Define = {
3
+ type Define = {
4
4
  loc: AST.Position;
5
5
  };
6
6
  export declare class CommentDirectives {
@@ -1,11 +1,11 @@
1
1
  import type { AST } from "svelte-eslint-parser";
2
2
  import type { RuleContext } from "../../types";
3
- export declare type IgnoreItemWithoutCode = {
3
+ export type IgnoreItemWithoutCode = {
4
4
  range: [number, number];
5
5
  code: null;
6
6
  token: AST.Token | AST.Comment;
7
7
  };
8
- export declare type IgnoreItem = {
8
+ export type IgnoreItem = {
9
9
  range: [number, number];
10
10
  code: string;
11
11
  token: AST.Token | AST.Comment;
@@ -1,13 +1,13 @@
1
1
  import type { AST } from "svelte-eslint-parser";
2
2
  import type { RuleContext } from "../../types";
3
3
  import type { IgnoreItem } from "./ignore-comment";
4
- export declare type SvelteCompileWarnings = {
4
+ export type SvelteCompileWarnings = {
5
5
  warnings: Warning[];
6
6
  unusedIgnores: IgnoreItem[];
7
7
  kind: "warn" | "error";
8
8
  stripStyleElements: AST.SvelteStyleElement[];
9
9
  };
10
- export declare type Loc = {
10
+ export type Loc = {
11
11
  start?: {
12
12
  line: number;
13
13
  column: number;
@@ -17,7 +17,7 @@ export declare type Loc = {
17
17
  column: number;
18
18
  };
19
19
  };
20
- export declare type Warning = {
20
+ export type Warning = {
21
21
  code?: string;
22
22
  message: string;
23
23
  } & Loc;
@@ -1,5 +1,5 @@
1
1
  import type { AST } from "svelte-eslint-parser";
2
- export declare type TransformResult = {
2
+ export type TransformResult = {
3
3
  inputRange: AST.Range;
4
4
  output: string;
5
5
  mappings: string;
@@ -1,12 +1,13 @@
1
1
  import type { TSESTree, AST_NODE_TYPES } from "@typescript-eslint/types";
2
2
  import type { AST } from "svelte-eslint-parser";
3
- export declare type ASTNode = AST.SvelteNode | Exclude<Omit<TSESTree.Node, "parent">, {
3
+ export type ASTNode = AST.SvelteNode | Exclude<Omit<TSESTree.Node, "parent">, {
4
4
  type: AST.SvelteNode["type"];
5
5
  }>;
6
- export declare type ASTNodeWithParent = (Exclude<ASTNode, AST.SvelteProgram> & {
6
+ export type ASTNodeWithParent = (Exclude<ASTNode, AST.SvelteProgram> & {
7
7
  parent: ASTNodeWithParent;
8
8
  }) | AST.SvelteProgram;
9
- export declare type ASTNodeListener = {
9
+ export type ASTNodeListener = {
10
+ AccessorProperty?: (node: TSESTree.AccessorProperty & ASTNodeWithParent) => void;
10
11
  ArrayExpression?: (node: TSESTree.ArrayExpression & ASTNodeWithParent) => void;
11
12
  ArrayPattern?: (node: TSESTree.ArrayPattern & ASTNodeWithParent) => void;
12
13
  ArrowFunctionExpression?: (node: TSESTree.ArrowFunctionExpression & ASTNodeWithParent) => void;
@@ -94,6 +95,7 @@ export declare type ASTNodeListener = {
94
95
  WhileStatement?: (node: TSESTree.WhileStatement & ASTNodeWithParent) => void;
95
96
  WithStatement?: (node: TSESTree.WithStatement & ASTNodeWithParent) => void;
96
97
  YieldExpression?: (node: TSESTree.YieldExpression & ASTNodeWithParent) => void;
98
+ TSAbstractAccessorProperty?: (node: TSESTree.TSAbstractAccessorProperty & ASTNodeWithParent) => void;
97
99
  TSAbstractKeyword?: (node: TSESTree.TSAbstractKeyword & ASTNodeWithParent) => void;
98
100
  TSAbstractMethodDefinition?: (node: TSESTree.TSAbstractMethodDefinition & ASTNodeWithParent) => void;
99
101
  TSAbstractPropertyDefinition?: (node: TSESTree.TSAbstractPropertyDefinition & ASTNodeWithParent) => void;
@@ -151,6 +153,7 @@ export declare type ASTNodeListener = {
151
153
  TSQualifiedName?: (node: TSESTree.TSQualifiedName & ASTNodeWithParent) => void;
152
154
  TSReadonlyKeyword?: (node: TSESTree.TSReadonlyKeyword & ASTNodeWithParent) => void;
153
155
  TSRestType?: (node: TSESTree.TSRestType & ASTNodeWithParent) => void;
156
+ TSSatisfiesExpression?: (node: TSESTree.TSSatisfiesExpression & ASTNodeWithParent) => void;
154
157
  TSStaticKeyword?: (node: TSESTree.TSStaticKeyword & ASTNodeWithParent) => void;
155
158
  TSStringKeyword?: (node: TSESTree.TSStringKeyword & ASTNodeWithParent) => void;
156
159
  TSSymbolKeyword?: (node: TSESTree.TSSymbolKeyword & ASTNodeWithParent) => void;
@@ -204,7 +207,8 @@ export declare type ASTNodeListener = {
204
207
  SvelteHTMLComment?: (node: AST.SvelteHTMLComment & ASTNodeWithParent) => void;
205
208
  SvelteReactiveStatement?: (node: AST.SvelteReactiveStatement & ASTNodeWithParent) => void;
206
209
  };
207
- export declare type ESNodeListener = {
210
+ export type ESNodeListener = {
211
+ AccessorProperty?: (node: TSESTree.AccessorProperty & ASTNodeWithParent) => void;
208
212
  ArrayExpression?: (node: TSESTree.ArrayExpression & ASTNodeWithParent) => void;
209
213
  ArrayPattern?: (node: TSESTree.ArrayPattern & ASTNodeWithParent) => void;
210
214
  ArrowFunctionExpression?: (node: TSESTree.ArrowFunctionExpression & ASTNodeWithParent) => void;
@@ -277,10 +281,11 @@ export declare type ESNodeListener = {
277
281
  Program?: (node: AST.SvelteProgram & ASTNodeWithParent) => void;
278
282
  SvelteReactiveStatement?: (node: AST.SvelteReactiveStatement & ASTNodeWithParent) => void;
279
283
  };
280
- export declare type TSNodeListener = {
284
+ export type TSNodeListener = {
281
285
  Decorator?: (node: TSESTree.Decorator & ASTNodeWithParent) => void;
282
286
  ImportAttribute?: (node: TSESTree.ImportAttribute & ASTNodeWithParent) => void;
283
287
  StaticBlock?: (node: TSESTree.StaticBlock & ASTNodeWithParent) => void;
288
+ TSAbstractAccessorProperty?: (node: TSESTree.TSAbstractAccessorProperty & ASTNodeWithParent) => void;
284
289
  TSAbstractKeyword?: (node: TSESTree.TSAbstractKeyword & ASTNodeWithParent) => void;
285
290
  TSAbstractMethodDefinition?: (node: TSESTree.TSAbstractMethodDefinition & ASTNodeWithParent) => void;
286
291
  TSAbstractPropertyDefinition?: (node: TSESTree.TSAbstractPropertyDefinition & ASTNodeWithParent) => void;
@@ -338,6 +343,7 @@ export declare type TSNodeListener = {
338
343
  TSQualifiedName?: (node: TSESTree.TSQualifiedName & ASTNodeWithParent) => void;
339
344
  TSReadonlyKeyword?: (node: TSESTree.TSReadonlyKeyword & ASTNodeWithParent) => void;
340
345
  TSRestType?: (node: TSESTree.TSRestType & ASTNodeWithParent) => void;
346
+ TSSatisfiesExpression?: (node: TSESTree.TSSatisfiesExpression & ASTNodeWithParent) => void;
341
347
  TSStaticKeyword?: (node: TSESTree.TSStaticKeyword & ASTNodeWithParent) => void;
342
348
  TSStringKeyword?: (node: TSESTree.TSStringKeyword & ASTNodeWithParent) => void;
343
349
  TSSymbolKeyword?: (node: TSESTree.TSSymbolKeyword & ASTNodeWithParent) => void;
@@ -360,7 +366,7 @@ export declare type TSNodeListener = {
360
366
  TSUnknownKeyword?: (node: TSESTree.TSUnknownKeyword & ASTNodeWithParent) => void;
361
367
  TSVoidKeyword?: (node: TSESTree.TSVoidKeyword & ASTNodeWithParent) => void;
362
368
  };
363
- export declare type SvelteNodeListener = {
369
+ export type SvelteNodeListener = {
364
370
  SvelteScriptElement?: (node: AST.SvelteScriptElement & ASTNodeWithParent) => void;
365
371
  SvelteStyleElement?: (node: AST.SvelteStyleElement & ASTNodeWithParent) => void;
366
372
  SvelteElement?: (node: AST.SvelteElement & ASTNodeWithParent) => void;
package/lib/types.d.ts CHANGED
@@ -17,7 +17,7 @@ export interface RuleModule {
17
17
  meta: RuleMetaData;
18
18
  create: (context: RuleContext) => RuleListener;
19
19
  }
20
- export declare type RuleCategory = "Possible Errors" | "Security Vulnerability" | "Best Practices" | "Stylistic Issues" | "Extension Rules" | "System";
20
+ export type RuleCategory = "Possible Errors" | "Security Vulnerability" | "Best Practices" | "Stylistic Issues" | "Extension Rules" | "System";
21
21
  export interface RuleMetaData {
22
22
  docs: {
23
23
  description: string;
@@ -77,7 +77,7 @@ export interface PartialRuleMetaData {
77
77
  };
78
78
  type: "problem" | "suggestion" | "layout";
79
79
  }
80
- export declare type RuleContext = {
80
+ export type RuleContext = {
81
81
  id: string;
82
82
  options: any[];
83
83
  settings?: {
@@ -108,7 +108,7 @@ export declare type RuleContext = {
108
108
  report(descriptor: ReportDescriptor): void;
109
109
  getCwd?: () => string;
110
110
  };
111
- export declare type NodeOrToken = {
111
+ export type NodeOrToken = {
112
112
  type: string;
113
113
  loc?: AST.SourceLocation | null;
114
114
  range?: [number, number];
@@ -119,22 +119,22 @@ interface ReportDescriptorOptionsBase {
119
119
  };
120
120
  fix?: null | ((fixer: RuleFixer) => null | Rule.Fix | IterableIterator<Rule.Fix> | Rule.Fix[]);
121
121
  }
122
- declare type SuggestionDescriptorMessage = {
122
+ type SuggestionDescriptorMessage = {
123
123
  desc: string;
124
124
  } | {
125
125
  messageId: string;
126
126
  };
127
- export declare type SuggestionReportDescriptor = SuggestionDescriptorMessage & ReportDescriptorOptionsBase;
127
+ export type SuggestionReportDescriptor = SuggestionDescriptorMessage & ReportDescriptorOptionsBase;
128
128
  interface ReportDescriptorOptions extends ReportDescriptorOptionsBase {
129
129
  suggest?: SuggestionReportDescriptor[] | null;
130
130
  }
131
- declare type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions;
132
- declare type ReportDescriptorMessage = {
131
+ type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions;
132
+ type ReportDescriptorMessage = {
133
133
  message: string;
134
134
  } | {
135
135
  messageId: string;
136
136
  };
137
- declare type ReportDescriptorLocation = {
137
+ type ReportDescriptorLocation = {
138
138
  node: NodeOrToken;
139
139
  } | {
140
140
  loc: AST.SourceLocation | {
@@ -32,7 +32,7 @@ export declare function getLangValue(node: SvAST.SvelteScriptElement | SvAST.Sve
32
32
  export declare function findVariable(context: RuleContext, node: TSESTree.Identifier): Variable | null;
33
33
  export declare function getScope(context: RuleContext, currentNode: TSESTree.Node): Scope;
34
34
  export declare function getParent(node: TSESTree.Node): TSESTree.Node | null;
35
- export declare type QuoteAndRange = {
35
+ export type QuoteAndRange = {
36
36
  quote: "unquoted" | "double" | "single";
37
37
  range: [number, number];
38
38
  firstToken: SvAST.Token | SvAST.Comment;
@@ -47,7 +47,7 @@ export declare function getMustacheTokens(node: SvAST.SvelteDirective | SvAST.Sv
47
47
  openToken: SvAST.Token;
48
48
  closeToken: SvAST.Token;
49
49
  } | null;
50
- export declare function getAttributeKeyText(node: SvAST.SvelteAttribute | SvAST.SvelteShorthandAttribute | SvAST.SvelteStyleDirective | SvAST.SvelteDirective | SvAST.SvelteSpecialDirective): string;
50
+ export declare function getAttributeKeyText(node: SvAST.SvelteAttribute | SvAST.SvelteShorthandAttribute | SvAST.SvelteStyleDirective | SvAST.SvelteDirective | SvAST.SvelteSpecialDirective, context: RuleContext): string;
51
51
  export declare function getDirectiveName(node: SvAST.SvelteDirective): string;
52
52
  export declare function getNodeName(node: SvAST.SvelteElement): string;
53
53
  export declare function isVoidHtmlElement(node: SvAST.SvelteElement): boolean;
@@ -276,7 +276,7 @@ function getMustacheTokens(node, sourceCode) {
276
276
  };
277
277
  }
278
278
  exports.getMustacheTokens = getMustacheTokens;
279
- function getAttributeKeyText(node) {
279
+ function getAttributeKeyText(node, context) {
280
280
  switch (node.type) {
281
281
  case "SvelteAttribute":
282
282
  case "SvelteShorthandAttribute":
@@ -287,7 +287,7 @@ function getAttributeKeyText(node) {
287
287
  return node.kind;
288
288
  case "SvelteDirective": {
289
289
  const dir = getDirectiveName(node);
290
- return `${dir}:${node.key.name.name}${node.key.modifiers.length ? `|${node.key.modifiers.join("|")}` : ""}`;
290
+ return `${dir}:${getSimpleNameFromNode(node.key.name, context)}${node.key.modifiers.length ? `|${node.key.modifiers.join("|")}` : ""}`;
291
291
  }
292
292
  default:
293
293
  throw new Error(`Unknown node type: ${node.type}`);
@@ -339,17 +339,7 @@ function getAttributeValueRangeTokens(attr, sourceCode) {
339
339
  };
340
340
  }
341
341
  function getNodeName(node) {
342
- if (node.name.type === "Identifier" || node.name.type === "SvelteName") {
343
- return node.name.name;
344
- }
345
- const memberPath = [node.name.property.name];
346
- let currentObject = node.name.object;
347
- while (currentObject.type === "SvelteMemberExpressionName") {
348
- memberPath.unshift(currentObject.property.name);
349
- currentObject = currentObject.object;
350
- }
351
- memberPath.unshift(currentObject.name);
352
- return memberPath.join(".");
342
+ return getSimpleNameFromNode(node.name);
353
343
  }
354
344
  exports.getNodeName = getNodeName;
355
345
  function isVoidHtmlElement(node) {
@@ -392,3 +382,16 @@ function isExpressionIdentifier(node) {
392
382
  return true;
393
383
  }
394
384
  exports.isExpressionIdentifier = isExpressionIdentifier;
385
+ function getSimpleNameFromNode(node, context) {
386
+ if (node.type === "Identifier" || node.type === "SvelteName") {
387
+ return node.name;
388
+ }
389
+ if (node.type === "SvelteMemberExpressionName" ||
390
+ (node.type === "MemberExpression" && !node.computed)) {
391
+ return `${getSimpleNameFromNode(node.object, context)}.${getSimpleNameFromNode(node.property, context)}`;
392
+ }
393
+ if (!context) {
394
+ throw new Error("Rule context is required");
395
+ }
396
+ return context.getSourceCode().getText(node);
397
+ }
@@ -2,7 +2,7 @@ import type { AST } from "svelte-eslint-parser";
2
2
  import type { RuleContext } from "../../types";
3
3
  import type { TSESTree } from "@typescript-eslint/types";
4
4
  export declare function parseStyleAttributeValue(node: AST.SvelteAttribute, context: RuleContext): SvelteStyleRoot<AST.SvelteMustacheTagText> | null;
5
- export declare type SvelteStyleInterpolation = AST.SvelteMustacheTagText | TSESTree.Expression;
5
+ export type SvelteStyleInterpolation = AST.SvelteMustacheTagText | TSESTree.Expression;
6
6
  export interface SvelteStyleNode<E extends SvelteStyleInterpolation> {
7
7
  nodes?: SvelteStyleChildNode<E>[];
8
8
  range: AST.Range;
@@ -40,4 +40,4 @@ export interface SvelteStyleComment extends SvelteStyleNode<never> {
40
40
  type: "comment";
41
41
  addInterpolation: (tagOrExpr: SvelteStyleInterpolation) => void;
42
42
  }
43
- export declare type SvelteStyleChildNode<E extends SvelteStyleInterpolation = SvelteStyleInterpolation> = SvelteStyleDeclaration<E> | SvelteStyleComment;
43
+ export type SvelteStyleChildNode<E extends SvelteStyleInterpolation = SvelteStyleInterpolation> = SvelteStyleDeclaration<E> | SvelteStyleComment;
@@ -1,5 +1,5 @@
1
1
  import type { Tokenizer } from "postcss/lib/tokenize";
2
2
  import tokenize from "postcss/lib/tokenize";
3
- declare type Tokenize = typeof tokenize;
3
+ type Tokenize = typeof tokenize;
4
4
  declare function templateTokenize(...args: Parameters<Tokenize>): Tokenizer;
5
5
  export default templateTokenize;
@@ -1,4 +1,4 @@
1
- declare type PackageJson = Record<string, any> & {
1
+ type PackageJson = Record<string, any> & {
2
2
  filePath: string;
3
3
  };
4
4
  export declare function getPackageJson(startPath?: string): PackageJson | null;
@@ -19,7 +19,9 @@ const no_at_debug_tags_1 = __importDefault(require("../rules/no-at-debug-tags"))
19
19
  const no_at_html_tags_1 = __importDefault(require("../rules/no-at-html-tags"));
20
20
  const no_dom_manipulating_1 = __importDefault(require("../rules/no-dom-manipulating"));
21
21
  const no_dupe_else_if_blocks_1 = __importDefault(require("../rules/no-dupe-else-if-blocks"));
22
+ const no_dupe_on_directives_1 = __importDefault(require("../rules/no-dupe-on-directives"));
22
23
  const no_dupe_style_properties_1 = __importDefault(require("../rules/no-dupe-style-properties"));
24
+ const no_dupe_use_directives_1 = __importDefault(require("../rules/no-dupe-use-directives"));
23
25
  const no_dynamic_slot_name_1 = __importDefault(require("../rules/no-dynamic-slot-name"));
24
26
  const no_export_load_in_svelte_module_in_kit_pages_1 = __importDefault(require("../rules/no-export-load-in-svelte-module-in-kit-pages"));
25
27
  const no_extra_reactive_curlies_1 = __importDefault(require("../rules/no-extra-reactive-curlies"));
@@ -66,7 +68,9 @@ exports.rules = [
66
68
  no_at_html_tags_1.default,
67
69
  no_dom_manipulating_1.default,
68
70
  no_dupe_else_if_blocks_1.default,
71
+ no_dupe_on_directives_1.default,
69
72
  no_dupe_style_properties_1.default,
73
+ no_dupe_use_directives_1.default,
70
74
  no_dynamic_slot_name_1.default,
71
75
  no_export_load_in_svelte_module_in_kit_pages_1.default,
72
76
  no_extra_reactive_curlies_1.default,
@@ -1,8 +1,8 @@
1
1
  import type { RuleContext, ASTNode } from "../../types";
2
2
  import type * as TS from "typescript";
3
- export declare type TypeScript = typeof TS;
3
+ export type TypeScript = typeof TS;
4
4
  export type { TS };
5
- export declare type TSTools = {
5
+ export type TSTools = {
6
6
  service: {
7
7
  esTreeNodeToTSNodeMap: ReadonlyMap<unknown, TS.Node>;
8
8
  tsNodeToESTreeNodeMap: ReadonlyMap<TS.Node, ASTNode>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-svelte",
3
- "version": "2.13.0",
3
+ "version": "2.14.0",
4
4
  "description": "ESLint plugin for Svelte using AST",
5
5
  "repository": "git+https://github.com/ota-meshi/eslint-plugin-svelte.git",
6
6
  "homepage": "https://ota-meshi.github.io/eslint-plugin-svelte",
@@ -73,7 +73,7 @@
73
73
  "postcss-load-config": "^3.1.4",
74
74
  "postcss-safe-parser": "^6.0.0",
75
75
  "sourcemap-codec": "^1.4.8",
76
- "svelte-eslint-parser": "^0.21.0"
76
+ "svelte-eslint-parser": "^0.22.0"
77
77
  },
78
78
  "devDependencies": {
79
79
  "@1stg/browserslist-config": "^1.2.3",
@@ -110,8 +110,8 @@
110
110
  "@types/postcss-safe-parser": "^5.0.1",
111
111
  "@types/prismjs": "^1.26.0",
112
112
  "@types/stylus": "^0.48.38",
113
- "@typescript-eslint/eslint-plugin": "^5.4.0",
114
- "@typescript-eslint/parser": "^5.4.1-0",
113
+ "@typescript-eslint/eslint-plugin": "^5.45.0",
114
+ "@typescript-eslint/parser": "^5.45.0",
115
115
  "@typescript-eslint/parser-v4": "npm:@typescript-eslint/parser@4",
116
116
  "@typescript/vfs": "^1.4.0",
117
117
  "assert": "^2.0.0",
@@ -140,7 +140,7 @@
140
140
  "less": "^4.1.2",
141
141
  "lint-staged": "^13.0.3",
142
142
  "locate-character": "^2.0.5",
143
- "magic-string": "^0.26.0",
143
+ "magic-string": "^0.27.0",
144
144
  "markdown-it-anchor": "^8.4.1",
145
145
  "markdown-it-container": "^3.0.0",
146
146
  "markdown-it-emoji": "^2.0.0",
@@ -164,7 +164,7 @@
164
164
  "svelte-adapter-ghpages": "0.0.2",
165
165
  "svelte-i18n": "^3.4.0",
166
166
  "type-coverage": "^2.22.0",
167
- "typescript": "^4.5.2",
167
+ "typescript": "^4.9.3",
168
168
  "vite": "^3.1.0-0",
169
169
  "vite-plugin-svelte-md": "^0.1.5",
170
170
  "yaml": "^2.1.1",
@@ -174,7 +174,7 @@
174
174
  "access": "public"
175
175
  },
176
176
  "typeCoverage": {
177
- "atLeast": 98.72,
177
+ "atLeast": 99.05,
178
178
  "cache": true,
179
179
  "detail": true,
180
180
  "ignoreAsAssertion": true,