diff --git a/.changeset/smart-buttons-return.md b/.changeset/smart-buttons-return.md new file mode 100644 index 000000000000..fb4bfc1dd054 --- /dev/null +++ b/.changeset/smart-buttons-return.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': minor +--- + +feat: provide SvelteKit html typings diff --git a/packages/kit/src/core/sync/sync.js b/packages/kit/src/core/sync/sync.js index 3d1f0f9e57e9..d16466818f40 100644 --- a/packages/kit/src/core/sync/sync.js +++ b/packages/kit/src/core/sync/sync.js @@ -5,6 +5,7 @@ import { write_root } from './write_root.js'; import { write_tsconfig } from './write_tsconfig.js'; import { write_types, write_all_types } from './write_types/index.js'; import { write_ambient } from './write_ambient.js'; +import { write_non_ambient } from './write_non_ambient.js'; import { write_server } from './write_server.js'; /** @@ -15,6 +16,7 @@ import { write_server } from './write_server.js'; export function init(config, mode) { write_tsconfig(config.kit); write_ambient(config.kit, mode); + write_non_ambient(config.kit); } /** diff --git a/packages/kit/src/core/sync/write_non_ambient.js b/packages/kit/src/core/sync/write_non_ambient.js new file mode 100644 index 000000000000..a191495ac6f2 --- /dev/null +++ b/packages/kit/src/core/sync/write_non_ambient.js @@ -0,0 +1,42 @@ +import path from 'node:path'; +import { GENERATED_COMMENT } from '../../constants.js'; +import { write_if_changed } from './utils.js'; + +// `declare module "svelte/elements"` needs to happen in a non-ambient module, and dts-buddy generates one big ambient module, +// so we can't add it there - therefore generate the typings ourselves here. +// We're not using the `declare namespace svelteHTML` variant because that one doesn't augment the HTMLAttributes interface +// people could use to type their own components. +// The T generic is needed or else there's a "all declarations must have identical type parameters" error. +const template = ` +${GENERATED_COMMENT} + +declare module "svelte/elements" { + export interface HTMLAttributes { + 'data-sveltekit-keepfocus'?: true | '' | 'off' | undefined | null; + 'data-sveltekit-noscroll'?: true | '' | 'off' | 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 | '' | 'off' | undefined | null; + 'data-sveltekit-replacestate'?: true | '' | 'off' | undefined | null; + } +} + +export {}; +`; + +/** + * Writes non-ambient declarations to the output directory + * @param {import('types').ValidatedKitConfig} config + */ +export function write_non_ambient(config) { + write_if_changed(path.join(config.outDir, 'non-ambient.d.ts'), template); +} diff --git a/packages/kit/src/core/sync/write_tsconfig.js b/packages/kit/src/core/sync/write_tsconfig.js index d896d4a5ff50..cec52dca506a 100644 --- a/packages/kit/src/core/sync/write_tsconfig.js +++ b/packages/kit/src/core/sync/write_tsconfig.js @@ -86,6 +86,7 @@ export function get_tsconfig(kit, include_base_url) { const include = new Set([ 'ambient.d.ts', + 'non-ambient.d.ts', './types/**/$types.d.ts', config_relative('vite.config.js'), config_relative('vite.config.ts') @@ -109,7 +110,7 @@ export function get_tsconfig(kit, include_base_url) { include.add(config_relative(`${test_folder}/**/*.ts`)); include.add(config_relative(`${test_folder}/**/*.svelte`)); - const exclude = [config_relative('node_modules/**'), './[!ambient.d.ts]**']; + const exclude = [config_relative('node_modules/**')]; if (path.extname(kit.files.serviceWorker)) { exclude.push(config_relative(kit.files.serviceWorker)); } else { diff --git a/packages/kit/src/core/sync/write_tsconfig.spec.js b/packages/kit/src/core/sync/write_tsconfig.spec.js index 94590cff00ac..86a62109bc06 100644 --- a/packages/kit/src/core/sync/write_tsconfig.spec.js +++ b/packages/kit/src/core/sync/write_tsconfig.spec.js @@ -100,6 +100,7 @@ test('Creates tsconfig include from kit.files', () => { expect(include).toEqual([ 'ambient.d.ts', + 'non-ambient.d.ts', './types/**/$types.d.ts', '../vite.config.js', '../vite.config.ts',