Repository: sveltejs/language-tools (ts)

Issue:
Remove `sveltekit:prefetch` auto-completion
### Description

Typing `prefetch` on anchor tags suggests auto-completing the [removed `sveltekit:prefetch`](https://github.com/sveltejs/kit/commit/8e9839a) as well as the [new `data-sveltekit-prefetch`](https://kit.svelte.dev/docs/link-options#data-sveltekit-prefetch).

![Screen Shot 2022-10-13 at 21 19 03](https://user-images.githubusercontent.com/30958850/195761714-0104cce4-4f2b-4b52-a040-c8a32c647669.png)

When selecting the new `data-sveltekit-prefetch`, it completes to an empty string:

![Screen Shot 2022-10-13 at 21 19 27](https://user-images.githubusercontent.com/30958850/195761782-b3401808-eefb-44db-a420-aa729f613bf9.png)


### Proposed solution

Remove `sveltekit:prefetch` and complete `data-sveltekit-prefetch` to this instead:

```
<a href="foo" data-sveltekit-prefetch></a>
```

since prefetching takes no arguments.

### Alternatives

_No response_

### Additional Information, eg. Screenshots

_No response_

Pull request:
Update SvelteKit anchor tag props
Closes #1680.

```txt
sveltekit:noscroll -> data-sveltekit-noscroll
sveltekit:prefetch -> data-sveltekit-prefetch
sveltekit:reload -> data-sveltekit-reload
```


Patch:
diff --git a/packages/language-server/src/plugins/html/dataProvider.ts b/packages/language-server/src/plugins/html/dataProvider.ts
index 86323ffb..92fd35d4 100644
--- a/packages/language-server/src/plugins/html/dataProvider.ts
+++ b/packages/language-server/src/plugins/html/dataProvider.ts
@@ -65,6 +65,40 @@ const svelteAttributes: IAttributeData[] = [
             'To get a reference to a DOM node, use bind:this. If used on a component, gets a reference to that component instance.'
     }
 ];
+const sveltekitAttributes: IAttributeData[] = [
+    {
+        name: 'data-sveltekit-noscroll',
+        description:
+            'SvelteKit-specific attribute. Will prevent scrolling after the link is clicked.',
+        valueSet: 'v'
+    },
+    {
+        name: 'data-sveltekit-preload-code',
+        description:
+            "SvelteKit-specific attribute. Will cause SvelteKit to run the page's load function as soon as the user hovers over the link (on a desktop) or touches it (on mobile), rather than waiting for the click event to trigger navigation.",
+        valueSet: 'v',
+        values: [
+            { name: 'eager' },
+            { name: 'viewport' },
+            { name: 'hover' },
+            { name: 'tap' },
+            { name: 'off' }
+        ]
+    },
+    {
+        name: 'data-sveltekit-preload-data',
+        description:
+            "SvelteKit-specific attribute. Will cause SvelteKit to run the page's load function as soon as the user hovers over the link (on a desktop) or touches it (on mobile), rather than waiting for the click event to trigger navigation.",
+        valueSet: 'v',
+        values: [{ name: 'hover' }, { name: 'tap' }, { name: 'off' }]
+    },
+    {
+        name: 'data-sveltekit-reload',
+        description:
+            'SvelteKit-specific attribute. Will cause SvelteKit to do a normal browser navigation which results in a full page reload.',
+        valueSet: 'v'
+    }
+];
 
 const svelteTags: ITagData[] = [
     {
@@ -288,26 +322,6 @@ const addAttributes: Record<string, IAttributeData[]> = {
     textarea: [{ name: 'bind:value' }],
     video: [...mediaAttributes, ...videoAttributes],
     audio: [...mediaAttributes],
-    a: [
-        {
-            name: 'sveltekit:noscroll',
-            description:
-                'SvelteKit-specific attribute. Will prevent scrolling after the link is clicked.',
-            valueSet: 'v'
-        },
-        {
-            name: 'sveltekit:prefetch',
-            description:
-                "SvelteKit-specific attribute. Will cause SvelteKit to run the page's load function as soon as the user hovers over the link (on a desktop) or touches it (on mobile), rather than waiting for the click event to trigger navigation.",
-            valueSet: 'v'
-        },
-        {
-            name: 'sveltekit:reload',
-            description:
-                'SvelteKit-specific attribute. Will cause SvelteKit to do a normal browser navigation which results in a full page reload.',
-            valueSet: 'v'
-        }
-    ],
     details: [
         {
             name: 'bind:open'
@@ -328,7 +342,12 @@ const html5Tags = htmlData.tags!.map((tag) => {
 
 export const svelteHtmlDataProvider = newHTMLDataProvider('svelte-builtin', {
     version: 1,
-    globalAttributes: [...htmlData.globalAttributes!, ...svelteEvents, ...svelteAttributes],
+    globalAttributes: [
+        ...htmlData.globalAttributes!,
+        ...svelteEvents,
+        ...svelteAttributes,
+        ...sveltekitAttributes
+    ],
     tags: [...html5Tags, ...svelteTags],
     valueSets: htmlData.valueSets
 });
diff --git a/packages/svelte2tsx/src/htmlxtojsx/nodes/attribute.ts b/packages/svelte2tsx/src/htmlxtojsx/nodes/attribute.ts
index fc3ad030..b0533246 100644
--- a/packages/svelte2tsx/src/htmlxtojsx/nodes/attribute.ts
+++ b/packages/svelte2tsx/src/htmlxtojsx/nodes/attribute.ts
@@ -1,7 +1,7 @@
 import MagicString from 'magic-string';
+import { Attribute, BaseNode } from '../../interfaces';
 import svgAttributes from '../svgattributes';
 import { buildTemplateString } from '../utils/node-utils';
-import { Attribute, BaseNode } from '../../interfaces';
 
 /**
  * List taken from `svelte-jsx.d.ts` by searching for all attributes of type number
@@ -61,9 +61,10 @@ export function handleAttribute(
     if (parent.type == 'Element') {
         const sapperLinkActions = ['sapper:prefetch', 'sapper:noscroll'];
         const sveltekitLinkActions = [
-            'sveltekit:prefetch',
-            'sveltekit:noscroll',
-            'sveltekit:reload'
+            'data-sveltekit-preload-code',
+            'data-sveltekit-preload-data',
+            'data-sveltekit-noscroll',
+            'data-sveltekit-reload'
         ];
         // skip Attribute shorthand, that is handled below
         if (
diff --git a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts
index d8a82ea5..49dc7728 100644
--- a/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts
+++ b/packages/svelte2tsx/src/htmlxtojsx_v2/nodes/Attribute.ts
@@ -68,7 +68,7 @@ export function handleAttribute(
     const addAttribute =
         element instanceof Element
             ? (name: TransformationArray, value?: TransformationArray) => {
-                  if (attr.name.startsWith('data-')) {
+                  if (attr.name.startsWith('data-') && !attr.name.startsWith('data-sveltekit-')) {
                       // any attribute prefixed with data- is valid, but we can't
                       // type that statically, so we need this workaround
                       name.unshift('...__sveltets_2_empty({');
diff --git a/packages/svelte2tsx/svelte-html-do-not-use.d.ts b/packages/svelte2tsx/svelte-html-do-not-use.d.ts
index 8a85f130..44400eda 100644
--- a/packages/svelte2tsx/svelte-html-do-not-use.d.ts
+++ b/packages/svelte2tsx/svelte-html-do-not-use.d.ts
@@ -559,9 +559,10 @@ export interface HTMLAnchorAttributes extends HTMLAttributes<HTMLAnchorElement>
 	referrerpolicy?: ReferrerPolicy | undefined | null;
 
 	// SvelteKit
-	'sveltekit:noscroll'?: true | undefined | null;
-	'sveltekit:prefetch'?: true | undefined | null;
-	'sveltekit:reload'?: true | undefined | null;
+	'data-sveltekit-noscroll'?: true | undefined | null;
+	'data-sveltekit-preload-code'?: true | 'eager' | 'viewport' | 'hover' | 'tap' | 'off' | undefined | null;
+	'data-sveltekit-preload-data'?: true | 'hover' | 'tap' | 'off' | undefined | null;
+	'data-sveltekit-reload'?: true | undefined | null;
 
 	// Sapper
 	'sapper:noscroll'?: true | undefined | null;
diff --git a/packages/svelte2tsx/svelte-jsx.d.ts b/packages/svelte2tsx/svelte-jsx.d.ts
index 91f883a7..157f95f3 100644
--- a/packages/svelte2tsx/svelte-jsx.d.ts
+++ b/packages/svelte2tsx/svelte-jsx.d.ts
@@ -1176,10 +1176,10 @@ declare namespace svelte.JSX {
     }
 
     interface SvelteKitAnchorProps {
-        // transformed from sveltekit:noscroll so it should be camel case
-        sveltekitNoscroll?: true | undefined | null;
-        sveltekitPrefetch?: true | undefined | null;
-        sveltekitReload?: true | undefined | null;
+        'data-sveltekit-noscroll'?: true | undefined | null;
+        'data-sveltekit-preload-code'?: true | 'eager' | 'viewport' | 'hover' | 'tap' | 'off' | undefined | null;
+        'data-sveltekit-preload-data'?: true | 'hover' | 'tap' | 'off' | undefined | null;
+        'data-sveltekit-reload'?: true | undefined | null;
     }
 
     interface SvelteMediaTimeRange {


Test patch:
diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/sveltekit-anchor-attrs/expected.jsx b/packages/svelte2tsx/test/htmlx2jsx/samples/sveltekit-anchor-attrs/expected.jsx
index d17de542..5aab53ae 100644
--- a/packages/svelte2tsx/test/htmlx2jsx/samples/sveltekit-anchor-attrs/expected.jsx
+++ b/packages/svelte2tsx/test/htmlx2jsx/samples/sveltekit-anchor-attrs/expected.jsx
@@ -1,4 +1,5 @@
-<><a sveltekitNoscroll></a>
-<a sveltekitPrefetch></a>
-<a sveltekitReload></a>
-<svelteelement this="a" sveltekitPrefetch></svelteelement></>
+<><a data-sveltekit-noscroll></a>
+<a data-sveltekit-preload-code></a>
+<a data-sveltekit-preload-data></a>
+<a data-sveltekit-reload></a>
+<svelteelement this="a" data-sveltekit-preload-data></svelteelement></>
diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/sveltekit-anchor-attrs/expectedv2.js b/packages/svelte2tsx/test/htmlx2jsx/samples/sveltekit-anchor-attrs/expectedv2.js
index 9f6a1d40..933fc248 100644
--- a/packages/svelte2tsx/test/htmlx2jsx/samples/sveltekit-anchor-attrs/expectedv2.js
+++ b/packages/svelte2tsx/test/htmlx2jsx/samples/sveltekit-anchor-attrs/expectedv2.js
@@ -1,4 +1,5 @@
- { svelteHTML.createElement("a", {"sveltekit:noscroll":true,}); }
- { svelteHTML.createElement("a", {"sveltekit:prefetch":true,}); }
- { svelteHTML.createElement("a", {"sveltekit:reload":true,}); }
- { svelteHTML.createElement("a", { "sveltekit:prefetch":true,}); }
+ { svelteHTML.createElement("a", {"data-sveltekit-noscroll":true,}); }
+ { svelteHTML.createElement("a", {"data-sveltekit-preload-code":true,}); }
+ { svelteHTML.createElement("a", {"data-sveltekit-preload-data":true,}); }
+ { svelteHTML.createElement("a", {"data-sveltekit-reload":true,}); }
+ { svelteHTML.createElement("a", { "data-sveltekit-preload-data":true,}); }
diff --git a/packages/svelte2tsx/test/htmlx2jsx/samples/sveltekit-anchor-attrs/input.svelte b/packages/svelte2tsx/test/htmlx2jsx/samples/sveltekit-anchor-attrs/input.svelte
index e24c3dbe..a9edfcc0 100644
--- a/packages/svelte2tsx/test/htmlx2jsx/samples/sveltekit-anchor-attrs/input.svelte
+++ b/packages/svelte2tsx/test/htmlx2jsx/samples/sveltekit-anchor-attrs/input.svelte
@@ -1,4 +1,5 @@
-<a sveltekit:noscroll></a>
-<a sveltekit:prefetch></a>
-<a sveltekit:reload></a>
-<svelte:element this="a" sveltekit:prefetch></svelte:element>
+<a data-sveltekit-noscroll></a>
+<a data-sveltekit-preload-code></a>
+<a data-sveltekit-preload-data></a>
+<a data-sveltekit-reload></a>
+<svelte:element this="a" data-sveltekit-preload-data></svelte:element>
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expected.tsx b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expected.tsx
index bddb8061..7465ffce 100644
--- a/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expected.tsx
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expected.tsx
@@ -10,7 +10,7 @@
 <svelteelement this={tag ? 'a' : 'b'} />
 <svelteelement this={tag}>{tag}</svelteelement>
 <svelteelement this={tag} onclick={() => tag} />
-<svelteelement this={'a'} sveltekitPrefetch href="https://kit.svelte.dev" /></>);
+<svelteelement this={'a'} data-sveltekit-preload-data href="https://kit.svelte.dev" /></>);
 return { props: /** @type {Record<string, never>} */ ({}), slots: {}, events: {} }}
 
 export default class Input__SvelteComponent_ extends __sveltets_1_createSvelte2TsxComponent(__sveltets_1_partial(__sveltets_1_with_any_event(render()))) {
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expectedv2.ts b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expectedv2.ts
index ace20283..e3ad7a65 100644
--- a/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expectedv2.ts
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/expectedv2.ts
@@ -10,8 +10,8 @@ async () => {
  { svelteHTML.createElement(tag ? 'a' : 'b', {  });}
  { svelteHTML.createElement(tag, { });tag; }
  { svelteHTML.createElement(tag, {    "on:click":() => tag,});}
- { svelteHTML.createElement('a', {    "sveltekit:prefetch":true,"href":`https://kit.svelte.dev`,});}};
+ { svelteHTML.createElement('a', {    "data-sveltekit-preload-data":true,"href":`https://kit.svelte.dev`,});}};
 return { props: /** @type {Record<string, never>} */ ({}), slots: {}, events: {} }}
 
 export default class Input__SvelteComponent_ extends __sveltets_1_createSvelte2TsxComponent(__sveltets_1_partial(__sveltets_1_with_any_event(render()))) {
-}
\ No newline at end of file
+}
diff --git a/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/input.svelte b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/input.svelte
index ea16ac86..7bfcdcd0 100644
--- a/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/input.svelte
+++ b/packages/svelte2tsx/test/svelte2tsx/samples/svelte-element/input.svelte
@@ -7,4 +7,4 @@
 <svelte:element this={tag ? 'a' : 'b'} />
 <svelte:element this={tag}>{tag}</svelte:element>
 <svelte:element this={tag} on:click={() => tag} />
-<svelte:element this={'a'} sveltekit:prefetch href="https://kit.svelte.dev" />
+<svelte:element this={'a'} data-sveltekit-preload-data href="https://kit.svelte.dev" />