diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2eb842967a..9fe83d2bcb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,4 +49,4 @@ jobs: with: node-version: 16 cache: pnpm - - run: 'pnpm i && pnpm check && pnpm lint' + - run: pnpm i && pnpm check && pnpm lint && pnpm build && [ "`git status --porcelain=v1`" == "" ] # ensures that commited types are up-to-date diff --git a/packages/svelte/.gitignore b/packages/svelte/.gitignore index 2f5d67e7de..3bcf2c3c42 100644 --- a/packages/svelte/.gitignore +++ b/packages/svelte/.gitignore @@ -6,13 +6,13 @@ /test/runtime/shards _actual*.* _output -/types +/types/compiler -action.d.ts -animate.d.ts -compiler.d.ts -easing.d.ts -index.d.ts -motion.d.ts -store.d.ts -transition.d.ts +/action.d.ts +/animate.d.ts +/compiler.d.ts +/easing.d.ts +/index.d.ts +/motion.d.ts +/store.d.ts +/transition.d.ts diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts new file mode 100644 index 0000000000..24bc9cf4d2 --- /dev/null +++ b/packages/svelte/types/index.d.ts @@ -0,0 +1,1877 @@ +declare module 'svelte' { + export interface ComponentConstructorOptions< + Props extends Record = Record + > { + target: Element | Document | ShadowRoot; + anchor?: Element; + props?: Props; + context?: Map; + hydrate?: boolean; + intro?: boolean; + $$inline?: boolean; + } + + /** + * Convenience type to get the events the given component expects. Example: + * ```html + * + * + * + * ``` + */ + export type ComponentEvents = + Component extends SvelteComponent ? Events : never; + + /** + * Convenience type to get the props the given component expects. Example: + * ```html + * + * ``` + */ + export type ComponentProps = + Component extends SvelteComponent ? Props : never; + + /** + * Convenience type to get the type of a Svelte component. Useful for example in combination with + * dynamic components using ``. + * + * Example: + * ```html + * + * + * + * + * ``` + */ + export type ComponentType = (new ( + options: ComponentConstructorOptions< + Component extends SvelteComponent ? Props : Record + > + ) => Component) & { + /** The custom element version of the component. Only present if compiled with the `customElement` compiler option */ + element?: typeof HTMLElement; + }; + + interface DispatchOptions { + cancelable?: boolean; + } + + interface EventDispatcher> { + // Implementation notes: + // - undefined extends X instead of X extends undefined makes this work better with both strict and nonstrict mode + // - | null | undefined is added for convenience, as they are equivalent for the custom event constructor (both result in a null detail) + ( + ...args: null extends EventMap[Type] + ? [type: Type, parameter?: EventMap[Type] | null | undefined, options?: DispatchOptions] + : undefined extends EventMap[Type] + ? [type: Type, parameter?: EventMap[Type] | null | undefined, options?: DispatchOptions] + : [type: Type, parameter: EventMap[Type], options?: DispatchOptions] + ): boolean; + } + /** + * Base class for Svelte components. Used when dev=false. + * + * + */ + class SvelteComponent_1< + Props extends Record = any, + Events extends Record = any + > { + /** + * ### PRIVATE API + * + * Do not use, may change at any time + * + * */ + $$: any; + /** + * ### PRIVATE API + * + * Do not use, may change at any time + * + * */ + $$set: any; + + $destroy(): void; + + $on>( + type: K, + callback: ((e: Events[K]) => void) | null | undefined + ): () => void; + + $set(props: Partial): void; + } + /** + * Base class for Svelte components with some minor dev-enhancements. Used when dev=true. + * + * Can be used to create strongly typed Svelte components. + * + * #### Example: + * + * You have component library on npm called `component-library`, from which + * you export a component called `MyComponent`. For Svelte+TypeScript users, + * you want to provide typings. Therefore you create a `index.d.ts`: + * ```ts + * import { SvelteComponent } from "svelte"; + * export class MyComponent extends SvelteComponent<{foo: string}> {} + * ``` + * Typing this makes it possible for IDEs like VS Code with the Svelte extension + * to provide intellisense and to use the component like this in a Svelte file + * with TypeScript: + * ```svelte + * + * + * ``` + * + */ + export class SvelteComponent< + Props extends Record = any, + Events extends Record = any, + Slots extends Record = any + > extends SvelteComponent_1 { + [prop: string]: any; + + constructor(options: ComponentConstructorOptions); + /** + * For type checking capabilities only. + * Does not exist at runtime. + * ### DO NOT USE! + * + * */ + $$prop_def: Props; + /** + * For type checking capabilities only. + * Does not exist at runtime. + * ### DO NOT USE! + * + * */ + $$events_def: Events; + /** + * For type checking capabilities only. + * Does not exist at runtime. + * ### DO NOT USE! + * + * */ + $$slot_def: Slots; + + $capture_state(): void; + + $inject_state(): void; + } + /** + * @deprecated Use `SvelteComponent` instead. See PR for more information: https://github.com/sveltejs/svelte/pull/8512 + * + */ + export class SvelteComponentTyped< + Props extends Record = any, + Events extends Record = any, + Slots extends Record = any + > extends SvelteComponent {} + /** + * Schedules a callback to run immediately before the component is updated after any state change. + * + * The first time the callback runs will be before the initial `onMount` + * + * https://svelte.dev/docs/svelte#beforeupdate + * */ + export function beforeUpdate(fn: () => any): void; + /** + * The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM. + * It must be called during the component's initialisation (but doesn't need to live *inside* the component; + * it can be called from an external module). + * + * If a function is returned _synchronously_ from `onMount`, it will be called when the component is unmounted. + * + * `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api). + * + * https://svelte.dev/docs/svelte#onmount + * */ + export function onMount( + fn: () => NotFunction | Promise> | (() => any) + ): void; + /** + * Schedules a callback to run immediately after the component has been updated. + * + * The first time the callback runs will be after the initial `onMount` + * + * https://svelte.dev/docs/svelte#afterupdate + * */ + export function afterUpdate(fn: () => any): void; + /** + * Schedules a callback to run immediately before the component is unmounted. + * + * Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the + * only one that runs inside a server-side component. + * + * https://svelte.dev/docs/svelte#ondestroy + * */ + export function onDestroy(fn: () => any): void; + /** + * Creates an event dispatcher that can be used to dispatch [component events](/docs#template-syntax-component-directives-on-eventname). + * Event dispatchers are functions that can take two arguments: `name` and `detail`. + * + * Component events created with `createEventDispatcher` create a + * [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). + * These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture). + * The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail) + * property and can contain any type of data. + * + * The event dispatcher can be typed to narrow the allowed event names and the type of the `detail` argument: + * ```ts + * const dispatch = createEventDispatcher<{ + * loaded: never; // does not take a detail argument + * change: string; // takes a detail argument of type string, which is required + * optional: number | null; // takes an optional detail argument of type number + * }>(); + * ``` + * + * https://svelte.dev/docs/svelte#createeventdispatcher + * */ + export function createEventDispatcher< + EventMap extends Record = any + >(): EventDispatcher; + /** + * Associates an arbitrary `context` object with the current component and the specified `key` + * and returns that object. The context is then available to children of the component + * (including slotted content) with `getContext`. + * + * Like lifecycle functions, this must be called during component initialisation. + * + * https://svelte.dev/docs/svelte#setcontext + * */ + export function setContext(key: any, context: T): T; + /** + * Retrieves the context that belongs to the closest parent component with the specified `key`. + * Must be called during component initialisation. + * + * https://svelte.dev/docs/svelte#getcontext + * */ + export function getContext(key: any): T; + /** + * Retrieves the whole context map that belongs to the closest parent component. + * Must be called during component initialisation. Useful, for example, if you + * programmatically create a component and want to pass the existing context to it. + * + * https://svelte.dev/docs/svelte#getallcontexts + * */ + export function getAllContexts = Map>(): T; + /** + * Checks whether a given `key` has been set in the context of a parent component. + * Must be called during component initialisation. + * + * https://svelte.dev/docs/svelte#hascontext + * */ + export function hasContext(key: any): boolean; + export function tick(): Promise; + /** + * Anything except a function + */ + type NotFunction = T extends Function ? never : T; +} + +declare module 'svelte/compiler' { + import type { AssignmentExpression, Node, Program } from 'estree'; + import type { SourceMap } from 'magic-string'; + export { walk } from 'estree-walker'; + interface BaseNode { + start: number; + end: number; + type: string; + children?: TemplateNode[]; + [prop_name: string]: any; + } + + interface Text extends BaseNode { + type: 'Text'; + data: string; + } + + interface MustacheTag extends BaseNode { + type: 'MustacheTag' | 'RawMustacheTag'; + expression: Node; + } + + interface Comment extends BaseNode { + type: 'Comment'; + data: string; + ignores: string[]; + } + + interface ConstTag extends BaseNode { + type: 'ConstTag'; + expression: AssignmentExpression; + } + + interface DebugTag extends BaseNode { + type: 'DebugTag'; + identifiers: Node[]; + } + + type DirectiveType = + | 'Action' + | 'Animation' + | 'Binding' + | 'Class' + | 'StyleDirective' + | 'EventHandler' + | 'Let' + | 'Ref' + | 'Transition'; + + interface BaseDirective extends BaseNode { + type: DirectiveType; + name: string; + } + + interface BaseExpressionDirective extends BaseDirective { + type: DirectiveType; + expression: null | Node; + name: string; + modifiers: string[]; + } + + interface Element extends BaseNode { + type: + | 'InlineComponent' + | 'SlotTemplate' + | 'Title' + | 'Slot' + | 'Element' + | 'Head' + | 'Options' + | 'Window' + | 'Document' + | 'Body'; + attributes: Array; + name: string; + } + + interface Attribute extends BaseNode { + type: 'Attribute'; + name: string; + value: any[]; + } + + interface SpreadAttribute extends BaseNode { + type: 'Spread'; + expression: Node; + } + + interface Transition extends BaseExpressionDirective { + type: 'Transition'; + intro: boolean; + outro: boolean; + } + + type Directive = BaseDirective | BaseExpressionDirective | Transition; + + type TemplateNode = + | Text + | ConstTag + | DebugTag + | MustacheTag + | BaseNode + | Element + | Attribute + | SpreadAttribute + | Directive + | Transition + | Comment; + + interface Script extends BaseNode { + type: 'Script'; + context: string; + content: Program; + } + + interface Style extends BaseNode { + type: 'Style'; + attributes: any[]; // TODO + children: any[]; // TODO add CSS node types + content: { + start: number; + end: number; + styles: string; + }; + } + + interface Ast { + html: TemplateNode; + css?: Style; + instance?: Script; + module?: Script; + } + + interface Warning { + start?: { line: number; column: number; pos?: number }; + end?: { line: number; column: number }; + pos?: number; + code: string; + message: string; + filename?: string; + frame?: string; + toString: () => string; + } + + export type EnableSourcemap = boolean | { js: boolean; css: boolean }; + + export type CssHashGetter = (args: { + name: string; + filename: string | undefined; + css: string; + hash: (input: string) => string; + }) => string; + + export interface CompileOptions { + /** + * Sets the name of the resulting JavaScript class (though the compiler will rename it if it would otherwise conflict with other variables in scope). + * It will normally be inferred from `filename` + * + * @default 'Component' + */ + name?: string; + + /** + * Used for debugging hints and sourcemaps. Your bundler plugin will set it automatically. + * + * @default null + */ + filename?: string; + + /** + * If `"dom"`, Svelte emits a JavaScript class for mounting to the DOM. + * If `"ssr"`, Svelte emits an object with a `render` method suitable for server-side rendering. + * If `false`, no JavaScript or CSS is returned; just metadata. + * + * @default 'dom' + */ + generate?: 'dom' | 'ssr' | false; + + /** + * If `"throw"`, Svelte throws when a compilation error occurred. + * If `"warn"`, Svelte will treat errors as warnings and add them to the warning report. + * + * @default 'throw' + */ + errorMode?: 'throw' | 'warn'; + + /** + * If `"strict"`, Svelte returns a variables report with only variables that are not globals nor internals. + * If `"full"`, Svelte returns a variables report with all detected variables. + * If `false`, no variables report is returned. + * + * @default 'strict' + */ + varsReport?: 'full' | 'strict' | false; + + /** + * An initial sourcemap that will be merged into the final output sourcemap. + * This is usually the preprocessor sourcemap. + * + * @default null + */ + sourcemap?: object | string; + + /** + * If `true`, Svelte generate sourcemaps for components. + * Use an object with `js` or `css` for more granular control of sourcemap generation. + * + * @default true + */ + enableSourcemap?: EnableSourcemap; + + /** + * Used for your JavaScript sourcemap. + * + * @default null + */ + outputFilename?: string; + + /** + * Used for your CSS sourcemap. + * + * @default null + */ + cssOutputFilename?: string; + + /** + * The location of the `svelte` package. + * Any imports from `svelte` or `svelte/[module]` will be modified accordingly. + * + * @default 'svelte' + */ + sveltePath?: string; + + /** + * If `true`, causes extra code to be added to components that will perform runtime checks and provide debugging information during development. + * + * @default false + */ + dev?: boolean; + + /** + * If `true`, getters and setters will be created for the component's props. If `false`, they will only be created for readonly exported values (i.e. those declared with `const`, `class` and `function`). If compiling with `customElement: true` this option defaults to `true`. + * + * @default false + */ + accessors?: boolean; + + /** + * If `true`, tells the compiler that you promise not to mutate any objects. + * This allows it to be less conservative about checking whether values have changed. + * + * @default false + */ + immutable?: boolean; + + /** + * If `true` when generating DOM code, enables the `hydrate: true` runtime option, which allows a component to upgrade existing DOM rather than creating new DOM from scratch. + * When generating SSR code, this adds markers to `` elements so that hydration knows which to replace. + * + * @default false + */ + hydratable?: boolean; + + /** + * If `true`, generates code that will work in IE9 and IE10, which don't support things like `element.dataset`. + * + * @default false + */ + legacy?: boolean; + + /** + * If `true`, tells the compiler to generate a custom element constructor instead of a regular Svelte component. + * + * @default false + */ + customElement?: boolean; + + /** + * A `string` that tells Svelte what tag name to register the custom element with. + * It must be a lowercase alphanumeric string with at least one hyphen, e.g. `"my-element"`. + * + * @default null + */ + tag?: string; + + /** + * - `'injected'` (formerly `true`), styles will be included in the JavaScript class and injected at runtime for the components actually rendered. + * - `'external'` (formerly `false`), the CSS will be returned in the `css` field of the compilation result. Most Svelte bundler plugins will set this to `'external'` and use the CSS that is statically generated for better performance, as it will result in smaller JavaScript bundles and the output can be served as cacheable `.css` files. + * - `'none'`, styles are completely avoided and no CSS output is generated. + */ + css?: 'injected' | 'external' | 'none' | boolean; + + /** + * A `number` that tells Svelte to break the loop if it blocks the thread for more than `loopGuardTimeout` ms. + * This is useful to prevent infinite loops. + * **Only available when `dev: true`**. + * + * @default 0 + */ + loopGuardTimeout?: number; + + /** + * The namespace of the element; e.g., `"mathml"`, `"svg"`, `"foreign"`. + * + * @default 'html' + */ + namespace?: string; + + /** + * A function that takes a `{ hash, css, name, filename }` argument and returns the string that is used as a classname for scoped CSS. + * It defaults to returning `svelte-${hash(css)}`. + * + * @default undefined + */ + cssHash?: CssHashGetter; + + /** + * If `true`, your HTML comments will be preserved during server-side rendering. By default, they are stripped out. + * + * @default false + */ + preserveComments?: boolean; + + /** + * If `true`, whitespace inside and between elements is kept as you typed it, rather than removed or collapsed to a single space where possible. + * + * @default false + */ + preserveWhitespace?: boolean; + /** + * If `true`, exposes the Svelte major version on the global `window` object in the browser. + * + * @default true + */ + discloseVersion?: boolean; + } + + interface ParserOptions { + filename?: string; + customElement?: boolean; + css?: 'injected' | 'external' | 'none' | boolean; + } + + interface Var { + name: string; + /** the `bar` in `export { foo as bar }` or `export let bar` */ + export_name?: string; + /** true if assigned a boolean default value (`export let foo = true`) */ + is_boolean?: boolean; + injected?: boolean; + module?: boolean; + mutated?: boolean; + reassigned?: boolean; + referenced?: boolean; // referenced from template scope + referenced_from_script?: boolean; // referenced from script + writable?: boolean; + + // used internally, but not exposed + global?: boolean; + internal?: boolean; // event handlers, bindings + initialised?: boolean; + hoistable?: boolean; + subscribable?: boolean; + is_reactive_dependency?: boolean; + imported?: boolean; + } + + interface CssResult { + code: string; + map: SourceMap; + } + + /** The returned shape of `compile` from `svelte/compiler` */ + export interface CompileResult { + /** The resulting JavaScript code from compling the component */ + js: { + /** Code as a string */ + code: string; + /** A source map */ + map: any; + }; + /** The resulting CSS code from compling the component */ + css: CssResult; + /** The abstract syntax tree representing the structure of the component */ + ast: Ast; + /** + * An array of warning objects that were generated during compilation. Each warning has several properties: + * - code is a string identifying the category of warning + * - message describes the issue in human-readable terms + * - start and end, if the warning relates to a specific location, are objects with line, column and character properties + * - frame, if applicable, is a string highlighting the offending code with line numbers + * */ + warnings: Warning[]; + /** An array of the component's declarations used by tooling in the ecosystem (like our ESLint plugin) to infer more information */ + vars: Var[]; + /** An object used by the Svelte developer team for diagnosing the compiler. Avoid relying on it to stay the same! */ + stats: { + timings: { + total: number; + }; + }; + } + /** + * The result of a preprocessor run. If the preprocessor does not return a result, it is assumed that the code is unchanged. + */ + export interface Processed { + /** + * The new code + */ + code: string; + /** + * A source map mapping back to the original code + */ + map?: string | object; // we are opaque with the type here to avoid dependency on the remapping module for our public types. + /** + * A list of additional files to watch for changes + */ + dependencies?: string[]; + /** + * Only for script/style preprocessors: The updated attributes to set on the tag. If undefined, attributes stay unchanged. + */ + attributes?: Record; + toString?: () => string; + } + + /** + * A markup preprocessor that takes a string of code and returns a processed version. + */ + export type MarkupPreprocessor = (options: { + /** + * The whole Svelte file content + */ + content: string; + /** + * The filename of the Svelte file + */ + filename?: string; + }) => Processed | void | Promise; + + /** + * A script/style preprocessor that takes a string of code and returns a processed version. + */ + export type Preprocessor = (options: { + /** + * The script/style tag content + */ + content: string; + /** + * The attributes on the script/style tag + */ + attributes: Record; + /** + * The whole Svelte file content + */ + markup: string; + /** + * The filename of the Svelte file + */ + filename?: string; + }) => Processed | void | Promise; + + /** + * A preprocessor group is a set of preprocessors that are applied to a Svelte file. + */ + export interface PreprocessorGroup { + /** Name of the preprocessor. Will be a required option in the next major version */ + name?: string; + markup?: MarkupPreprocessor; + style?: Preprocessor; + script?: Preprocessor; + } + + /** + * Utility type to extract the type of a preprocessor from a preprocessor group + */ + export interface SveltePreprocessor< + PreprocessorType extends keyof PreprocessorGroup, + Options = any + > { + (options?: Options): Required>; + } + /** + * `compile` takes your component source code, and turns it into a JavaScript module that exports a class. + * + * https://svelte.dev/docs/svelte-compiler#svelte-compile + * */ + export function compile(source: string, options?: CompileOptions): CompileResult; + /** + * The parse function parses a component, returning only its abstract syntax tree. + * + * https://svelte.dev/docs/svelte-compiler#svelte-parse + * */ + export function parse(template: string, options?: ParserOptions): Ast; + /** + * The preprocess function provides convenient hooks for arbitrarily transforming component source code. + * For example, it can be used to convert a