Skip to content

Commit 9e9fe1b

Browse files
committed
fix(no-navigation-without-resolve): properly detecting absolute and fragment URLs in variables
1 parent 358fff7 commit 9e9fe1b

File tree

2 files changed

+60
-19
lines changed

2 files changed

+60
-19
lines changed

.changeset/hungry-rats-arrive.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-svelte': patch
3+
---
4+
5+
fix(no-navigation-without-resolve): properly detecting absolute and fragment URLs in variables

packages/eslint-plugin-svelte/src/rules/no-navigation-without-resolve.ts

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,11 @@ export default createRule('no-navigation-without-resolve', {
9696
}
9797
if (
9898
(node.value[0].type === 'SvelteLiteral' &&
99-
!expressionIsAbsolute(node.value[0]) &&
100-
!expressionIsFragment(node.value[0])) ||
99+
!expressionIsAbsolute(node.value[0], context) &&
100+
!expressionIsFragment(node.value[0], context)) ||
101101
(node.value[0].type === 'SvelteMustacheTag' &&
102-
!expressionIsAbsolute(node.value[0].expression) &&
103-
!expressionIsFragment(node.value[0].expression) &&
102+
!expressionIsAbsolute(node.value[0].expression, context) &&
103+
!expressionIsFragment(node.value[0].expression, context) &&
104104
!isResolveCall(context, node.value[0].expression, resolveReferences))
105105
) {
106106
context.report({ loc: node.value[0].loc, messageId: 'linkWithoutResolve' });
@@ -252,31 +252,49 @@ function expressionIsEmpty(url: TSESTree.CallExpressionArgument): boolean {
252252
);
253253
}
254254

255-
function expressionIsAbsolute(url: AST.SvelteLiteral | TSESTree.Expression): boolean {
255+
function expressionIsAbsolute(
256+
url: AST.SvelteLiteral | TSESTree.Expression,
257+
context: RuleContext
258+
): boolean {
256259
switch (url.type) {
257260
case 'BinaryExpression':
258-
return binaryExpressionIsAbsolute(url);
261+
return binaryExpressionIsAbsolute(url, context);
262+
case 'Identifier':
263+
return identifierIsAbsolute(url, context);
259264
case 'Literal':
260265
return typeof url.value === 'string' && urlValueIsAbsolute(url.value);
261266
case 'SvelteLiteral':
262267
return urlValueIsAbsolute(url.value);
263268
case 'TemplateLiteral':
264-
return templateLiteralIsAbsolute(url);
269+
return templateLiteralIsAbsolute(url, context);
265270
default:
266271
return false;
267272
}
268273
}
269274

270-
function binaryExpressionIsAbsolute(url: TSESTree.BinaryExpression): boolean {
275+
function binaryExpressionIsAbsolute(url: TSESTree.BinaryExpression, context: RuleContext): boolean {
271276
return (
272-
(url.left.type !== 'PrivateIdentifier' && expressionIsAbsolute(url.left)) ||
273-
expressionIsAbsolute(url.right)
277+
(url.left.type !== 'PrivateIdentifier' && expressionIsAbsolute(url.left, context)) ||
278+
expressionIsAbsolute(url.right, context)
274279
);
275280
}
276281

277-
function templateLiteralIsAbsolute(url: TSESTree.TemplateLiteral): boolean {
282+
function identifierIsAbsolute(url: TSESTree.Identifier, context: RuleContext): boolean {
283+
const variable = findVariable(context, url);
284+
if (
285+
variable === null ||
286+
variable.identifiers.length === 0 ||
287+
variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
288+
variable.identifiers[0].parent.init === null
289+
) {
290+
return false;
291+
}
292+
return expressionIsAbsolute(variable.identifiers[0].parent.init, context);
293+
}
294+
295+
function templateLiteralIsAbsolute(url: TSESTree.TemplateLiteral, context: RuleContext): boolean {
278296
return (
279-
url.expressions.some(expressionIsAbsolute) ||
297+
url.expressions.some((expression) => expressionIsAbsolute(expression, context)) ||
280298
url.quasis.some((quasi) => urlValueIsAbsolute(quasi.value.raw))
281299
);
282300
}
@@ -285,28 +303,46 @@ function urlValueIsAbsolute(url: string): boolean {
285303
return /^[+a-z]*:/i.test(url);
286304
}
287305

288-
function expressionIsFragment(url: AST.SvelteLiteral | TSESTree.Expression): boolean {
306+
function expressionIsFragment(
307+
url: AST.SvelteLiteral | TSESTree.Expression,
308+
context: RuleContext
309+
): boolean {
289310
switch (url.type) {
290311
case 'BinaryExpression':
291-
return binaryExpressionIsFragment(url);
312+
return binaryExpressionIsFragment(url, context);
313+
case 'Identifier':
314+
return identifierIsFragment(url, context);
292315
case 'Literal':
293316
return typeof url.value === 'string' && urlValueIsFragment(url.value);
294317
case 'SvelteLiteral':
295318
return urlValueIsFragment(url.value);
296319
case 'TemplateLiteral':
297-
return templateLiteralIsFragment(url);
320+
return templateLiteralIsFragment(url, context);
298321
default:
299322
return false;
300323
}
301324
}
302325

303-
function binaryExpressionIsFragment(url: TSESTree.BinaryExpression): boolean {
304-
return url.left.type !== 'PrivateIdentifier' && expressionIsFragment(url.left);
326+
function binaryExpressionIsFragment(url: TSESTree.BinaryExpression, context: RuleContext): boolean {
327+
return url.left.type !== 'PrivateIdentifier' && expressionIsFragment(url.left, context);
328+
}
329+
330+
function identifierIsFragment(url: TSESTree.Identifier, context: RuleContext): boolean {
331+
const variable = findVariable(context, url);
332+
if (
333+
variable === null ||
334+
variable.identifiers.length === 0 ||
335+
variable.identifiers[0].parent.type !== 'VariableDeclarator' ||
336+
variable.identifiers[0].parent.init === null
337+
) {
338+
return false;
339+
}
340+
return expressionIsFragment(variable.identifiers[0].parent.init, context);
305341
}
306342

307-
function templateLiteralIsFragment(url: TSESTree.TemplateLiteral): boolean {
343+
function templateLiteralIsFragment(url: TSESTree.TemplateLiteral, context: RuleContext): boolean {
308344
return (
309-
(url.expressions.length >= 1 && expressionIsFragment(url.expressions[0])) ||
345+
(url.expressions.length >= 1 && expressionIsFragment(url.expressions[0], context)) ||
310346
(url.quasis.length >= 1 && urlValueIsFragment(url.quasis[0].value.raw))
311347
);
312348
}

0 commit comments

Comments
 (0)