eslint-plugin-svelte 3.12.2 → 3.12.4

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
@@ -85,6 +85,9 @@ export default [
85
85
  // By doing so, some rules in eslint-plugin-svelte will automatically read the configuration and adjust their behavior accordingly.
86
86
  // While certain Svelte settings may be statically loaded from svelte.config.js even if you don’t specify it,
87
87
  // explicitly specifying it ensures better compatibility and functionality.
88
+ //
89
+ // If non-serializable properties are included, running ESLint with the --cache flag will fail.
90
+ // In that case, please remove the non-serializable properties. (e.g. `svelteConfig: { ...svelteConfig, kit: { ...svelteConfig.kit, typescript: undefined }}`)
88
91
  svelteConfig
89
92
  }
90
93
  }
@@ -143,6 +146,9 @@ export default ts.config(
143
146
  // By doing so, some rules in eslint-plugin-svelte will automatically read the configuration and adjust their behavior accordingly.
144
147
  // While certain Svelte settings may be statically loaded from svelte.config.js even if you don’t specify it,
145
148
  // explicitly specifying it ensures better compatibility and functionality.
149
+ //
150
+ // If non-serializable properties are included, running ESLint with the --cache flag will fail.
151
+ // In that case, please remove the non-serializable properties. (e.g. `svelteConfig: { ...svelteConfig, kit: { ...svelteConfig.kit, typescript: undefined }}`)
146
152
  svelteConfig
147
153
  }
148
154
  }
package/lib/main.d.ts CHANGED
@@ -14,7 +14,7 @@ export declare const configs: {
14
14
  export declare const rules: Record<string, Rule.RuleModule>;
15
15
  export declare const meta: {
16
16
  name: "eslint-plugin-svelte";
17
- version: "3.12.2";
17
+ version: "3.12.4";
18
18
  };
19
19
  export declare const processors: {
20
20
  '.svelte': typeof processor;
package/lib/meta.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export declare const name: "eslint-plugin-svelte";
2
- export declare const version: "3.12.2";
2
+ export declare const version: "3.12.4";
package/lib/meta.js CHANGED
@@ -2,4 +2,4 @@
2
2
  // This file has been automatically generated,
3
3
  // in order to update its content execute "pnpm run update"
4
4
  export const name = 'eslint-plugin-svelte';
5
- export const version = '3.12.2';
5
+ export const version = '3.12.4';
@@ -1,5 +1,5 @@
1
1
  import { createRule } from '../utils/index.js';
2
- import { findVariable, getAttributeValueQuoteAndRange, getStringIfConstant } from '../utils/ast-utils.js';
2
+ import { FindVariableContext, getAttributeValueQuoteAndRange, getStringIfConstant } from '../utils/ast-utils.js';
3
3
  export default createRule('no-dynamic-slot-name', {
4
4
  meta: {
5
5
  docs: {
@@ -56,16 +56,15 @@ export default createRule('no-dynamic-slot-name', {
56
56
  * Get static text from given expression
57
57
  */
58
58
  function getStaticText(node) {
59
- const expr = findRootExpression(node);
59
+ const expr = findRootExpression(new FindVariableContext(context), node);
60
60
  return getStringIfConstant(expr);
61
61
  }
62
62
  /** Find data expression */
63
- function findRootExpression(node, already = new Set()) {
64
- if (node.type !== 'Identifier' || already.has(node)) {
63
+ function findRootExpression(ctx, node) {
64
+ if (node.type !== 'Identifier') {
65
65
  return node;
66
66
  }
67
- already.add(node);
68
- const variable = findVariable(context, node);
67
+ const variable = ctx.findVariable(node);
69
68
  if (!variable || variable.defs.length !== 1) {
70
69
  return node;
71
70
  }
@@ -73,7 +72,7 @@ export default createRule('no-dynamic-slot-name', {
73
72
  if (def.type === 'Variable') {
74
73
  if (def.parent.kind === 'const' && def.node.init) {
75
74
  const init = def.node.init;
76
- return findRootExpression(init, already);
75
+ return findRootExpression(ctx, init);
77
76
  }
78
77
  }
79
78
  return node;
@@ -1,5 +1,5 @@
1
1
  import { createRule } from '../utils/index.js';
2
- import { findVariable, iterateIdentifiers } from '../utils/ast-utils.js';
2
+ import { FindVariableContext, iterateIdentifiers } from '../utils/ast-utils.js';
3
3
  export default createRule('no-immutable-reactive-statements', {
4
4
  meta: {
5
5
  docs: {
@@ -81,7 +81,7 @@ export default createRule('no-immutable-reactive-statements', {
81
81
  return true;
82
82
  }
83
83
  }
84
- return hasWrite(variable);
84
+ return hasWrite(new FindVariableContext(context), variable);
85
85
  }
86
86
  return false;
87
87
  });
@@ -89,7 +89,7 @@ export default createRule('no-immutable-reactive-statements', {
89
89
  return isMutableDefine;
90
90
  }
91
91
  /** Checks whether the given variable has a write or reactive store reference or not. */
92
- function hasWrite(variable) {
92
+ function hasWrite(ctx, variable) {
93
93
  const defIds = variable.defs.map((def) => def.name);
94
94
  for (const reference of variable.references) {
95
95
  if (reference.isWrite() &&
@@ -97,14 +97,14 @@ export default createRule('no-immutable-reactive-statements', {
97
97
  reference.identifier.range[1] <= defId.range[1])) {
98
98
  return true;
99
99
  }
100
- if (hasWriteMember(reference.identifier)) {
100
+ if (hasWriteMember(ctx, reference.identifier)) {
101
101
  return true;
102
102
  }
103
103
  }
104
104
  return false;
105
105
  }
106
106
  /** Checks whether the given expression has writing to a member or not. */
107
- function hasWriteMember(expr) {
107
+ function hasWriteMember(ctx, expr) {
108
108
  if (expr.type === 'JSXIdentifier')
109
109
  return false;
110
110
  const parent = expr.parent;
@@ -118,21 +118,23 @@ export default createRule('no-immutable-reactive-statements', {
118
118
  return parent.operator === 'delete' && parent.argument === expr;
119
119
  }
120
120
  if (parent.type === 'MemberExpression') {
121
- return parent.object === expr && hasWriteMember(parent);
121
+ return parent.object === expr && hasWriteMember(ctx, parent);
122
122
  }
123
123
  if (parent.type === 'SvelteDirective') {
124
124
  return parent.kind === 'Binding' && parent.expression === expr;
125
125
  }
126
126
  if (parent.type === 'SvelteEachBlock') {
127
- return (parent.context !== null && parent.expression === expr && hasWriteReference(parent.context));
127
+ return (parent.context !== null &&
128
+ parent.expression === expr &&
129
+ hasWriteReference(ctx, parent.context));
128
130
  }
129
131
  return false;
130
132
  }
131
133
  /** Checks whether the given pattern has writing or not. */
132
- function hasWriteReference(pattern) {
134
+ function hasWriteReference(ctx, pattern) {
133
135
  for (const id of iterateIdentifiers(pattern)) {
134
- const variable = findVariable(context, id);
135
- if (variable && hasWrite(variable))
136
+ const variable = ctx.findVariable(id);
137
+ if (variable && hasWrite(ctx, variable))
136
138
  return true;
137
139
  }
138
140
  return false;
@@ -1,5 +1,6 @@
1
1
  import { createRule } from '../utils/index.js';
2
2
  import { ReferenceTracker } from '@eslint-community/eslint-utils';
3
+ import { FindVariableContext } from '../utils/ast-utils.js';
3
4
  import { findVariable } from '../utils/ast-utils.js';
4
5
  export default createRule('no-navigation-without-resolve', {
5
6
  meta: {
@@ -74,12 +75,12 @@ export default createRule('no-navigation-without-resolve', {
74
75
  return;
75
76
  }
76
77
  if ((node.value[0].type === 'SvelteLiteral' &&
77
- !expressionIsAbsolute(node.value[0]) &&
78
- !expressionIsFragment(node.value[0])) ||
78
+ !expressionIsAbsolute(new FindVariableContext(context), node.value[0]) &&
79
+ !expressionIsFragment(new FindVariableContext(context), node.value[0])) ||
79
80
  (node.value[0].type === 'SvelteMustacheTag' &&
80
- !expressionIsAbsolute(node.value[0].expression) &&
81
- !expressionIsFragment(node.value[0].expression) &&
82
- !isResolveCall(context, node.value[0].expression, resolveReferences))) {
81
+ !expressionIsAbsolute(new FindVariableContext(context), node.value[0].expression) &&
82
+ !expressionIsFragment(new FindVariableContext(context), node.value[0].expression) &&
83
+ !isResolveCall(new FindVariableContext(context), node.value[0].expression, resolveReferences))) {
83
84
  context.report({ loc: node.value[0].loc, messageId: 'linkWithoutResolve' });
84
85
  }
85
86
  }
@@ -149,7 +150,7 @@ function checkGotoCall(context, call, resolveReferences) {
149
150
  return;
150
151
  }
151
152
  const url = call.arguments[0];
152
- if (!isResolveCall(context, url, resolveReferences)) {
153
+ if (!isResolveCall(new FindVariableContext(context), url, resolveReferences)) {
153
154
  context.report({ loc: url.loc, messageId: 'gotoWithoutResolve' });
154
155
  }
155
156
  }
@@ -158,12 +159,13 @@ function checkShallowNavigationCall(context, call, resolveReferences, messageId)
158
159
  return;
159
160
  }
160
161
  const url = call.arguments[0];
161
- if (!expressionIsEmpty(url) && !isResolveCall(context, url, resolveReferences)) {
162
+ if (!expressionIsEmpty(url) &&
163
+ !isResolveCall(new FindVariableContext(context), url, resolveReferences)) {
162
164
  context.report({ loc: url.loc, messageId });
163
165
  }
164
166
  }
165
167
  // Helper functions
166
- function isResolveCall(context, node, resolveReferences) {
168
+ function isResolveCall(ctx, node, resolveReferences) {
167
169
  if (node.type === 'CallExpression' &&
168
170
  ((node.callee.type === 'Identifier' && resolveReferences.has(node.callee)) ||
169
171
  (node.callee.type === 'MemberExpression' &&
@@ -171,17 +173,17 @@ function isResolveCall(context, node, resolveReferences) {
171
173
  resolveReferences.has(node.callee.property)))) {
172
174
  return true;
173
175
  }
174
- if (node.type === 'Identifier') {
175
- const variable = findVariable(context, node);
176
- if (variable !== null &&
177
- variable.identifiers.length > 0 &&
178
- variable.identifiers[0].parent.type === 'VariableDeclarator' &&
179
- variable.identifiers[0].parent.init !== null &&
180
- isResolveCall(context, variable.identifiers[0].parent.init, resolveReferences)) {
181
- return true;
182
- }
176
+ if (node.type !== 'Identifier') {
177
+ return false;
178
+ }
179
+ const variable = ctx.findVariable(node);
180
+ if (variable === null ||
181
+ variable.identifiers.length === 0 ||
182
+ variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
183
+ variable.identifiers[0].parent.init === null) {
184
+ return false;
183
185
  }
184
- return false;
186
+ return isResolveCall(ctx, variable.identifiers[0].parent.init, resolveReferences);
185
187
  }
186
188
  function expressionIsEmpty(url) {
187
189
  return ((url.type === 'Literal' && url.value === '') ||
@@ -190,50 +192,74 @@ function expressionIsEmpty(url) {
190
192
  url.quasis.length === 1 &&
191
193
  url.quasis[0].value.raw === ''));
192
194
  }
193
- function expressionIsAbsolute(url) {
195
+ function expressionIsAbsolute(ctx, url) {
194
196
  switch (url.type) {
195
197
  case 'BinaryExpression':
196
- return binaryExpressionIsAbsolute(url);
198
+ return binaryExpressionIsAbsolute(ctx, url);
199
+ case 'Identifier':
200
+ return identifierIsAbsolute(ctx, url);
197
201
  case 'Literal':
198
202
  return typeof url.value === 'string' && urlValueIsAbsolute(url.value);
199
203
  case 'SvelteLiteral':
200
204
  return urlValueIsAbsolute(url.value);
201
205
  case 'TemplateLiteral':
202
- return templateLiteralIsAbsolute(url);
206
+ return templateLiteralIsAbsolute(ctx, url);
203
207
  default:
204
208
  return false;
205
209
  }
206
210
  }
207
- function binaryExpressionIsAbsolute(url) {
208
- return ((url.left.type !== 'PrivateIdentifier' && expressionIsAbsolute(url.left)) ||
209
- expressionIsAbsolute(url.right));
211
+ function binaryExpressionIsAbsolute(ctx, url) {
212
+ return ((url.left.type !== 'PrivateIdentifier' && expressionIsAbsolute(ctx, url.left)) ||
213
+ expressionIsAbsolute(ctx, url.right));
214
+ }
215
+ function identifierIsAbsolute(ctx, url) {
216
+ const variable = ctx.findVariable(url);
217
+ if (variable === null ||
218
+ variable.identifiers.length === 0 ||
219
+ variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
220
+ variable.identifiers[0].parent.init === null) {
221
+ return false;
222
+ }
223
+ return expressionIsAbsolute(ctx, variable.identifiers[0].parent.init);
210
224
  }
211
- function templateLiteralIsAbsolute(url) {
212
- return (url.expressions.some(expressionIsAbsolute) ||
225
+ function templateLiteralIsAbsolute(ctx, url) {
226
+ return (url.expressions.some((expression) => expressionIsAbsolute(ctx, expression)) ||
213
227
  url.quasis.some((quasi) => urlValueIsAbsolute(quasi.value.raw)));
214
228
  }
215
229
  function urlValueIsAbsolute(url) {
216
230
  return /^[+a-z]*:/i.test(url);
217
231
  }
218
- function expressionIsFragment(url) {
232
+ function expressionIsFragment(ctx, url) {
219
233
  switch (url.type) {
220
234
  case 'BinaryExpression':
221
- return binaryExpressionIsFragment(url);
235
+ return binaryExpressionIsFragment(ctx, url);
236
+ case 'Identifier':
237
+ return identifierIsFragment(ctx, url);
222
238
  case 'Literal':
223
239
  return typeof url.value === 'string' && urlValueIsFragment(url.value);
224
240
  case 'SvelteLiteral':
225
241
  return urlValueIsFragment(url.value);
226
242
  case 'TemplateLiteral':
227
- return templateLiteralIsFragment(url);
243
+ return templateLiteralIsFragment(ctx, url);
228
244
  default:
229
245
  return false;
230
246
  }
231
247
  }
232
- function binaryExpressionIsFragment(url) {
233
- return url.left.type !== 'PrivateIdentifier' && expressionIsFragment(url.left);
248
+ function binaryExpressionIsFragment(ctx, url) {
249
+ return url.left.type !== 'PrivateIdentifier' && expressionIsFragment(ctx, url.left);
250
+ }
251
+ function identifierIsFragment(ctx, url) {
252
+ const variable = ctx.findVariable(url);
253
+ if (variable === null ||
254
+ variable.identifiers.length === 0 ||
255
+ variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
256
+ variable.identifiers[0].parent.init === null) {
257
+ return false;
258
+ }
259
+ return expressionIsFragment(ctx, variable.identifiers[0].parent.init);
234
260
  }
235
- function templateLiteralIsFragment(url) {
236
- return ((url.expressions.length >= 1 && expressionIsFragment(url.expressions[0])) ||
261
+ function templateLiteralIsFragment(ctx, url) {
262
+ return ((url.expressions.length >= 1 && expressionIsFragment(ctx, url.expressions[0])) ||
237
263
  (url.quasis.length >= 1 && urlValueIsFragment(url.quasis[0].value.raw)));
238
264
  }
239
265
  function urlValueIsFragment(url) {
@@ -1,6 +1,6 @@
1
1
  import { createRule } from '../utils/index.js';
2
- import { findVariable } from '../utils/ast-utils.js';
3
2
  import { EVENT_NAMES } from '../utils/events.js';
3
+ import { FindVariableContext } from '../utils/ast-utils.js';
4
4
  const PHRASES = {
5
5
  ObjectExpression: 'object',
6
6
  ArrayExpression: 'array',
@@ -34,12 +34,11 @@ export default createRule('no-not-function-handler', {
34
34
  },
35
35
  create(context) {
36
36
  /** Find data expression */
37
- function findRootExpression(node, already = new Set()) {
38
- if (node.type !== 'Identifier' || already.has(node)) {
37
+ function findRootExpression(ctx, node) {
38
+ if (node.type !== 'Identifier') {
39
39
  return node;
40
40
  }
41
- already.add(node);
42
- const variable = findVariable(context, node);
41
+ const variable = ctx.findVariable(node);
43
42
  if (!variable || variable.defs.length !== 1) {
44
43
  return node;
45
44
  }
@@ -47,7 +46,7 @@ export default createRule('no-not-function-handler', {
47
46
  if (def.type === 'Variable') {
48
47
  if (def.parent.kind === 'const' && def.node.init) {
49
48
  const init = def.node.init;
50
- return findRootExpression(init, already);
49
+ return findRootExpression(ctx, init);
51
50
  }
52
51
  }
53
52
  return node;
@@ -57,7 +56,7 @@ export default createRule('no-not-function-handler', {
57
56
  if (!node) {
58
57
  return;
59
58
  }
60
- const expression = findRootExpression(node);
59
+ const expression = findRootExpression(new FindVariableContext(context), node);
61
60
  if (expression.type !== 'ObjectExpression' &&
62
61
  expression.type !== 'ArrayExpression' &&
63
62
  expression.type !== 'ClassExpression' &&
@@ -331,12 +331,23 @@ export default createRule('no-top-level-browser-globals', {
331
331
  const end = pp.range[1];
332
332
  return (n) => start <= n.range[0] && n.range[1] <= end;
333
333
  }
334
- if (!guardInfo.not &&
335
- parent.type === 'LogicalExpression' &&
336
- parent.operator === '&&' &&
337
- parent.left === guardInfo.node) {
338
- const block = parent.right;
339
- return (n) => block.range[0] <= n.range[0] && n.range[1] <= block.range[1];
334
+ if (parent.type === 'LogicalExpression') {
335
+ if (!guardInfo.not && parent.operator === '&&') {
336
+ const parentChecker = getGuardChecker({ not: guardInfo.not, node: parent });
337
+ if (parent.left === guardInfo.node) {
338
+ const block = parent.right;
339
+ return (n) => {
340
+ if (parentChecker?.(n)) {
341
+ return true;
342
+ }
343
+ return block.range[0] <= n.range[0] && n.range[1] <= block.range[1];
344
+ };
345
+ }
346
+ return parentChecker;
347
+ }
348
+ if (guardInfo.not && parent.operator === '||') {
349
+ return getGuardChecker({ not: guardInfo.not, node: parent });
350
+ }
340
351
  }
341
352
  return null;
342
353
  }
@@ -2,6 +2,7 @@ import { createRule } from '../utils/index.js';
2
2
  import { getTypeScriptTools, isAnyType } from '../utils/ts-utils/index.js';
3
3
  import { findVariable } from '../utils/ast-utils.js';
4
4
  import { toRegExp } from '../utils/regexp.js';
5
+ import { normalize } from 'path';
5
6
  let isRemovedWarningShown = false;
6
7
  export default createRule('no-unused-props', {
7
8
  meta: {
@@ -100,7 +101,8 @@ export default createRule('no-unused-props', {
100
101
  const declarations = symbol.getDeclarations();
101
102
  if (!declarations || declarations.length === 0)
102
103
  return false;
103
- return declarations.every((decl) => decl.getSourceFile().fileName === fileName);
104
+ // TypeScript declaration file name is normalized to support Windows style paths
105
+ return declarations.every((decl) => normalize(decl.getSourceFile().fileName) === fileName);
104
106
  }
105
107
  /**
106
108
  * Extracts property paths from member expressions.
@@ -1,4 +1,5 @@
1
1
  import { createRule } from '../utils/index.js';
2
+ import path from 'path';
2
3
  export default createRule('valid-style-parse', {
3
4
  meta: {
4
5
  docs: {
@@ -15,14 +16,19 @@ export default createRule('valid-style-parse', {
15
16
  if (!sourceCode.parserServices.isSvelte) {
16
17
  return {};
17
18
  }
18
- const cwd = `${context.cwd ?? process.cwd()}/`;
19
+ const cwd = `${context.cwd ?? process.cwd()}${path.sep}`;
19
20
  return {
20
21
  SvelteStyleElement(node) {
21
22
  const styleContext = sourceCode.parserServices.getStyleContext();
22
23
  if (styleContext.status === 'parse-error') {
24
+ // This will replace backslashes to forward slashes only
25
+ // if Node.js reports Windows style path separators
26
+ let message = styleContext.error.message.replace(cwd, '');
27
+ if (path.sep === '\\')
28
+ message = message.replace(/\\/g, '/');
23
29
  context.report({
24
30
  loc: node.loc,
25
- message: `Error parsing style element. Error message: "${styleContext.error.message.replace(cwd, '')}"`
31
+ message: `Error parsing style element. Error message: "${message}"`
26
32
  });
27
33
  }
28
34
  if (styleContext.status === 'unknown-lang') {
@@ -62,6 +62,17 @@ export declare function getLangValue(node: SvAST.SvelteScriptElement | SvAST.Sve
62
62
  * Find the variable of a given name.
63
63
  */
64
64
  export declare function findVariable(context: RuleContext, node: TSESTree.Identifier): Variable | null;
65
+ /**
66
+ * Context for safely finding variables, avoiding infinite recursion.
67
+ * This should be used when the caller function may be called recursively, instead of `findVariable()`.
68
+ *
69
+ * Create an instance of this class at the top of the call stack where you want to start searching for identifiers,
70
+ * and then use it within the recursion.
71
+ */
72
+ export declare class FindVariableContext {
73
+ readonly findVariable: (node: TSESTree.Identifier) => Variable | null;
74
+ constructor(context: RuleContext);
75
+ }
65
76
  /**
66
77
  * Iterate the identifiers of a given pattern node.
67
78
  */
@@ -172,6 +172,25 @@ export function findVariable(context, node) {
172
172
  // Remove the $ and search for the variable again, as it may be a store access variable.
173
173
  return eslintUtils.findVariable(initialScope, node.name.slice(1));
174
174
  }
175
+ /**
176
+ * Context for safely finding variables, avoiding infinite recursion.
177
+ * This should be used when the caller function may be called recursively, instead of `findVariable()`.
178
+ *
179
+ * Create an instance of this class at the top of the call stack where you want to start searching for identifiers,
180
+ * and then use it within the recursion.
181
+ */
182
+ export class FindVariableContext {
183
+ constructor(context) {
184
+ const visited = new Set();
185
+ this.findVariable = (node) => {
186
+ if (visited.has(node)) {
187
+ return null;
188
+ }
189
+ visited.add(node);
190
+ return findVariable(context, node);
191
+ };
192
+ }
193
+ }
175
194
  /**
176
195
  * Iterate the identifiers of a given pattern node.
177
196
  */
@@ -1,6 +1,15 @@
1
- import { findVariable } from './ast-utils.js';
2
- // Variable prefix extraction
1
+ import { FindVariableContext } from './ast-utils.js';
3
2
  export function extractExpressionPrefixVariable(context, expression) {
3
+ return extractExpressionPrefixVariableInternal(new FindVariableContext(context), expression);
4
+ }
5
+ export function extractExpressionPrefixLiteral(context, expression) {
6
+ return extractExpressionPrefixLiteralInternal(new FindVariableContext(context), expression);
7
+ }
8
+ export function extractExpressionSuffixLiteral(context, expression) {
9
+ return extractExpressionSuffixLiteralInternal(new FindVariableContext(context), expression);
10
+ }
11
+ // Variable prefix extraction
12
+ function extractExpressionPrefixVariableInternal(context, expression) {
4
13
  switch (expression.type) {
5
14
  case 'BinaryExpression':
6
15
  return extractBinaryExpressionPrefixVariable(context, expression);
@@ -16,18 +25,19 @@ export function extractExpressionPrefixVariable(context, expression) {
16
25
  }
17
26
  function extractBinaryExpressionPrefixVariable(context, expression) {
18
27
  return expression.left.type !== 'PrivateIdentifier'
19
- ? extractExpressionPrefixVariable(context, expression.left)
28
+ ? extractExpressionPrefixVariableInternal(context, expression.left)
20
29
  : null;
21
30
  }
22
31
  function extractVariablePrefixVariable(context, expression) {
23
- const variable = findVariable(context, expression);
32
+ const variable = context.findVariable(expression);
24
33
  if (variable === null ||
25
34
  variable.identifiers.length !== 1 ||
26
35
  variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
27
36
  variable.identifiers[0].parent.init === null) {
28
37
  return expression;
29
38
  }
30
- return (extractExpressionPrefixVariable(context, variable.identifiers[0].parent.init) ?? expression);
39
+ return (extractExpressionPrefixVariableInternal(context, variable.identifiers[0].parent.init) ??
40
+ expression);
31
41
  }
32
42
  function extractMemberExpressionPrefixVariable(expression) {
33
43
  return expression.property.type === 'Identifier' ? expression.property : null;
@@ -40,14 +50,14 @@ function extractTemplateLiteralPrefixVariable(context, expression) {
40
50
  continue;
41
51
  }
42
52
  if (part.type !== 'TemplateElement') {
43
- return extractExpressionPrefixVariable(context, part);
53
+ return extractExpressionPrefixVariableInternal(context, part);
44
54
  }
45
55
  return null;
46
56
  }
47
57
  return null;
48
58
  }
49
59
  // Literal prefix extraction
50
- export function extractExpressionPrefixLiteral(context, expression) {
60
+ function extractExpressionPrefixLiteralInternal(context, expression) {
51
61
  switch (expression.type) {
52
62
  case 'BinaryExpression':
53
63
  return extractBinaryExpressionPrefixLiteral(context, expression);
@@ -65,18 +75,18 @@ export function extractExpressionPrefixLiteral(context, expression) {
65
75
  }
66
76
  function extractBinaryExpressionPrefixLiteral(context, expression) {
67
77
  return expression.left.type !== 'PrivateIdentifier'
68
- ? extractExpressionPrefixLiteral(context, expression.left)
78
+ ? extractExpressionPrefixLiteralInternal(context, expression.left)
69
79
  : null;
70
80
  }
71
81
  function extractVariablePrefixLiteral(context, expression) {
72
- const variable = findVariable(context, expression);
82
+ const variable = context.findVariable(expression);
73
83
  if (variable === null ||
74
84
  variable.identifiers.length !== 1 ||
75
85
  variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
76
86
  variable.identifiers[0].parent.init === null) {
77
87
  return null;
78
88
  }
79
- return extractExpressionPrefixLiteral(context, variable.identifiers[0].parent.init);
89
+ return extractExpressionPrefixLiteralInternal(context, variable.identifiers[0].parent.init);
80
90
  }
81
91
  function extractTemplateLiteralPrefixLiteral(context, expression) {
82
92
  const literalParts = [...expression.expressions, ...expression.quasis].sort((a, b) => a.range[0] < b.range[0] ? -1 : 1);
@@ -88,12 +98,12 @@ function extractTemplateLiteralPrefixLiteral(context, expression) {
88
98
  }
89
99
  return part.value.raw;
90
100
  }
91
- return extractExpressionPrefixLiteral(context, part);
101
+ return extractExpressionPrefixLiteralInternal(context, part);
92
102
  }
93
103
  return null;
94
104
  }
95
105
  // Literal suffix extraction
96
- export function extractExpressionSuffixLiteral(context, expression) {
106
+ function extractExpressionSuffixLiteralInternal(context, expression) {
97
107
  switch (expression.type) {
98
108
  case 'BinaryExpression':
99
109
  return extractBinaryExpressionSuffixLiteral(context, expression);
@@ -110,17 +120,17 @@ export function extractExpressionSuffixLiteral(context, expression) {
110
120
  }
111
121
  }
112
122
  function extractBinaryExpressionSuffixLiteral(context, expression) {
113
- return extractExpressionSuffixLiteral(context, expression.right);
123
+ return extractExpressionSuffixLiteralInternal(context, expression.right);
114
124
  }
115
125
  function extractVariableSuffixLiteral(context, expression) {
116
- const variable = findVariable(context, expression);
126
+ const variable = context.findVariable(expression);
117
127
  if (variable === null ||
118
128
  variable.identifiers.length !== 1 ||
119
129
  variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
120
130
  variable.identifiers[0].parent.init === null) {
121
131
  return null;
122
132
  }
123
- return extractExpressionSuffixLiteral(context, variable.identifiers[0].parent.init);
133
+ return extractExpressionSuffixLiteralInternal(context, variable.identifiers[0].parent.init);
124
134
  }
125
135
  function extractTemplateLiteralSuffixLiteral(context, expression) {
126
136
  const literalParts = [...expression.expressions, ...expression.quasis].sort((a, b) => a.range[0] < b.range[0] ? -1 : 1);
@@ -132,7 +142,7 @@ function extractTemplateLiteralSuffixLiteral(context, expression) {
132
142
  }
133
143
  return part.value.raw;
134
144
  }
135
- return extractExpressionSuffixLiteral(context, part);
145
+ return extractExpressionSuffixLiteralInternal(context, part);
136
146
  }
137
147
  return null;
138
148
  }
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "eslint-plugin-svelte",
3
- "version": "3.12.2",
3
+ "version": "3.12.4",
4
4
  "description": "ESLint plugin for Svelte using AST",
5
- "repository": "git+https://github.com/sveltejs/eslint-plugin-svelte.git",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/sveltejs/eslint-plugin-svelte.git",
8
+ "directory": "packages/eslint-plugin-svelte"
9
+ },
6
10
  "homepage": "https://sveltejs.github.io/eslint-plugin-svelte",
7
11
  "author": "Yosuke Ota (https://github.com/ota-meshi)",
8
12
  "funding": "https://github.com/sponsors/ota-meshi",
@@ -58,6 +62,8 @@
58
62
  "@types/postcss-safe-parser": "^5.0.4",
59
63
  "@types/semver": "^7.7.0",
60
64
  "@types/stylus": "^0.48.43",
65
+ "@typescript-eslint/scope-manager": "^8.43.0",
66
+ "@typescript-eslint/types": "^8.43.0",
61
67
  "acorn": "^8.15.0",
62
68
  "assert": "^2.1.0",
63
69
  "esbuild": "^0.25.9",
@@ -65,6 +71,7 @@
65
71
  "eslint-typegen": "^2.3.0",
66
72
  "eslint-visitor-keys": "^4.2.1",
67
73
  "espree": "^10.4.0",
74
+ "jiti": "^2.5.1",
68
75
  "less": "^4.4.1",
69
76
  "mocha": "~11.7.2",
70
77
  "postcss-nested": "^7.0.2",