sveld 0.34.1 → 0.35.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +357 -89
  2. package/cli.js +6 -1
  3. package/lib/ComponentParser.d.ts +229 -568
  4. package/lib/ast-guards.d.ts +7 -1
  5. package/lib/browser.d.ts +39 -0
  6. package/lib/browser.js +290 -0
  7. package/lib/bundle.d.ts +23 -3
  8. package/lib/check.d.ts +6 -0
  9. package/lib/cli.d.ts +18 -18
  10. package/lib/diagnostics.d.ts +5 -1
  11. package/lib/example-check.d.ts +3 -1
  12. package/lib/index.js +306 -720
  13. package/lib/load-config.d.ts +20 -2
  14. package/lib/parse-exports.d.ts +5 -1
  15. package/lib/parser/bindings.d.ts +6 -0
  16. package/lib/parser/context.d.ts +114 -0
  17. package/lib/parser/contexts.d.ts +19 -0
  18. package/lib/parser/diagnostics.d.ts +8 -0
  19. package/lib/parser/events.d.ts +23 -0
  20. package/lib/parser/generics.d.ts +24 -0
  21. package/lib/parser/jsdoc.d.ts +59 -0
  22. package/lib/parser/props.d.ts +73 -0
  23. package/lib/parser/rest-props.d.ts +6 -0
  24. package/lib/parser/runes-detection.d.ts +16 -0
  25. package/lib/parser/runes-props.d.ts +18 -0
  26. package/lib/parser/scopes.d.ts +58 -0
  27. package/lib/parser/slots.d.ts +29 -0
  28. package/lib/parser/source-position.d.ts +30 -0
  29. package/lib/parser/type-resolution.d.ts +32 -0
  30. package/lib/parser/typescript-casts.d.ts +2 -0
  31. package/lib/plugin.d.ts +7 -3
  32. package/lib/resolve-types.d.ts +1 -1
  33. package/lib/sveld.d.ts +6 -19
  34. package/lib/writer/MarkdownWriterBase.d.ts +2 -1
  35. package/lib/writer/Writer.d.ts +13 -49
  36. package/lib/writer/WriterMarkdown.d.ts +1 -1
  37. package/lib/writer/format-generated-ts.d.ts +8 -0
  38. package/lib/writer/writer-custom-elements-core.d.ts +86 -0
  39. package/lib/writer/writer-custom-elements.d.ts +15 -0
  40. package/lib/writer/writer-ts-definitions-core.d.ts +12 -1
  41. package/lib/writer/writer-ts-definitions.d.ts +4 -3
  42. package/package.json +6 -4
@@ -1,9 +1,27 @@
1
1
  import type { PluginSveldOptions } from "./plugin";
2
+ /**
3
+ * Options shared by the config file, the CLI, and the programmatic `sveld()`
4
+ * API. Superset of `PluginSveldOptions` with the CLI-oriented flags that only
5
+ * make sense as part of a full `sveld` run (not the Vite/Rollup plugin).
6
+ */
7
+ export interface SveldRuntimeOptions extends PluginSveldOptions {
8
+ /** Print unresolved-type diagnostics to stderr. */
9
+ reportDiagnostics?: boolean;
10
+ /** Exit code 1 when diagnostics exist. Implies `reportDiagnostics`. */
11
+ strict?: boolean;
12
+ /**
13
+ * Diff the parsed component API against a committed snapshot (default:
14
+ * the `json` writer's `outFile`, or `COMPONENT_API.json`) and assign a
15
+ * semver bump to each change. Exits `1` on a breaking change. Pass a
16
+ * string for a custom snapshot path.
17
+ */
18
+ check?: boolean | string;
19
+ }
2
20
  /**
3
21
  * Public shape of a `sveld.config.{js,ts,mjs}` file. Identical to the options
4
- * accepted by the Vite/Rollup plugin and the CLI.
22
+ * accepted by the CLI and the programmatic `sveld()` API.
5
23
  */
6
- export type SveldConfig = PluginSveldOptions;
24
+ export type SveldConfig = SveldRuntimeOptions;
7
25
  /** Config file names probed at the project root. First existing file wins. */
8
26
  export declare const CONFIG_FILE_NAMES: readonly ["sveld.config.js", "sveld.config.mjs", "sveld.config.ts"];
9
27
  /**
@@ -17,5 +17,9 @@ export type ParsedExports = Record<string, {
17
17
  * // App: { source: "./App.svelte", default: true }
18
18
  * // }
19
19
  * ```
20
+ *
21
+ * @param resolving - Absolute paths currently being resolved on this call
22
+ * stack, used to break `export *` cycles between files that re-export
23
+ * each other. Callers should not pass this; it is threaded internally.
20
24
  */
21
- export declare function parseExports(source: string, dir: string): ParsedExports;
25
+ export declare function parseExports(source: string, dir: string, resolving?: Set<string>): ParsedExports;
@@ -0,0 +1,6 @@
1
+ import type ComponentParser from "../ComponentParser";
2
+ import type { ParserContext } from "./context";
3
+ /** Pull `propName`'s type out of an object type string like `{ value: string; other: number }`. */
4
+ export declare function extractPropertyType(typeStr: string, propName: string): string | undefined;
5
+ /** Resolve `obj.prop` by looking up `obj`'s type and calling {@link extractPropertyType}. */
6
+ export declare function resolveMemberExpressionType(ctx: ParserContext, parser: ComponentParser, expr: unknown): string | undefined;
@@ -0,0 +1,114 @@
1
+ import type { FunctionDeclaration, VariableDeclaration } from "estree";
2
+ import type { ComponentContext, ComponentElement, ComponentEvent, ComponentGenerics, ComponentInlineElement, ComponentProp, ComponentPropBindings, Extends, InternalComponentSlot, LegacyAstRoot, LexicalScope, LocalTypeDeclaration, RestProps, RunesPropsDeclarationMetadata, ScriptLanguage, SourceRange, SyntaxMode, TypeDef, TypeImportBinding } from "../ComponentParser";
3
+ import type { SveldDiagnostic } from "../diagnostics";
4
+ /** Per-parse mutable state for {@link ComponentParser}. Reset via {@link createParserContext} on each parse. */
5
+ export interface ParserContext {
6
+ /** Whether the component uses legacy or runes syntax according to compiler metadata */
7
+ syntaxMode: SyntaxMode;
8
+ /** Language used by the component's instance or module script, when supported */
9
+ scriptLanguage?: ScriptLanguage;
10
+ /** Raw source code of the Svelte component being parsed */
11
+ source?: string;
12
+ /** Parsed abstract syntax tree from the Svelte compiler */
13
+ parsed?: LegacyAstRoot;
14
+ /**
15
+ * Explicit `<svelte:options runes={...} />` value, resolved during the modern-mode parse for
16
+ * runes prop type metadata. When present, overrides rune-reference detection.
17
+ */
18
+ runesOptionOverride?: boolean;
19
+ /** Cached `ctx.source` split on newlines */
20
+ sourceLinesCache?: string[];
21
+ /** Cached 0-based source offsets for the start of each line */
22
+ sourceLineStartOffsetsCache?: number[];
23
+ /** Rest props configuration (e.g., `$$restProps`) if present in component */
24
+ rest_props?: RestProps;
25
+ /** Component extension information (e.g., `extends` attribute) */
26
+ extends?: Extends;
27
+ /** Custom-element tag name from `<svelte:options customElement="x-foo" />` (or the object form's `tag`), when present */
28
+ customElementTag?: string;
29
+ /** Component-level description extracted from `@component` HTML comment */
30
+ componentComment?: string;
31
+ /** Source range for the `@component` HTML comment, when available */
32
+ componentCommentSource?: SourceRange;
33
+ /** Component generic type parameters (null if no generics) */
34
+ generics: ComponentGenerics;
35
+ /**
36
+ * Raw `generics` script attribute value (with `lang="ts"` already validated),
37
+ * held until the end of parsing so it can override any `@generics`/`@template`
38
+ * JSDoc-derived {@link ParserContext.generics}.
39
+ */
40
+ scriptGenericsAttribute?: {
41
+ value: string;
42
+ source?: SourceRange;
43
+ };
44
+ /** Diagnostics for the parse in progress. */
45
+ readonly diagnosticRecords: SveldDiagnostic[];
46
+ /** File path tagged onto each diagnostic. */
47
+ componentFilePath: string;
48
+ /** Map of component props keyed by prop name */
49
+ readonly props: Map<string, ComponentProp>;
50
+ /** Map of module exports (functions/variables exported from script) keyed by name */
51
+ readonly moduleExports: Map<string, ComponentProp>;
52
+ /** Maps local binding names back to their public prop names */
53
+ readonly propLocalToPublicName: Map<string, string>;
54
+ /** Set of reactive variable names found in the component */
55
+ readonly reactive_vars: Set<string>;
56
+ /** Function declarations in the component script, by name */
57
+ readonly funcDecls: Map<string, FunctionDeclaration>;
58
+ /** Set of all variable declarations found in the component script */
59
+ readonly vars: Set<VariableDeclaration>;
60
+ /** Per-declarator type metadata extracted from modern AST `$props()` annotations */
61
+ readonly runesPropsDeclarationMetadataByDeclaratorStart: Map<number, RunesPropsDeclarationMetadata>;
62
+ /** Typed `$props()` declarations discovered in source order */
63
+ readonly typedRunesPropsDeclarations: RunesPropsDeclarationMetadata[];
64
+ /** Explicit TypeScript prop annotations for legacy `export let` declarations keyed by local name */
65
+ readonly explicitPropTypesByName: Map<string, string>;
66
+ /** Type-only imports keyed by their local binding names */
67
+ readonly typeImportBindingsByLocalName: Map<string, TypeImportBinding>;
68
+ /** Local interface/type declarations keyed by type name */
69
+ readonly localTypeDeclarationsByName: Map<string, LocalTypeDeclaration>;
70
+ /** Tracks identifier bindings that capture the entire `$props()` object */
71
+ readonly wholePropsLocals: Set<string>;
72
+ /** Tracks `$props()` bindings that are used as spread/rest props */
73
+ readonly restPropLocals: Set<string>;
74
+ /** Component-level lexical scope shared by instance script and template */
75
+ readonly componentScope: LexicalScope;
76
+ /** Precomputed lexical scopes for nested AST nodes */
77
+ scopeDeclarations: WeakMap<object, LexicalScope>;
78
+ /** Active lexical scopes while walking the component AST */
79
+ readonly activeScopes: LexicalScope[];
80
+ /** Map of component slots keyed by slot name (null for default slot) */
81
+ readonly slots: Map<string | null, InternalComponentSlot>;
82
+ /** Tracks prop locals that are used as snippet/render props */
83
+ readonly snippetPropLocals: Set<string>;
84
+ /** @template tags in a @slot/@snippet block (no @extends), held until finalization. */
85
+ deferredSlotBlockGenerics: Array<{
86
+ name: string;
87
+ constraint: string;
88
+ }>;
89
+ /** Map of component events (dispatched events) keyed by event name */
90
+ readonly events: Map<string, ComponentEvent>;
91
+ /** Map of event descriptions extracted from JSDoc comments keyed by event name */
92
+ readonly eventDescriptions: Map<string, string | undefined>;
93
+ /** Map of forwarded events (events forwarded from child components) keyed by event name */
94
+ readonly forwardedEvents: Map<string, ComponentInlineElement | ComponentElement>;
95
+ /** `@event` names from JSDoc, checked against dispatches at end of parse. */
96
+ readonly jsDocEventNames: Set<string>;
97
+ /** Source range of each `@event` JSDoc tag, keyed by event name, for `event-no-source` diagnostics. */
98
+ readonly jsDocEventSources: Map<string, SourceRange | undefined>;
99
+ /** Map of prop bindings (e.g., `bind:value`) keyed by prop name */
100
+ readonly bindings: Map<string, ComponentPropBindings>;
101
+ /** Map of component contexts (created with `setContext`) keyed by context name */
102
+ readonly contexts: Map<string, ComponentContext>;
103
+ /** Map of type definitions (typedefs) extracted from JSDoc comments keyed by type name */
104
+ readonly typedefs: Map<string, TypeDef>;
105
+ /** Memoized `findVariableTypeAndDescription` results */
106
+ variableInfoCache: Map<string, {
107
+ type: string;
108
+ description?: string;
109
+ }>;
110
+ /** Whether {@link variableInfoCache} has been populated by a whole-source scan yet */
111
+ variableInfoCacheBuilt: boolean;
112
+ }
113
+ /** Fresh {@link ParserContext}. Keep in sync with new fields on {@link ParserContext}. */
114
+ export declare function createParserContext(): ParserContext;
@@ -0,0 +1,19 @@
1
+ import type { CallExpression, NewExpression } from "estree";
2
+ import type { Node } from "estree-walker";
3
+ import type ComponentParser from "../ComponentParser";
4
+ import type { ComponentContext } from "../ComponentParser";
5
+ import type { ParserContext } from "./context";
6
+ /** Turn `simple-modal` into `SimpleModalContext`. */
7
+ export declare function generateContextTypeName(key: string): string;
8
+ /** Build a {@link ComponentContext} from an object literal or variable reference. */
9
+ export declare function parseContextValue(ctx: ParserContext, parser: ComponentParser, node: Node, key: string): ComponentContext | null;
10
+ /** Static description from `Symbol()` / `Symbol.for()`, or `""` when unknown. Returns `null` for other calls. */
11
+ export declare function resolveSymbolKeyDescription(node: CallExpression | NewExpression): string | null;
12
+ /**
13
+ * Resolve a `setContext` key to the string used in `{PascalCase}Context`.
14
+ * Accepts literals, static templates, `const` chains (depth 5), and `Symbol()`.
15
+ * Description-less symbols fall back to the binding name.
16
+ */
17
+ export declare function resolveContextKey(ctx: ParserContext, keyArg: unknown, depth?: number): string | null;
18
+ /** Parse `setContext(key, value)` when the key resolves statically. */
19
+ export declare function parseSetContextCall(ctx: ParserContext, parser: ComponentParser, node: Node, _parent?: Node): void;
@@ -0,0 +1,8 @@
1
+ import type { SourceRange } from "../ComponentParser";
2
+ import type { SveldDiagnosticKind } from "../diagnostics";
3
+ import type { ParserContext } from "./context";
4
+ /**
5
+ * Appends a diagnostic (a place sveld had to guess a type) to `ctx.diagnosticRecords`,
6
+ * tagged with the file path of the component currently being parsed.
7
+ */
8
+ export declare function recordDiagnostic(ctx: ParserContext, kind: SveldDiagnosticKind, name: string, message: string, source?: SourceRange): void;
@@ -0,0 +1,23 @@
1
+ import type { CallExpression } from "estree";
2
+ import type { DispatchedEvent } from "../ComponentParser";
3
+ import type { ParserContext } from "./context";
4
+ /** Render a literal event-detail value (from a `dispatch()`/`CustomEvent` argument) as TS type text, quoting strings. */
5
+ export declare function literalDetailToTypeText(value: unknown): string;
6
+ /** Merge or add a dispatched event. Detail defaults to `null` when the dispatch has no argument and no `@event` detail. */
7
+ export declare function addDispatchedEvent(ctx: ParserContext, { name, detail, has_argument, description, deprecated, tags, source, }: Pick<DispatchedEvent, "name" | "description" | "deprecated" | "tags" | "source"> & {
8
+ detail: string;
9
+ has_argument: boolean;
10
+ }): void;
11
+ /**
12
+ * Detect `$host().dispatchEvent(new CustomEvent("name", { detail }))` (or `new Event(...)`) and
13
+ * record it as a dispatched event, mirroring `createEventDispatcher()` detection.
14
+ */
15
+ export declare function parseHostDispatchEventCall(ctx: ParserContext, dispatchEventCall: CallExpression): string | undefined;
16
+ /** Build an inline object type (with optional JSDoc per property) for event details or typedefs. */
17
+ export declare function buildEventDetailFromProperties(properties: Array<{
18
+ name: string;
19
+ type: string;
20
+ description?: string;
21
+ optional?: boolean;
22
+ default?: string;
23
+ }>, _eventName?: string, multiline?: boolean): string;
@@ -0,0 +1,24 @@
1
+ import type { ComponentGenerics } from "../ComponentParser";
2
+ import type { ParserContext } from "./context";
3
+ /**
4
+ * Splits a string on top-level commas, ignoring commas nested inside
5
+ * `<>`, `()`, `[]`, or `{}`. Shared by the `generics` script attribute parser
6
+ * and the TypeScript definition writer, both of which must separate generic
7
+ * constraint declarations that may themselves contain commas (e.g. `Value extends Record<string, any>`).
8
+ */
9
+ export declare function splitTopLevelCommas(value: string): string[];
10
+ /**
11
+ * Parses the `generics` script attribute value (a TypeScript type-parameter
12
+ * list, e.g. `"Row extends DataTableRow = DataTableRow, Header"`) into the
13
+ * same `[names, constraints]` tuple the `@generics`/`@template` JSDoc tags produce.
14
+ */
15
+ export declare function parseGenericsAttribute(value: string): ComponentGenerics;
16
+ /**
17
+ * Extends `referencedImportedTypes`/`referencedLocalTypes` with any type names
18
+ * mentioned in the `generics` script attribute (e.g. the `DataTableRow` in
19
+ * `Row extends DataTableRow = DataTableRow`). These names only appear in the
20
+ * raw attribute string, not in the `$props()` type annotation AST that
21
+ * {@link collectReferencedTypeDependencies} normally walks, so without this
22
+ * they would never get hoisted into the emitted `.d.ts`.
23
+ */
24
+ export declare function collectGenericsAttributeTypeDependencies(ctx: ParserContext, referencedImportedTypes: Set<string>, referencedLocalTypes: Set<string>): void;
@@ -0,0 +1,59 @@
1
+ import { parse as parseComment } from "comment-parser";
2
+ import type ComponentParser from "../ComponentParser";
3
+ import type { ComponentPropBinding, ComponentPropParam, DeprecatedValue, JsDocPassthroughTag } from "../ComponentParser";
4
+ import type { ParserContext } from "./context";
5
+ export declare function formatComment(comment: string): string;
6
+ /** Split JSDoc tags into type/param/returns/passthrough buckets. */
7
+ export declare function getCommentTags(parsed: ReturnType<typeof parseComment>): {
8
+ type: import("comment-parser").Spec | undefined;
9
+ param: import("comment-parser").Spec[];
10
+ returns: import("comment-parser").Spec | undefined;
11
+ binding: ComponentPropBinding | undefined;
12
+ deprecated: DeprecatedValue | undefined;
13
+ additional: import("comment-parser").Spec[];
14
+ passthrough: import("comment-parser").Spec[];
15
+ description: string;
16
+ };
17
+ /** Last leading comment (JSDoc when present). TypeScript directives are stripped first. */
18
+ export declare function findJSDocComment(leadingComments: unknown[]): {
19
+ value: string;
20
+ } | undefined;
21
+ export declare function findAdjacentJSDocComment(ctx: ParserContext, leadingComments: unknown[] | undefined, nodeStart: number | undefined): {
22
+ value: string;
23
+ } | undefined;
24
+ export declare function processNodeJSDoc(ctx: ParserContext, parser: ComponentParser, node: {
25
+ leadingComments?: unknown[];
26
+ start?: number;
27
+ } | null | undefined): {
28
+ type?: string;
29
+ params?: ComponentPropParam[];
30
+ returnType?: string;
31
+ description?: string;
32
+ binding?: ComponentPropBinding;
33
+ deprecated?: DeprecatedValue;
34
+ tags?: JsDocPassthroughTag[];
35
+ } | undefined;
36
+ export declare function processLeadingCommentsJSDoc(ctx: ParserContext, parser: ComponentParser, node: {
37
+ leadingComments?: unknown[];
38
+ start?: number;
39
+ } | null | undefined): {
40
+ type?: string;
41
+ params?: ComponentPropParam[];
42
+ returnType?: string;
43
+ description?: string;
44
+ binding?: ComponentPropBinding;
45
+ deprecated?: DeprecatedValue;
46
+ tags?: JsDocPassthroughTag[];
47
+ } | undefined;
48
+ /** Parse adjacent JSDoc into type, params, returns, description, and passthrough tags. */
49
+ export declare function processJSDocComment(parser: ComponentParser, leadingComments: unknown[]): {
50
+ type?: string;
51
+ params?: ComponentPropParam[];
52
+ returnType?: string;
53
+ description?: string;
54
+ binding?: ComponentPropBinding;
55
+ deprecated?: DeprecatedValue;
56
+ tags?: JsDocPassthroughTag[];
57
+ } | undefined;
58
+ /** Scan source JSDoc for events, typedefs, callbacks, slots, extends, and generics. */
59
+ export declare function parseCustomTypes(ctx: ParserContext, parser: ComponentParser): void;
@@ -0,0 +1,73 @@
1
+ import type { ArrowFunctionExpression, FunctionDeclaration, FunctionExpression } from "estree";
2
+ import type ComponentParser from "../ComponentParser";
3
+ import type { ComponentProp, ComponentPropParam, ProcessedInitializer } from "../ComponentParser";
4
+ import type { ParserContext } from "./context";
5
+ /** Merge a prop into `ctx.props`, or add it if missing. */
6
+ export declare function addProp(parser: ComponentParser, ctx: ParserContext, prop_name: string, data: ComponentProp): void;
7
+ /** Read value, type, and function-ness from a prop initializer expression. */
8
+ export declare function processInitializer(parser: ComponentParser, ctx: ParserContext, init: unknown, depth?: number): ProcessedInitializer;
9
+ /**
10
+ * Look up a local variable's initializer AST node by name.
11
+ * Returns the init node if found, or undefined.
12
+ */
13
+ export declare function resolveLocalVarInitializer(ctx: ParserContext, name: string): unknown | undefined;
14
+ /**
15
+ * Look up the initializer for a local `const` by name.
16
+ *
17
+ * {@link resolveLocalVarInitializer} also walks `let`/`var`. This method does not.
18
+ * Props and mutable bindings can change at runtime, so they cannot be context keys.
19
+ *
20
+ * @param name - The variable name to look up
21
+ * @returns The initializer node for a matching `const` binding, or undefined
22
+ */
23
+ export declare function resolveConstInitializer(ctx: ParserContext, name: string): unknown | undefined;
24
+ /**
25
+ * Build a function type from `@param`/`@returns` when `@type` is missing.
26
+ * If JSDoc has no params or return either, try the function `node`, then
27
+ * `(...args: any[]) => any`.
28
+ */
29
+ export declare function buildFunctionTypeFromParts(jsdoc?: {
30
+ params?: ComponentPropParam[];
31
+ returnType?: string;
32
+ }, node?: FunctionDeclaration | FunctionExpression | ArrowFunctionExpression): string;
33
+ /**
34
+ * Guess arity and return type for a function default with no JSDoc `@type`.
35
+ * Explicit `@type`/`@param`/`@returns` on the prop beat this every time.
36
+ * A default's body is a weak signal for the prop contract. We only read
37
+ * named params and literal returns. Everything else becomes `any`.
38
+ */
39
+ export declare function inferFunctionTypeFromNode(node: FunctionDeclaration | FunctionExpression | ArrowFunctionExpression): string;
40
+ /**
41
+ * Turn params into `name: any`, or use `...args: any[]` when arity is unclear:
42
+ * no params, destructuring, rest, or defaults.
43
+ */
44
+ export declare function inferParamsFromNode(node: FunctionDeclaration | FunctionExpression | ArrowFunctionExpression): string;
45
+ /**
46
+ * Infer return type from literal returns only. Every `return` must agree on
47
+ * the same primitive. Bare `return;`, no returns, identifiers, calls,
48
+ * objects, ternaries, async, or generators all become `any`.
49
+ */
50
+ export declare function inferReturnTypeFromNode(node: FunctionDeclaration | FunctionExpression | ArrowFunctionExpression): string;
51
+ /**
52
+ * Walk a block body and collect each `return`'s argument, skipping nested
53
+ * functions. Bare `return;` becomes `null`.
54
+ *
55
+ * Not fused with the componentRoot walk: this runs from `processInitializer`, called
56
+ * synchronously while the outer walk is still on the ancestor `ExportNamedDeclaration`/
57
+ * `VariableDeclaration` node, so it needs the inferred type before the outer walk would
58
+ * otherwise reach these descendant statements. Deferring it to ride along with the outer
59
+ * traversal would mean computing prop types in a second pass instead of inline.
60
+ */
61
+ export declare function collectReturnArguments(body: unknown): unknown[];
62
+ /**
63
+ * Map one return expression to `string`, `number`, or `boolean`, or `null`
64
+ * if it isn't a literal, template literal, or `String`/`Number`/`Boolean` call.
65
+ */
66
+ export declare function inferReturnPrimitive(expr: unknown): "string" | "number" | "boolean" | null;
67
+ /**
68
+ * Unwraps `$bindable(...)` calls so defaults are documented as their underlying values.
69
+ */
70
+ export declare function unwrapBindableInitializer(init: unknown): {
71
+ init?: unknown;
72
+ bindable: boolean;
73
+ };
@@ -0,0 +1,6 @@
1
+ import type { RestProps } from "../ComponentParser";
2
+ import type { ParserContext } from "./context";
3
+ /** {@link RestProps} for the parent of a `{...$$restProps}` spread. */
4
+ export declare function createRestPropsFromParent(parent: unknown): RestProps;
5
+ /** Record the first `{...$$restProps}` target on `ctx.rest_props`. */
6
+ export declare function maybeSetRestProps(ctx: ParserContext, parent: unknown): void;
@@ -0,0 +1,16 @@
1
+ import type { SyntaxMode } from "../ComponentParser";
2
+ import type { ParserContext } from "./context";
3
+ /**
4
+ * Determines a component's syntax mode without running the svelte compiler's analyze phase.
5
+ *
6
+ * Mirrors `analyze_component`'s own logic (`node_modules/svelte/src/compiler/phases/2-analyze/index.js`):
7
+ * an explicit `<svelte:options runes={...} />` always wins; otherwise the component is in runes
8
+ * mode if any rune name is referenced - and not shadowed by a local declaration of the same name -
9
+ * anywhere in the module script, instance script, or template.
10
+ *
11
+ * Known simplification: svelte also force-enables runes mode on top-level `await` (blocking awaits
12
+ * outside of any function). No sveld fixture exercises that path, so it's intentionally not
13
+ * replicated here; a component relying solely on top-level `await` to opt into runes mode (with no
14
+ * other rune usage and no explicit `svelte:options`) would be misdetected as legacy.
15
+ */
16
+ export declare function detectSyntaxMode(ctx: ParserContext): SyntaxMode;
@@ -0,0 +1,18 @@
1
+ import type { VariableDeclaration } from "estree";
2
+ import type ComponentParser from "../ComponentParser";
3
+ import type { ModernRunesTypeNode, RunesPropTypeMetadata } from "../ComponentParser";
4
+ import type { ParserContext } from "./context";
5
+ /** Flatten a runes `$props()` type node into prop name -> metadata, following local aliases and intersections. */
6
+ export declare function buildRunesPropTypeMetadataMap(parser: ComponentParser, ctx: ParserContext, typeNode: ModernRunesTypeNode | undefined, localTypeDeclarations: Map<string, ModernRunesTypeNode>, visitedTypeNames?: Set<string>): Map<string, RunesPropTypeMetadata>;
7
+ /**
8
+ * Re-parse `ctx.source` in modern AST mode before the legacy walk: type imports,
9
+ * local types, explicit `export let` annotations, and `$props()` metadata.
10
+ */
11
+ export declare function buildRunesPropTypeMetadata(parser: ComponentParser, ctx: ParserContext): void;
12
+ /** Top-level `$props()` declarations in runes components. */
13
+ export declare function parseRunesPropsDeclaration(parser: ComponentParser, ctx: ParserContext, node: VariableDeclaration): void;
14
+ /**
15
+ * Runes-only: fold phantom `@event` entries into matching `on<Event>` callback props
16
+ * when nothing in the component actually dispatches that event.
17
+ */
18
+ export declare function normalizeRunesCallbackProps(ctx: ParserContext, actuallyDispatchedEvents: Set<string>): void;
@@ -0,0 +1,58 @@
1
+ import type { ArrowFunctionExpression, Expression, FunctionDeclaration, FunctionExpression, Pattern, VariableDeclaration, VariableDeclarator } from "estree";
2
+ import type ComponentParser from "../ComponentParser";
3
+ import type { LexicalScope, ScopeBinding, ScopeBindingKind } from "../ComponentParser";
4
+ import type { ParserContext } from "./context";
5
+ /** Declares `name` into `scope` unless it's empty/already bound (first declaration wins). */
6
+ export declare function declareScopeBinding(scope: LexicalScope, name: string, binding: ScopeBinding): void;
7
+ /** Resolves `name` to its public prop name by walking active scopes innermost-first. */
8
+ export declare function resolveIdentifierToReactiveProp(ctx: ParserContext, name: string): string | undefined;
9
+ /** Collects all identifier names bound by a destructuring/assignment pattern (or plain expression). */
10
+ export declare function collectPatternIdentifiers(target: Pattern | Expression | null | undefined, names?: Set<string>): Set<string>;
11
+ /** Marks any reactive props referenced by a mutation target (assignment LHS / update argument) as reactive. */
12
+ export declare function markReactivePropsFromMutationTarget(ctx: ParserContext, target: Pattern | Expression | null | undefined): void;
13
+ /** True for AST/Svelte node types that introduce a new lexical scope. */
14
+ export declare function isScopeOwner(node: unknown): boolean;
15
+ /** True for node types that introduce a new `var`-hoisting (function) scope. */
16
+ export declare function isFunctionScopeOwner(node: unknown): boolean;
17
+ /** Returns the scope map for `node`, creating and caching an empty one on first access. */
18
+ export declare function getOrCreateScope(ctx: ParserContext, node: object): LexicalScope;
19
+ /** Scope bindings from `const { a, b: c } = $props()`. Destructured props are `prop`; rest is `local`. */
20
+ export declare function extractRunesScopeBindings(parser: ComponentParser, _node: VariableDeclaration, declarator: VariableDeclarator): {
21
+ kind: ScopeBindingKind;
22
+ name: string;
23
+ publicPropName?: string;
24
+ }[];
25
+ /** Declares bindings for every declarator in a `var`/`let`/`const` declaration into the appropriate scope. */
26
+ export declare function declareVariableDeclaration(parser: ComponentParser, declaration: unknown, lexicalScope: LexicalScope, varScope: LexicalScope, options?: {
27
+ allowRunesProps?: boolean;
28
+ forceProp?: boolean;
29
+ }): void;
30
+ /** Declares a function-like node's own name (if any) and its parameter bindings into `scope`. */
31
+ export declare function declareFunctionLikeScopeBindings(node: FunctionExpression | ArrowFunctionExpression | FunctionDeclaration, scope: LexicalScope): void;
32
+ /** Declares top-level `var`/`function`/`class` bindings directly within a block's statement list. */
33
+ export declare function collectDirectBlockDeclarations(parser: ComponentParser, body: unknown, lexicalScope: LexicalScope, varScope: LexicalScope): void;
34
+ /** Declares all component-instance-level (`<script>`) bindings into `ctx.componentScope`. */
35
+ export declare function collectComponentScopeDeclarations(parser: ComponentParser, ctx: ParserContext, instance: unknown): void;
36
+ /**
37
+ * Resets `ctx.componentScope` / `ctx.scopeDeclarations` / `ctx.activeScopes` and declares the
38
+ * top-level `<script>` bindings. Does not walk the component tree; nested scope declarations are
39
+ * built incrementally by {@link enterNestedScopeDeclarationNode} inside the caller's own traversal
40
+ * of `componentRoot` (fused with prop/slot/event extraction there rather than walked separately).
41
+ */
42
+ export declare function initComponentScope(parser: ComponentParser, ctx: ParserContext): void;
43
+ /** Mutable stack tracking the enclosing `var`-hoisting scope while walking `componentRoot`. */
44
+ export type ScopeWalkState = {
45
+ varScopeStack: LexicalScope[];
46
+ };
47
+ /** Creates the scope-walk state for a fresh traversal of `componentRoot`, seeded with `ctx.componentScope`. */
48
+ export declare function createScopeWalkState(ctx: ParserContext): ScopeWalkState;
49
+ /**
50
+ * Per-node `enter` step of the (formerly standalone) nested-scope-declaration walk. Declares
51
+ * bindings for `node` if it's a scope owner and pushes it as the active `var` scope for its
52
+ * descendants. Must be called during the same top-down traversal of `componentRoot` that
53
+ * {@link leaveNestedScopeDeclarationNode} tears down, and before any logic that reads
54
+ * `ctx.scopeDeclarations` for `node` itself (its own scope is only created here, on entry).
55
+ */
56
+ export declare function enterNestedScopeDeclarationNode(parser: ComponentParser, ctx: ParserContext, state: ScopeWalkState, node: unknown): void;
57
+ /** Per-node `leave` step counterpart to {@link enterNestedScopeDeclarationNode}. */
58
+ export declare function leaveNestedScopeDeclarationNode(state: ScopeWalkState, node: unknown): void;
@@ -0,0 +1,29 @@
1
+ import type { Expression, ObjectExpression } from "estree";
2
+ import type ComponentParser from "../ComponentParser";
3
+ import type { DeprecatedValue, JsDocPassthroughTag, SlotProps, SlotPropValue, SourceRange } from "../ComponentParser";
4
+ import type { ParserContext } from "./context";
5
+ /** Infer a slot prop value/type from an expression (identifier, literal, member access, or source text). */
6
+ export declare function inferSlotPropValueFromExpression(ctx: ParserContext, parser: ComponentParser, expression: unknown): SlotPropValue;
7
+ /** Slot props from an object expression, e.g. `{@render mySnippet({ foo: 1 })}`. */
8
+ export declare function buildSlotPropsFromObjectExpression(ctx: ParserContext, parser: ComponentParser, expression: ObjectExpression): SlotProps;
9
+ /** Snippet prop behind `{@render children()}` or `{@render props.children()}`. */
10
+ export declare function resolveRenderTagPropReference(ctx: ParserContext, callee: unknown): {
11
+ publicName: string;
12
+ trackingName: string;
13
+ } | null;
14
+ /** Callee and arguments from a `{@render ...}` expression (unwraps `ChainExpression` first). */
15
+ export declare function extractRenderTagInfo(ctx: ParserContext, expression: unknown): {
16
+ publicName: string;
17
+ trackingName: string;
18
+ arguments: Array<Expression | unknown>;
19
+ } | null;
20
+ /** Merge or add a slot. Empty `slot_name` is the default slot. */
21
+ export declare function addSlot(ctx: ParserContext, { slot_name, slot_props, slot_fallback, slot_description, slot_deprecated, slot_tags, source, }: {
22
+ slot_name?: string;
23
+ slot_props?: string | SlotProps;
24
+ slot_fallback?: string;
25
+ slot_description?: string;
26
+ slot_deprecated?: DeprecatedValue;
27
+ slot_tags?: JsDocPassthroughTag[];
28
+ source?: SourceRange;
29
+ }): void;
@@ -0,0 +1,30 @@
1
+ import type { SourcePosition, SourceRange } from "../ComponentParser";
2
+ import type { ParserContext } from "./context";
3
+ /**
4
+ * Returns (and lazily computes/caches on `ctx`) the 0-based source offset for
5
+ * the start of each line in `ctx.source`.
6
+ */
7
+ export declare function getSourceLineStartOffsets(ctx: ParserContext): number[];
8
+ /** Converts a 0-based source offset into a 1-based line / 0-based column {@link SourcePosition}. */
9
+ export declare function sourcePositionFromOffset(ctx: ParserContext, offset: number): SourcePosition | undefined;
10
+ /** Converts a pair of 0-based source offsets into a {@link SourceRange}. */
11
+ export declare function sourceRangeFromOffsets(ctx: ParserContext, start: number | undefined, end: number | undefined): SourceRange | undefined;
12
+ /** Converts an AST node's `start`/`end` offsets into a {@link SourceRange}. */
13
+ export declare function sourceRangeFromNode(ctx: ParserContext, node: unknown): SourceRange | undefined;
14
+ /**
15
+ * Computes the {@link SourceRange} for a JSDoc tag within a parsed comment
16
+ * block, given the block's own source lines and starting offset.
17
+ */
18
+ export declare function sourceRangeFromCommentTag(ctx: ParserContext, blockSource: Array<{
19
+ number: number;
20
+ source: string;
21
+ }>, tagSource: Array<{
22
+ number: number;
23
+ source: string;
24
+ tokens: {
25
+ tag?: string;
26
+ };
27
+ }> | undefined, blockStartOffset: number | undefined): SourceRange | undefined;
28
+ export declare function sourceAtPos(ctx: ParserContext, start: number, end: number): string | undefined;
29
+ /** Source text for an expression, newlines collapsed to one line. */
30
+ export declare function sourceForExpression(ctx: ParserContext, node: unknown): string | undefined;
@@ -0,0 +1,32 @@
1
+ import type { ModernRunesTypeNode, ParsedComponentTypeScriptMetadata } from "../ComponentParser";
2
+ import type { ParserContext } from "./context";
3
+ /**
4
+ * Looks up the modern-runes `$props()` declaration metadata recorded for the
5
+ * declarator starting at `declaratorStart`, if any.
6
+ */
7
+ export declare function getRunesPropsDeclarationMetadata(ctx: ParserContext, declaratorStart: number | undefined): import("../ComponentParser").RunesPropsDeclarationMetadata | undefined;
8
+ /**
9
+ * Looks up the per-prop type metadata (optionality, source range, type text)
10
+ * for `propName` within the `$props()` declaration starting at `declaratorStart`.
11
+ */
12
+ export declare function getRunesPropTypeMetadata(ctx: ParserContext, declaratorStart: number | undefined, propName: string): import("../ComponentParser").RunesPropTypeMetadata | undefined;
13
+ /** Rightmost name from a type reference (`Foo` or `NS.Foo`). */
14
+ export declare function getTypeReferenceName(typeName: unknown): string | undefined;
15
+ /** Leftmost name from a type reference, for import/local lookup. */
16
+ export declare function getTypeDependencyName(typeName: unknown): string | undefined;
17
+ /** Returns the trimmed source text spanned by a type annotation node, if positions are available. */
18
+ export declare function getTypeAnnotationText(ctx: ParserContext, typeAnnotation: {
19
+ start?: number;
20
+ end?: number;
21
+ } | undefined): string | undefined;
22
+ /** Returns the trimmed source text spanned by a bare type node (no leading `:`), if positions are available. */
23
+ export declare function getTypeNodeText(ctx: ParserContext, typeNode: {
24
+ start?: number;
25
+ end?: number;
26
+ } | undefined): string | undefined;
27
+ /** Collect imported and local type names referenced by a type AST node. */
28
+ export declare function collectReferencedTypeDependencies(ctx: ParserContext, typeNode: ModernRunesTypeNode | undefined, referencedImportedTypes: Set<string>, referencedLocalTypes: Set<string>, visitedLocalTypes?: Set<string>): void;
29
+ /** Emit `import type` statements for referenced type names, grouped by module. */
30
+ export declare function buildTypeImportStatements(ctx: ParserContext, referencedImportedTypes: Set<string>): string[];
31
+ /** `ParsedComponentTypeScriptMetadata` for a single typed `$props()` declaration, if any. */
32
+ export declare function buildTypeScriptMetadata(ctx: ParserContext): ParsedComponentTypeScriptMetadata | undefined;
@@ -0,0 +1,2 @@
1
+ /** In-place: replaces every `expr as T` / `expr satisfies T` / `expr!` / `<T>expr` / `expr<T>` with `expr`. */
2
+ export declare function stripTypeCastWrappers(root: unknown): void;
package/lib/plugin.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { type GenerateBundleOptions, type GenerateBundleResult } from "./bundle";
2
2
  import "./writer/built-in-writers";
3
+ import type { WriteCustomElementsOptions } from "./writer/writer-custom-elements";
3
4
  import type { WriteJsonOptions } from "./writer/writer-json";
4
5
  import type { WriteMarkdownOptions } from "./writer/writer-markdown";
5
6
  import type { WriteTsDefinitionsOptions } from "./writer/writer-ts-definitions";
@@ -20,6 +21,9 @@ export interface PluginSveldOptions extends Pick<GenerateBundleOptions, "resolve
20
21
  jsonOptions?: Partial<Omit<WriteJsonOptions, "inputDir">>;
21
22
  markdown?: boolean;
22
23
  markdownOptions?: Partial<WriteMarkdownOptions>;
24
+ /** Generate a Custom Elements Manifest (`custom-elements.json`, schemaVersion "1.0.0"). */
25
+ customElements?: boolean;
26
+ customElementsOptions?: Partial<Omit<WriteCustomElementsOptions, "inputDir">>;
23
27
  /**
24
28
  * Run additional, userland-registered writers (via `registerWriter` from
25
29
  * "sveld") beyond the built-in `json`/`markdown`/`types` outputs. Keyed by
@@ -50,7 +54,7 @@ interface SveldPlugin {
50
54
  enforce?: "pre" | "post";
51
55
  buildStart(): void | Promise<void>;
52
56
  generateBundle(): Promise<void>;
53
- writeBundle(): void;
57
+ writeBundle(): Promise<void>;
54
58
  /** Vite dev-server HMR hook (serve mode). */
55
59
  handleHotUpdate?(ctx: HotUpdateContext): void;
56
60
  /** Rollup/Vite watch hook (build `--watch`). */
@@ -70,7 +74,7 @@ export default function pluginSveld(opts?: PluginSveldOptions): SveldPlugin;
70
74
  *
71
75
  * @example
72
76
  * ```ts
73
- * writeOutput(result, {
77
+ * await writeOutput(result, {
74
78
  * types: true,
75
79
  * json: true,
76
80
  * markdown: true
@@ -78,4 +82,4 @@ export default function pluginSveld(opts?: PluginSveldOptions): SveldPlugin;
78
82
  * // Generates: types/*.d.ts, COMPONENT_API.json, COMPONENT_INDEX.md
79
83
  * ```
80
84
  */
81
- export declare function writeOutput(result: GenerateBundleResult, opts: PluginSveldOptions, input: string): void;
85
+ export declare function writeOutput(result: GenerateBundleResult, opts: PluginSveldOptions, input: string): Promise<void>;
@@ -23,6 +23,7 @@ export interface ExampleCheckDiagnostic {
23
23
  export declare class TypeResolver {
24
24
  private readonly api;
25
25
  private readonly symbolFlags;
26
+ private readonly typeFlags;
26
27
  private readonly tsconfigPath;
27
28
  private readonly overlay;
28
29
  private constructor();
@@ -45,7 +46,6 @@ export declare class TypeResolver {
45
46
  checkExamples(targets: ExampleCheckTarget[]): Promise<Map<string, ExampleCheckDiagnostic[]>>;
46
47
  /** Closes the TypeScript server process. */
47
48
  dispose(): Promise<void>;
48
- private resolveFile;
49
49
  private createFileSystem;
50
50
  private virtualFileName;
51
51
  private exampleFileName;