diff --git a/.changeset/icy-planets-know.md b/.changeset/icy-planets-know.md new file mode 100644 index 000000000..d32303d87 --- /dev/null +++ b/.changeset/icy-planets-know.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-svelte': minor +--- + +feat(no-navigation-without-resolve): checking link shorthand attributes diff --git a/packages/eslint-plugin-svelte/src/rules/no-navigation-without-resolve.ts b/packages/eslint-plugin-svelte/src/rules/no-navigation-without-resolve.ts index 0beb2aa71..bd1e49f61 100644 --- a/packages/eslint-plugin-svelte/src/rules/no-navigation-without-resolve.ts +++ b/packages/eslint-plugin-svelte/src/rules/no-navigation-without-resolve.ts @@ -84,6 +84,26 @@ export default createRule('no-navigation-without-resolve', { } } }, + SvelteShorthandAttribute(node) { + if ( + context.options[0]?.ignoreLinks === true || + node.parent.parent.type !== 'SvelteElement' || + node.parent.parent.kind !== 'html' || + node.parent.parent.name.type !== 'SvelteName' || + node.parent.parent.name.name !== 'a' || + node.key.name !== 'href' || + node.value.type !== 'Identifier' + ) { + return; + } + if ( + !expressionIsAbsolute(new FindVariableContext(context), node.value) && + !expressionIsFragment(new FindVariableContext(context), node.value) && + !isResolveCall(new FindVariableContext(context), node.value, resolveReferences) + ) { + context.report({ loc: node.loc, messageId: 'linkWithoutResolve' }); + } + }, SvelteAttribute(node) { if ( context.options[0]?.ignoreLinks === true || diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-partial-resolve01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-partial-resolve01-errors.yaml index c9996ac7f..2049a0dbf 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-partial-resolve01-errors.yaml +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-partial-resolve01-errors.yaml @@ -1,12 +1,16 @@ - message: Found a link with a url that isn't resolved. - line: 7 + line: 8 column: 9 suggestions: null - message: Found a link with a url that isn't resolved. - line: 8 + line: 9 column: 9 suggestions: null - message: Found a link with a url that isn't resolved. - line: 9 + line: 10 column: 9 suggestions: null +- message: Found a link with a url that isn't resolved. + line: 11 + column: 4 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-partial-resolve01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-partial-resolve01-input.svelte index 6994a2cb1..661e8c14e 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-partial-resolve01-input.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-partial-resolve01-input.svelte @@ -2,8 +2,10 @@ import { resolve } from '$app/paths'; const value = resolve('/foo') + '/bar'; + const href = resolve('/foo') + '/bar'; Click me! Click me! Click me! +Click me! diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-with-fragment01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-with-fragment01-errors.yaml index f6888e8c1..f5adbd301 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-with-fragment01-errors.yaml +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-with-fragment01-errors.yaml @@ -1,10 +1,6 @@ -- message: Found a link with a url that isn't resolved. - line: 5 - column: 10 - suggestions: null - message: Found a link with a url that isn't resolved. line: 6 - column: 9 + column: 10 suggestions: null - message: Found a link with a url that isn't resolved. line: 7 @@ -18,3 +14,11 @@ line: 9 column: 9 suggestions: null +- message: Found a link with a url that isn't resolved. + line: 10 + column: 4 + suggestions: null +- message: Found a link with a url that isn't resolved. + line: 11 + column: 9 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-with-fragment01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-with-fragment01-input.svelte index 2a2d1d418..8e955d59a 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-with-fragment01-input.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-with-fragment01-input.svelte @@ -1,9 +1,11 @@ Click me! Click me! Click me! Click me! +Click me! Click me! diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-without-resolve01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-without-resolve01-errors.yaml index f6888e8c1..f5adbd301 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-without-resolve01-errors.yaml +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-without-resolve01-errors.yaml @@ -1,10 +1,6 @@ -- message: Found a link with a url that isn't resolved. - line: 5 - column: 10 - suggestions: null - message: Found a link with a url that isn't resolved. line: 6 - column: 9 + column: 10 suggestions: null - message: Found a link with a url that isn't resolved. line: 7 @@ -18,3 +14,11 @@ line: 9 column: 9 suggestions: null +- message: Found a link with a url that isn't resolved. + line: 10 + column: 4 + suggestions: null +- message: Found a link with a url that isn't resolved. + line: 11 + column: 9 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-without-resolve01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-without-resolve01-input.svelte index 4ae6bc7ec..2dab745ff 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-without-resolve01-input.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/invalid/link-without-resolve01-input.svelte @@ -1,9 +1,11 @@ Click me! Click me! Click me! Click me! +Click me! Click me! diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/link-absolute-url01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/link-absolute-url01-input.svelte index 4b57ff9ba..cbc35c4a0 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/link-absolute-url01-input.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/link-absolute-url01-input.svelte @@ -2,6 +2,7 @@ const protocol = 'https'; const value = "https://svelte.dev"; + const href = "https://svelte.dev"; Click me! @@ -16,3 +17,4 @@ Click me! Click me! Click me! +Click me! diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/link-fragment-url01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/link-fragment-url01-input.svelte index cf56203a5..2e35b7630 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/link-fragment-url01-input.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/link-fragment-url01-input.svelte @@ -2,6 +2,7 @@ const section = 'sectionName'; const value = '#section'; + const href = '#section'; Click me! @@ -12,3 +13,4 @@ Click me! Click me! Click me! +Click me! diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/link-resolved01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/link-resolved01-input.svelte index 2561d7490..0ea7fca3a 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/link-resolved01-input.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/link-resolved01-input.svelte @@ -2,7 +2,9 @@ import { resolve } from '$app/paths'; const value = resolve('/foo/'); + const href = resolve('/foo/'); Click me! Click me! +Click me!