eslint-plugin-svelte 2.12.0 → 2.13.1

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
@@ -298,6 +298,7 @@ These rules relate to possible syntax or logic errors in Svelte code:
298
298
 
299
299
  | Rule ID | Description | |
300
300
  |:--------|:------------|:---|
301
+ | [svelte/no-dom-manipulating](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dom-manipulating/) | disallow DOM manipulating | |
301
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: |
302
303
  | [svelte/no-dupe-style-properties](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dupe-style-properties/) | disallow duplicate style properties | :star: |
303
304
  | [svelte/no-dynamic-slot-name](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-dynamic-slot-name/) | disallow dynamic slot name | :star::wrench: |
@@ -49,14 +49,14 @@ exports.default = (0, utils_1.createRule)("html-self-closing", {
49
49
  },
50
50
  ],
51
51
  },
52
- create(ctx) {
52
+ create(context) {
53
53
  let options = {
54
54
  void: "always",
55
55
  normal: "always",
56
56
  component: "always",
57
57
  svelte: "always",
58
58
  };
59
- const option = ctx.options?.[0];
59
+ const option = context.options?.[0];
60
60
  switch (option) {
61
61
  case "none":
62
62
  options = {
@@ -103,16 +103,22 @@ exports.default = (0, utils_1.createRule)("html-self-closing", {
103
103
  }
104
104
  return true;
105
105
  }
106
- function report(node, close) {
106
+ function report(node, shouldBeClosed) {
107
107
  const elementType = getElementType(node);
108
- ctx.report({
108
+ context.report({
109
109
  node,
110
- messageId: close ? "requireClosing" : "disallowClosing",
110
+ loc: {
111
+ start: context
112
+ .getSourceCode()
113
+ .getLocFromIndex(node.startTag.range[1] - (node.startTag.selfClosing ? 2 : 1)),
114
+ end: node.loc.end,
115
+ },
116
+ messageId: shouldBeClosed ? "requireClosing" : "disallowClosing",
111
117
  data: {
112
118
  type: TYPE_MESSAGES[elementType],
113
119
  },
114
120
  *fix(fixer) {
115
- if (close) {
121
+ if (shouldBeClosed) {
116
122
  for (const child of node.children) {
117
123
  yield fixer.removeRange(child.range);
118
124
  }
@@ -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 {};
@@ -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 {};
@@ -0,0 +1,2 @@
1
+ declare const _default: import("../types").RuleModule;
2
+ export default _default;
@@ -0,0 +1,109 @@
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
+ const eslint_utils_1 = require("eslint-utils");
6
+ const DOM_MANIPULATING_METHODS = new Set([
7
+ "appendChild",
8
+ "insertBefore",
9
+ "normalize",
10
+ "removeChild",
11
+ "replaceChild",
12
+ "after",
13
+ "append",
14
+ "before",
15
+ "insertAdjacentElement",
16
+ "insertAdjacentHTML",
17
+ "insertAdjacentText",
18
+ "prepend",
19
+ "remove",
20
+ "replaceChildren",
21
+ "replaceWith",
22
+ ]);
23
+ const DOM_MANIPULATING_PROPERTIES = new Set([
24
+ "textContent",
25
+ "innerHTML",
26
+ "outerHTML",
27
+ "innerText",
28
+ "outerText",
29
+ ]);
30
+ exports.default = (0, utils_1.createRule)("no-dom-manipulating", {
31
+ meta: {
32
+ docs: {
33
+ description: "disallow DOM manipulating",
34
+ category: "Possible Errors",
35
+ recommended: false,
36
+ },
37
+ schema: [],
38
+ messages: {
39
+ disallowManipulateDOM: "Don't manipulate the DOM directly. The Svelte runtime can get confused if there is a difference between the actual DOM and the DOM expected by the Svelte runtime.",
40
+ },
41
+ type: "problem",
42
+ },
43
+ create(context) {
44
+ const domVariables = new Set();
45
+ function verifyIdentifier(node) {
46
+ const member = node.parent;
47
+ if (member?.type !== "MemberExpression" || member.object !== node) {
48
+ return;
49
+ }
50
+ const name = (0, eslint_utils_1.getPropertyName)(member);
51
+ if (!name) {
52
+ return;
53
+ }
54
+ let target = member;
55
+ let parent = target.parent;
56
+ while (parent?.type === "ChainExpression") {
57
+ target = parent;
58
+ parent = parent.parent;
59
+ }
60
+ if (!parent) {
61
+ return;
62
+ }
63
+ if (parent.type === "CallExpression") {
64
+ if (parent.callee !== target || !DOM_MANIPULATING_METHODS.has(name)) {
65
+ return;
66
+ }
67
+ }
68
+ else if (parent.type === "AssignmentExpression") {
69
+ if (parent.left !== target || !DOM_MANIPULATING_PROPERTIES.has(name)) {
70
+ return;
71
+ }
72
+ }
73
+ context.report({
74
+ node: member,
75
+ messageId: "disallowManipulateDOM",
76
+ });
77
+ }
78
+ return {
79
+ "SvelteDirective[kind='Binding']"(node) {
80
+ if (node.key.name.name !== "this" ||
81
+ !node.expression ||
82
+ node.expression.type !== "Identifier") {
83
+ return;
84
+ }
85
+ const element = node.parent.parent;
86
+ if (element.type !== "SvelteElement" || !isHTMLElement(element)) {
87
+ return;
88
+ }
89
+ const variable = (0, ast_utils_1.findVariable)(context, node.expression);
90
+ if (!variable ||
91
+ (variable.scope.type !== "module" && variable.scope.type !== "global")) {
92
+ return;
93
+ }
94
+ domVariables.add(variable);
95
+ },
96
+ "Program:exit"() {
97
+ for (const variable of domVariables) {
98
+ for (const reference of variable.references) {
99
+ verifyIdentifier(reference.identifier);
100
+ }
101
+ }
102
+ },
103
+ };
104
+ function isHTMLElement(node) {
105
+ return (node.kind === "html" ||
106
+ (node.kind === "special" && (0, ast_utils_1.getNodeName)(node) === "svelte:element"));
107
+ }
108
+ },
109
+ });
@@ -47,7 +47,8 @@ exports.default = (0, utils_1.createRule)("prefer-destructured-store-props", {
47
47
  }
48
48
  }
49
49
  function isReactiveVariableDefinitionWithMemberExpression(node) {
50
- return (node.parent?.type === "MemberExpression" &&
50
+ return (node.type === "Identifier" &&
51
+ node.parent?.type === "MemberExpression" &&
51
52
  node.parent.object === node &&
52
53
  (0, eslint_utils_1.getPropertyName)(node.parent) === propName &&
53
54
  node.parent.parent?.type === "AssignmentExpression" &&
@@ -58,7 +59,8 @@ exports.default = (0, utils_1.createRule)("prefer-destructured-store-props", {
58
59
  .parent?.type === "SvelteReactiveStatement");
59
60
  }
60
61
  function isReactiveVariableDefinitionWithDestructuring(node) {
61
- return (node.parent?.type === "AssignmentExpression" &&
62
+ return (node.type === "Identifier" &&
63
+ node.parent?.type === "AssignmentExpression" &&
62
64
  node.parent.right === node &&
63
65
  node.parent.left.type === "ObjectPattern" &&
64
66
  node.parent.parent?.type === "ExpressionStatement" &&
@@ -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,12 @@
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
10
  ArrayExpression?: (node: TSESTree.ArrayExpression & ASTNodeWithParent) => void;
11
11
  ArrayPattern?: (node: TSESTree.ArrayPattern & ASTNodeWithParent) => void;
12
12
  ArrowFunctionExpression?: (node: TSESTree.ArrowFunctionExpression & ASTNodeWithParent) => void;
@@ -151,6 +151,7 @@ export declare type ASTNodeListener = {
151
151
  TSQualifiedName?: (node: TSESTree.TSQualifiedName & ASTNodeWithParent) => void;
152
152
  TSReadonlyKeyword?: (node: TSESTree.TSReadonlyKeyword & ASTNodeWithParent) => void;
153
153
  TSRestType?: (node: TSESTree.TSRestType & ASTNodeWithParent) => void;
154
+ TSSatisfiesExpression?: (node: TSESTree.TSSatisfiesExpression & ASTNodeWithParent) => void;
154
155
  TSStaticKeyword?: (node: TSESTree.TSStaticKeyword & ASTNodeWithParent) => void;
155
156
  TSStringKeyword?: (node: TSESTree.TSStringKeyword & ASTNodeWithParent) => void;
156
157
  TSSymbolKeyword?: (node: TSESTree.TSSymbolKeyword & ASTNodeWithParent) => void;
@@ -204,7 +205,7 @@ export declare type ASTNodeListener = {
204
205
  SvelteHTMLComment?: (node: AST.SvelteHTMLComment & ASTNodeWithParent) => void;
205
206
  SvelteReactiveStatement?: (node: AST.SvelteReactiveStatement & ASTNodeWithParent) => void;
206
207
  };
207
- export declare type ESNodeListener = {
208
+ export type ESNodeListener = {
208
209
  ArrayExpression?: (node: TSESTree.ArrayExpression & ASTNodeWithParent) => void;
209
210
  ArrayPattern?: (node: TSESTree.ArrayPattern & ASTNodeWithParent) => void;
210
211
  ArrowFunctionExpression?: (node: TSESTree.ArrowFunctionExpression & ASTNodeWithParent) => void;
@@ -277,7 +278,7 @@ export declare type ESNodeListener = {
277
278
  Program?: (node: AST.SvelteProgram & ASTNodeWithParent) => void;
278
279
  SvelteReactiveStatement?: (node: AST.SvelteReactiveStatement & ASTNodeWithParent) => void;
279
280
  };
280
- export declare type TSNodeListener = {
281
+ export type TSNodeListener = {
281
282
  Decorator?: (node: TSESTree.Decorator & ASTNodeWithParent) => void;
282
283
  ImportAttribute?: (node: TSESTree.ImportAttribute & ASTNodeWithParent) => void;
283
284
  StaticBlock?: (node: TSESTree.StaticBlock & ASTNodeWithParent) => void;
@@ -338,6 +339,7 @@ export declare type TSNodeListener = {
338
339
  TSQualifiedName?: (node: TSESTree.TSQualifiedName & ASTNodeWithParent) => void;
339
340
  TSReadonlyKeyword?: (node: TSESTree.TSReadonlyKeyword & ASTNodeWithParent) => void;
340
341
  TSRestType?: (node: TSESTree.TSRestType & ASTNodeWithParent) => void;
342
+ TSSatisfiesExpression?: (node: TSESTree.TSSatisfiesExpression & ASTNodeWithParent) => void;
341
343
  TSStaticKeyword?: (node: TSESTree.TSStaticKeyword & ASTNodeWithParent) => void;
342
344
  TSStringKeyword?: (node: TSESTree.TSStringKeyword & ASTNodeWithParent) => void;
343
345
  TSSymbolKeyword?: (node: TSESTree.TSSymbolKeyword & ASTNodeWithParent) => void;
@@ -360,7 +362,7 @@ export declare type TSNodeListener = {
360
362
  TSUnknownKeyword?: (node: TSESTree.TSUnknownKeyword & ASTNodeWithParent) => void;
361
363
  TSVoidKeyword?: (node: TSESTree.TSVoidKeyword & ASTNodeWithParent) => void;
362
364
  };
363
- export declare type SvelteNodeListener = {
365
+ export type SvelteNodeListener = {
364
366
  SvelteScriptElement?: (node: AST.SvelteScriptElement & ASTNodeWithParent) => void;
365
367
  SvelteStyleElement?: (node: AST.SvelteStyleElement & ASTNodeWithParent) => void;
366
368
  SvelteElement?: (node: AST.SvelteElement & ASTNodeWithParent) => void;
package/lib/types.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import type { JSONSchema4 } from "json-schema";
2
- import type { Linter, Rule, Scope, SourceCode as ESLintSourceCode } from "eslint";
2
+ import type { Linter, Rule, SourceCode as ESLintSourceCode } from "eslint";
3
3
  import type { AST } from "svelte-eslint-parser";
4
4
  import type { TSESTree } from "@typescript-eslint/types";
5
+ import type { ScopeManager, Scope, Variable } from "@typescript-eslint/scope-manager";
5
6
  import type { ASTNode, ASTNodeWithParent, ASTNodeListener } from "./types-for-node";
6
7
  export type { ASTNode, ASTNodeWithParent, ASTNodeListener };
7
8
  export interface RuleListener extends ASTNodeListener {
@@ -16,7 +17,7 @@ export interface RuleModule {
16
17
  meta: RuleMetaData;
17
18
  create: (context: RuleContext) => RuleListener;
18
19
  }
19
- 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";
20
21
  export interface RuleMetaData {
21
22
  docs: {
22
23
  description: string;
@@ -76,7 +77,7 @@ export interface PartialRuleMetaData {
76
77
  };
77
78
  type: "problem" | "suggestion" | "layout";
78
79
  }
79
- export declare type RuleContext = {
80
+ export type RuleContext = {
80
81
  id: string;
81
82
  options: any[];
82
83
  settings?: {
@@ -99,15 +100,15 @@ export declare type RuleContext = {
99
100
  parserOptions: Linter.ParserOptions;
100
101
  parserServices: ESLintSourceCode.ParserServices;
101
102
  getAncestors(): ASTNode[];
102
- getDeclaredVariables(node: TSESTree.Node): Scope.Variable[];
103
+ getDeclaredVariables(node: TSESTree.Node): Variable[];
103
104
  getFilename(): string;
104
- getScope(): Scope.Scope;
105
+ getScope(): Scope;
105
106
  getSourceCode(): SourceCode;
106
107
  markVariableAsUsed(name: string): boolean;
107
108
  report(descriptor: ReportDescriptor): void;
108
109
  getCwd?: () => string;
109
110
  };
110
- export declare type NodeOrToken = {
111
+ export type NodeOrToken = {
111
112
  type: string;
112
113
  loc?: AST.SourceLocation | null;
113
114
  range?: [number, number];
@@ -118,22 +119,22 @@ interface ReportDescriptorOptionsBase {
118
119
  };
119
120
  fix?: null | ((fixer: RuleFixer) => null | Rule.Fix | IterableIterator<Rule.Fix> | Rule.Fix[]);
120
121
  }
121
- declare type SuggestionDescriptorMessage = {
122
+ type SuggestionDescriptorMessage = {
122
123
  desc: string;
123
124
  } | {
124
125
  messageId: string;
125
126
  };
126
- export declare type SuggestionReportDescriptor = SuggestionDescriptorMessage & ReportDescriptorOptionsBase;
127
+ export type SuggestionReportDescriptor = SuggestionDescriptorMessage & ReportDescriptorOptionsBase;
127
128
  interface ReportDescriptorOptions extends ReportDescriptorOptionsBase {
128
129
  suggest?: SuggestionReportDescriptor[] | null;
129
130
  }
130
- declare type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions;
131
- declare type ReportDescriptorMessage = {
131
+ type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions;
132
+ type ReportDescriptorMessage = {
132
133
  message: string;
133
134
  } | {
134
135
  messageId: string;
135
136
  };
136
- declare type ReportDescriptorLocation = {
137
+ type ReportDescriptorLocation = {
137
138
  node: NodeOrToken;
138
139
  } | {
139
140
  loc: AST.SourceLocation | {
@@ -160,7 +161,7 @@ export interface SourceCode {
160
161
  lines: string[];
161
162
  hasBOM: boolean;
162
163
  parserServices: ESLintSourceCode.ParserServices;
163
- scopeManager: Scope.ScopeManager;
164
+ scopeManager: ScopeManager;
164
165
  visitorKeys: ESLintSourceCode.VisitorKeys;
165
166
  getText(node?: NodeOrToken, beforeCount?: number, afterCount?: number): string;
166
167
  getLines(): string[];
@@ -1,7 +1,7 @@
1
1
  import type { ASTNode, RuleContext, SourceCode } from "../types";
2
2
  import type { TSESTree } from "@typescript-eslint/types";
3
+ import type { Scope, Variable } from "@typescript-eslint/scope-manager";
3
4
  import type { AST as SvAST } from "svelte-eslint-parser";
4
- import type { Scope } from "eslint";
5
5
  export declare function equalTokens(left: ASTNode, right: ASTNode, sourceCode: SourceCode): boolean;
6
6
  export declare function getStringIfConstant(node: TSESTree.Expression | TSESTree.PrivateIdentifier): string | null;
7
7
  export declare function needParentheses(node: TSESTree.Expression, kind: "not" | "logical"): boolean;
@@ -29,10 +29,10 @@ export declare function findBindDirective<N extends string>(node: SvAST.SvelteEl
29
29
  }) | null;
30
30
  export declare function getStaticAttributeValue(node: SvAST.SvelteAttribute): string | null;
31
31
  export declare function getLangValue(node: SvAST.SvelteScriptElement | SvAST.SvelteStyleElement): string | null;
32
- export declare function findVariable(context: RuleContext, node: TSESTree.Identifier): Scope.Variable | null;
33
- export declare function getScope(context: RuleContext, currentNode: TSESTree.Node): Scope.Scope;
32
+ export declare function findVariable(context: RuleContext, node: TSESTree.Identifier): Variable | null;
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,19 +339,7 @@ function getAttributeValueRangeTokens(attr, sourceCode) {
339
339
  };
340
340
  }
341
341
  function getNodeName(node) {
342
- if ("name" in node.name) {
343
- return node.name.name;
344
- }
345
- let object = "";
346
- let currentObject = node.name.object;
347
- while ("object" in currentObject) {
348
- object = `${currentObject.property.name}.${object}`;
349
- currentObject = currentObject.object;
350
- }
351
- if ("name" in currentObject) {
352
- object = `${currentObject.name}.${object}`;
353
- }
354
- return object + node.name.property.name;
342
+ return getSimpleNameFromNode(node.name);
355
343
  }
356
344
  exports.getNodeName = getNodeName;
357
345
  function isVoidHtmlElement(node) {
@@ -394,3 +382,16 @@ function isExpressionIdentifier(node) {
394
382
  return true;
395
383
  }
396
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;
@@ -17,6 +17,7 @@ const max_attributes_per_line_1 = __importDefault(require("../rules/max-attribut
17
17
  const mustache_spacing_1 = __importDefault(require("../rules/mustache-spacing"));
18
18
  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
+ const no_dom_manipulating_1 = __importDefault(require("../rules/no-dom-manipulating"));
20
21
  const no_dupe_else_if_blocks_1 = __importDefault(require("../rules/no-dupe-else-if-blocks"));
21
22
  const no_dupe_style_properties_1 = __importDefault(require("../rules/no-dupe-style-properties"));
22
23
  const no_dynamic_slot_name_1 = __importDefault(require("../rules/no-dynamic-slot-name"));
@@ -63,6 +64,7 @@ exports.rules = [
63
64
  mustache_spacing_1.default,
64
65
  no_at_debug_tags_1.default,
65
66
  no_at_html_tags_1.default,
67
+ no_dom_manipulating_1.default,
66
68
  no_dupe_else_if_blocks_1.default,
67
69
  no_dupe_style_properties_1.default,
68
70
  no_dynamic_slot_name_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.12.0",
3
+ "version": "2.13.1",
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.20.0"
76
+ "svelte-eslint-parser": "^0.22.0"
77
77
  },
78
78
  "devDependencies": {
79
79
  "@1stg/browserslist-config": "^1.2.3",
@@ -174,7 +174,7 @@
174
174
  "access": "public"
175
175
  },
176
176
  "typeCoverage": {
177
- "atLeast": 98.72,
177
+ "atLeast": 99.04,
178
178
  "cache": true,
179
179
  "detail": true,
180
180
  "ignoreAsAssertion": true,