sveld 0.37.2 → 0.37.4

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.
package/README.md CHANGED
@@ -302,7 +302,7 @@ Without `resolveTypes`, JSON lists no props. With it, each field shows up with `
302
302
 
303
303
  ### Persistent parse cache (`cache`)
304
304
 
305
- Parsed output is written to disk and reused when the source file has not changed, on by default. That applies across runs, including CI on a fresh checkout.
305
+ Parsed output is written to disk and reused when the source file has not changed, on by default. That applies across runs, including CI on a fresh checkout. Generated `.d.ts` text is cached the same way, but is only reused when the component source _and_ every `typesOptions` value that affects output (for example [`format`](#dts-output-format-typesoptionsformat)) are unchanged; changing any of them regenerates that component's `.d.ts` without invalidating its cached parse.
306
306
 
307
307
  ```ts
308
308
  await sveld({ json: true });
@@ -435,7 +435,8 @@ Every diagnostic carries a stable, namespaced `code` (`"sveld/<kind>"`) alongsid
435
435
  | `sveld/rest-props-unresolved` | `warning` | Spread `$$restProps` onto a plain element (or `svelte:element`) instead of a component, or add an `@restProps` tag to type it manually. |
436
436
  | `sveld/context-duplicate-key` | `warning` | Remove the duplicate `setContext` call, or give it a distinct key; only the first call's shape is used. |
437
437
  | `sveld/spread-unresolved` | `warning` | Spread a local object literal or a variable with a resolvable type instead; otherwise the spread widens the generated type to `Record<string, any>`. |
438
- | `sveld/export-unresolved` | `warning` | Export a local declaration directly instead of re-exporting an import or a binding from another file; sveld only resolves exports of a local declaration. |
438
+ | `sveld/export-unresolved` | `warning` | Export a local declaration directly. Instance-script exports are props, so move a re-export (`export { x } from "..."`, or `export { x }` of an import) into `<script context="module">`, where sveld writes it to the `.d.ts` as-is. |
439
+ | `sveld/module-export-conflict` | `warning` | Rename the module-script export. `default` is always skipped (it collides with the component itself); a name matching the generated `<Name>Props`/`<Name>Exports` type breaks the `.d.ts` if the export carries a type. |
439
440
  | `sveld/extend-props-target-missing` | `error` | Point `@extends`/`@extendProps` at a file that exists, and (for a bundled `.svelte` target) name its generated `<Name>Props` interface exactly. |
440
441
  | `sveld/extend-props-duplicate` | `warning` | Remove the extra `@extends`/`@extendProps` tag; only the last one is used. |
441
442
  | `sveld/extend-props-override` | `warning` | Rename the own prop, or accept that it intentionally overrides the `@extends` target's prop of the same name. |
@@ -443,12 +444,14 @@ Every diagnostic carries a stable, namespaced `code` (`"sveld/<kind>"`) alongsid
443
444
  | `sveld/typedef-duplicate` | `warning` | Rename one of the `@typedef`/`@callback` declarations; only the later one is kept. |
444
445
  | `sveld/property-duplicate` | `warning` | Remove the duplicate `@property`; only the later one is kept. |
445
446
  | `sveld/generics-conflict` | `warning` | Rename one of the `@generics`/`@template` declarations to a distinct generic name. |
447
+ | `sveld/event-description-ambiguous` | `warning` | Put an event's description above its `@event` tag (or indent it as a continuation of the tag's line), or give each event its own comment block. Unindented text after an `@event` is read as the description of the tag below it. |
446
448
  | `sveld/jsdoc-tag-dropped` | `warning` | Move the tag next to a `@slot`/`@snippet`/`@event`/`@typedef`/`@callback` tag in the same comment block so it has something to attach to. |
447
449
  | `sveld/internal-typedef-referenced` | `error` | Remove `@internal`/`@ignore` from the referenced typedef, or stop referencing it from public type text (inline the shape, or make the referencing item `@internal` too). |
450
+ | `sveld/types-inline-unresolved` | `warning` | The import is kept as-is. Point it at a relative `.ts` file that exports a `type`/`interface`, or rename the colliding type. |
448
451
 
449
452
  #### Severity and `--strict=errors`
450
453
 
451
- Each diagnostic's `severity` is `"error"` (`example-compile-error`, `example-syntax-error`, `syntax-skipped`, `extend-props-target-missing`, `internal-typedef-referenced` — sveld emitted broken or unmodeled output) or `"warning"` (`prop-unknown-type`, `context-any-type`, `slot-missing-type`, `event-no-source`, `rest-props-unresolved`, `context-duplicate-key`, `spread-unresolved`, `export-unresolved`, `extend-props-duplicate`, `extend-props-override`, `jsdoc-unknown-tag`, `typedef-duplicate`, `property-duplicate`, `generics-conflict`, `jsdoc-tag-dropped` — a type fell back to `any`). Plain `strict: true` / `--strict` fails on both, unchanged from before. Pass `strict: "errors"` (or `--strict=errors`) to fail CI only on `error`-severity diagnostics, letting `any`-fallback warnings through:
454
+ Each diagnostic's `severity` is `"error"` (`example-compile-error`, `example-syntax-error`, `syntax-skipped`, `extend-props-target-missing`, `internal-typedef-referenced` — sveld emitted broken or unmodeled output) or `"warning"` (`prop-unknown-type`, `context-any-type`, `slot-missing-type`, `event-no-source`, `rest-props-unresolved`, `context-duplicate-key`, `spread-unresolved`, `export-unresolved`, `module-export-conflict`, `extend-props-duplicate`, `extend-props-override`, `jsdoc-unknown-tag`, `typedef-duplicate`, `property-duplicate`, `generics-conflict`, `event-description-ambiguous`, `jsdoc-tag-dropped`, `types-inline-unresolved` — a type fell back to `any`). Plain `strict: true` / `--strict` fails on both, unchanged from before. Pass `strict: "errors"` (or `--strict=errors`) to fail CI only on `error`-severity diagnostics, letting `any`-fallback warnings through:
452
455
 
453
456
  ```sh
454
457
  npx sveld --json --strict=errors
@@ -505,8 +508,9 @@ A bare `@sveld-ignore` (no code) suppresses every diagnostic for that symbol.
505
508
 
506
509
  - Node 22+ if your config is `sveld.config.js` or `sveld.config.mjs` — `sveld` declares no `engines.node` floor. A `sveld.config.ts` file loads via a raw `import()`, with no transpile step, so it only works if the runtime strips TypeScript itself: on Node this needs unflagged type stripping (Node 22.18 / 23.6+; on older Node 22 patches it's behind `--experimental-strip-types`, so use a `.js`/`.mjs` config instead), which is why Node 24 — the first current major where type stripping is always on — is the only reason to require it. Bun (see `.bun-version`) loads `.ts` configs without Node at all. CI runs on Bun and does not pin a Node version; the release workflow pins Node 24 for `actions/setup-node` on the npm publish job only, not a requirement for consumers.
507
510
  - `sveld` is ESM-only. `require("sveld")` does not work — use `import` or dynamic `import()`.
511
+ - The [persistent parse cache](#persistent-parse-cache-cache) hashes source with `node:crypto`'s one-shot `hash()`, which needs Node 22 (or Bun).
508
512
  - `sveld` bundles its own template parser to parse `.svelte` files, kept in parity with `svelte/compiler` (see [Approach](#approach)). Parsing does not depend on the Svelte version installed in your project, so Svelte 3 and Svelte 4 codebases parse the same way Svelte 5 codebases do — there is no compiler version to match up.
509
- - [`resolveTypes`](#opt-in-semantic-resolution-resolvetypes) and [`checkExamples`](#compile-checked-example-blocks-checkexamples) are optional and need `typescript` 7 or later (which provides `typescript/unstable/async`) plus a `tsconfig.json`. Everything else, including `.d.ts` generation, is AST-only and never loads TypeScript. If either is enabled and TypeScript can't be started (missing, too old, or no `tsconfig.json`), the run fails loudly: `sveld()` throws and the CLI exits `2` naming the requirement, rather than silently skipping the check.
513
+ - [`resolveTypes`](#opt-in-semantic-resolution-resolvetypes), [`checkExamples`](#compile-checked-example-blocks-checkexamples), and [`typesOptions.inline: "all"`](#typesoptionsinline) are optional and need `typescript` 7 or later (which provides `typescript/unstable/async`) plus a `tsconfig.json`. Everything else, including `.d.ts` generation and `typesOptions.inline: "local"`, is AST-only and never loads TypeScript. If any of the three is enabled and TypeScript can't be started (missing, too old, or no `tsconfig.json`), the run fails loudly: `sveld()` throws and the CLI exits `2` naming the requirement, rather than silently skipping the check. For `typesOptions.inline: "all"` this only actually triggers when there's a non-allow-listed bare import somewhere in the bundle to resolve; see [`typesOptions.inline`](#typesoptionsinline).
510
514
 
511
515
  ## Usage
512
516
 
@@ -592,7 +596,7 @@ npx sveld --json --markdown
592
596
 
593
597
  If no entry point can be resolved (no `package.json#svelte` field and no `--entry`), the CLI exits `1` and prints the reason to `stderr`. If `src/index.js` happens to exist relative to your working directory, sveld falls back to it and prints a one-line note asking you to set `package.json#svelte` (or `--entry`) instead of relying on the fallback.
594
598
 
595
- Flags are kebab-case: `--entry`, `--glob`, `--types`, `--json`, `--markdown`, `--custom-elements`, `--llms`, `--fail-fast`, `--dry-run`, `--cache`, `--resolve-types`, `--check-examples`, `--report-diagnostics`, `--strict`, `--check`, `--check-level`, `--types-format`, `--quiet`, `--stdout`, `--format`. The camelCase spellings `--resolveTypes` and `--checkExamples` still work as deprecated aliases for compatibility with existing scripts. `--entry`, `--cache`, `--check`, and `--types-format` take their value either as `--flag=value` or as a separate `--flag value` argument (`sveld --entry src/index.js` and `sveld --entry=src/index.js` are equivalent); if the next argument starts with `--` it's not consumed as a value, so `--cache` and `--check` fall back to their default location and `--entry` and `--types-format` report a usage error naming the flag. Boolean flags (`--json`, `--glob`, `--strict`, and the like) never consume a following argument. An unrecognized flag (e.g. `--markdwon`) prints `Unknown flag: --markdwon` to `stderr`, exits `1`, and skips generation; when a close match exists it appends a suggestion, e.g. `Unknown flag: --markdwon Did you mean --markdown?`. sveld takes no positional arguments, so any non-flag argument errors the same way.
599
+ Flags are kebab-case: `--entry`, `--glob`, `--types`, `--json`, `--markdown`, `--custom-elements`, `--llms`, `--fail-fast`, `--dry-run`, `--cache`, `--resolve-types`, `--check-examples`, `--report-diagnostics`, `--strict`, `--check`, `--check-level`, `--types-format`, `--types-export`, `--types-comments`, `--types-inline`, `--types-index-types`, `--types-props-declaration`, `--quiet`, `--stdout`, `--format`. The camelCase spellings `--resolveTypes` and `--checkExamples` still work as deprecated aliases for compatibility with existing scripts. `--entry`, `--cache`, `--check`, `--types-format`, `--types-export`, `--types-comments`, `--types-inline`, and `--types-props-declaration` take their value either as `--flag=value` or as a separate `--flag value` argument (`sveld --entry src/index.js` and `sveld --entry=src/index.js` are equivalent); if the next argument starts with `--` it's not consumed as a value, so `--cache` and `--check` fall back to their default location and the rest of that list report a usage error naming the flag. Boolean flags (`--json`, `--glob`, `--strict`, `--types-index-types`, and the like) never consume a following argument. An unrecognized flag (e.g. `--markdwon`) prints `Unknown flag: --markdwon` to `stderr`, exits `1`, and skips generation; when a close match exists it appends a suggestion, e.g. `Unknown flag: --markdwon Did you mean --markdown?`. sveld takes no positional arguments, so any non-flag argument errors the same way.
596
600
 
597
601
  Writer progress lines (`created "..."` / `unchanged "..."`) print to `stderr`, keeping `stdout` reserved for machine-readable data. Pass `--quiet` (or `quiet: true` in `sveld.config.*`) to suppress them; it does not suppress error messages, the diagnostics summary (`--report-diagnostics` / `--strict`), or the `--check` report.
598
602
 
@@ -923,6 +927,13 @@ The `svelte` condition lets bundlers that understand it (Vite, Rollup, webpack v
923
927
  - **`outDir`** (string, optional, default: `"types"`): Output directory for generated `.d.ts` files, relative to the project root.
924
928
  - **`preamble`** (string, optional, default: `""`): Raw text prepended to the top of the generated `index.d.ts` barrel file, before the `export * from "./..."` lines. Useful for license headers or lint-disable comments. See [`typesOptions.preamble`](#typesoptionspreamble) below.
925
929
  - **`format`** (`"class"` | `"component"`, optional, default: `"class"`): `.d.ts` output shape. `"class"` extends `SvelteComponentTyped`; `"component"` emits the Svelte 5 `Component` type. Also available as `--types-format`. See [`.d.ts` output format](#dts-output-format-typesoptionsformat).
930
+ - **`exportTypes`** (`boolean | { props?, exports?, typedefs?, contexts? }`, optional, default: `true`): Which generated type declarations get an `export` keyword. `false` keeps them all local to the `.d.ts` file; an object picks per kind. Also available as `--types-export=<all|none>` (the CLI can only set the boolean form, not the per-kind object). See [`typesOptions.exportTypes`](#typesoptionsexporttypes).
931
+ - **`typeNames`** (`{ props?: string; exports?: string }`, optional, default: `{ props: "{name}Props", exports: "{name}Exports" }`): Templates for generated type names. No CLI flag; config file or `sveld()` only. See [`typesOptions.typeNames`](#typesoptionstypenames).
932
+ - **`comments`** (`"all" | "descriptions" | "none"`, optional, default: `"all"`): How much JSDoc lands in the generated `.d.ts`. `"all"` keeps descriptions, `@deprecated`, `@default`, and passthrough tags (`@since`, `@see`, `@example`, `@link`); `"descriptions"` keeps descriptions and `@deprecated` only; `"none"` emits no comments at all. Also available as `--types-comments=<all|descriptions|none>`. See [`typesOptions.comments`](#typesoptionscomments).
933
+ - **`propsDeclaration`** (`"type" | "interface"`, optional, default: `"type"`): `"interface"` emits the props type as an `interface` instead of a `type` alias when the props are a plain object. Also available as `--types-props-declaration=<type|interface>`. See [`typesOptions.propsDeclaration`](#typesoptionspropsdeclaration).
934
+ - **`transform`** (function, optional): Post-processes each generated file's text before it is written. Runs after the generated-text cache, so it applies on every run. No CLI flag; config file or `sveld()` only. See [`typesOptions.transform`](#typesoptionstransform).
935
+ - **`indexTypes`** (`boolean | { props?, exports?, typedefs?, contexts? }`, optional, default: `false`): Also re-export generated types from `index.d.ts`. `true` re-exports each component's `Props` type (and `Exports` under `format: "component"`); an object can additionally include typedefs and contexts. Also available as `--types-index-types` (the CLI can only set the boolean form, not the per-kind object). See [`typesOptions.indexTypes`](#typesoptionsindextypes).
936
+ - **`inline`** (`false | "local" | "all"`, optional, default: `false`): Copies `type`/`interface` declarations imported from a relative source (or a tsconfig/jsconfig path alias) directly into the `.d.ts`, dropping the import. Also available as `--types-inline=<local|all>` (`--types-inline=false` resets to the default). See [`typesOptions.inline`](#typesoptionsinline).
926
937
  - **`json`** (boolean, optional): Generate component documentation in JSON format.
927
938
  - **`jsonOptions`** (object, optional): Options for JSON output.
928
939
  - **`outFile`** (string, optional, default: `"COMPONENT_API.json"`): Path (relative to the project root) for the single combined JSON document. Ignored when `outDir` is set.
@@ -990,6 +1001,390 @@ export { default as Button } from "./Button.svelte";
990
1001
 
991
1002
  `preamble` only affects the barrel file (`index.d.ts`); per-component `.d.ts` files are untouched.
992
1003
 
1004
+ #### `typesOptions.exportTypes`
1005
+
1006
+ Every type sveld generates is `export`ed by default. `typesOptions.exportTypes` lets a library keep some or all of them local to each component's `.d.ts` — useful when the props type is an implementation detail, or when it collides with a hand-written type of the same name in the package's own `index.d.ts`. Only the component itself needs to be public either way.
1007
+
1008
+ ```js
1009
+ sveld({
1010
+ types: true,
1011
+ typesOptions: {
1012
+ exportTypes: false,
1013
+ },
1014
+ });
1015
+ ```
1016
+
1017
+ **Button.svelte.d.ts** before:
1018
+
1019
+ ```ts
1020
+ export type ButtonProps = { label?: string };
1021
+
1022
+ export default class Button extends SvelteComponentTyped<
1023
+ ButtonProps,
1024
+ { click: WindowEventMap["click"] },
1025
+ { default: Record<string, never> }
1026
+ > {}
1027
+ ```
1028
+
1029
+ **Button.svelte.d.ts** after (`exportTypes: false`):
1030
+
1031
+ ```ts
1032
+ type ButtonProps = { label?: string };
1033
+
1034
+ export default class Button extends SvelteComponentTyped<
1035
+ ButtonProps,
1036
+ { click: WindowEventMap["click"] },
1037
+ { default: Record<string, never> }
1038
+ > {}
1039
+ ```
1040
+
1041
+ `Button` is still the only thing a consumer imports; `ButtonProps` is just no longer part of the public surface (it can still be referenced structurally — through `ComponentProps<typeof Button>`, for instance).
1042
+
1043
+ Pass an object instead of a boolean to pick per kind:
1044
+
1045
+ ```js
1046
+ typesOptions: {
1047
+ exportTypes: {
1048
+ props: false, // export type <Name>Props
1049
+ exports: true, // export type <Name>Exports (format: "component" only)
1050
+ typedefs: true, // export interface|type <Typedef> from @typedef
1051
+ contexts: true, // export type <Context> from setContext
1052
+ },
1053
+ }
1054
+ ```
1055
+
1056
+ Any key left out defaults to `true`.
1057
+
1058
+ `<script context="module">` exports (`export declare const` / `export declare function`) are real runtime exports and are always emitted as exports, regardless of `exportTypes`.
1059
+
1060
+ One exception: when a bundled component uses [`@extendProps`](#extendprops) to extend another bundled component, sveld emits `import type { ButtonProps } from "./Button.svelte"` in the extending component's `.d.ts`. If `Button`'s props type stopped being exported, that import would break — so sveld always keeps a component's props type exported when another component in the same run extends it, even under `exportTypes: false`.
1061
+
1062
+ Also available as `--types-export=<all|none>` on the CLI, mapped to the boolean form (`all` => `true`, `none` => `false`) — the CLI can't express the per-kind object form.
1063
+
1064
+ #### `typesOptions.typeNames`
1065
+
1066
+ By default, sveld names the generated props type `<Name>Props` and (for [`format: "component"`](#dts-output-format-typesoptionsformat)) the exports type `<Name>Exports`, where `<Name>` is the component's module name. `typesOptions.typeNames` lets a library follow its own naming convention instead, via a `{name}` placeholder template.
1067
+
1068
+ ```js
1069
+ sveld({
1070
+ types: true,
1071
+ typesOptions: {
1072
+ typeNames: { props: "I{name}Props" },
1073
+ },
1074
+ });
1075
+ ```
1076
+
1077
+ **Button.svelte.d.ts** before / after:
1078
+
1079
+ ```diff
1080
+ - export type ButtonProps = { label?: string };
1081
+ + export type IButtonProps = { label?: string };
1082
+
1083
+ - export default class Button extends SvelteComponentTyped<ButtonProps, ...> {}
1084
+ + export default class Button extends SvelteComponentTyped<IButtonProps, ...> {}
1085
+ ```
1086
+
1087
+ Each template must contain `{name}` and produce a valid identifier once substituted; sveld throws otherwise. Any key left out of the object keeps its default (`"{name}Props"` / `"{name}Exports"`).
1088
+
1089
+ If a bundled component then [`@extendProps`](#extendprops)/`@extends`-es another one, the tag must name the *templated* interface — `@extendProps {"./Button.svelte"} IButtonProps`, not `ButtonProps` — or sveld reports [`extend-props-target-missing`](#type-inference-diagnostics).
1090
+
1091
+ There's no CLI flag for `typeNames`; set it via a config file or the programmatic `sveld()` API.
1092
+
1093
+ #### `typesOptions.comments`
1094
+
1095
+ By default sveld carries every prop's JSDoc into the generated `.d.ts`: the description, `@deprecated`, `@default`, and passthrough tags like `@since`. `typesOptions.comments` lets a library ship a leaner `.d.ts` instead — useful when the docs live elsewhere (a docs site, Storybook) and duplicating them in the type declaration just adds noise.
1096
+
1097
+ ```svelte
1098
+ <script>
1099
+ /**
1100
+ * The button's visible label.
1101
+ * @deprecated Use `text` instead.
1102
+ * @default ""
1103
+ * @since 1.2.0
1104
+ */
1105
+ export let label = "";
1106
+ </script>
1107
+ ```
1108
+
1109
+ **`comments: "all"`** (default) — description, `@deprecated`, `@default`, and passthrough tags:
1110
+
1111
+ ```ts
1112
+ /**
1113
+ * The button's visible label.
1114
+ * @deprecated Use `text` instead.
1115
+ * @default ""
1116
+ * @since 1.2.0
1117
+ */
1118
+ label?: string;
1119
+ ```
1120
+
1121
+ **`comments: "descriptions"`** — description and `@deprecated` only; `@default` and passthrough tags are dropped:
1122
+
1123
+ ```ts
1124
+ /**
1125
+ * The button's visible label.
1126
+ * @deprecated Use `text` instead.
1127
+ */
1128
+ label?: string;
1129
+ ```
1130
+
1131
+ `@deprecated` survives at this level on purpose: editors render a strikethrough from it, so it's API information a consumer needs, not documentation.
1132
+
1133
+ **`comments: "none"`** — no comments at all; only the declaration:
1134
+
1135
+ ```ts
1136
+ label?: string;
1137
+ ```
1138
+
1139
+ ```js
1140
+ sveld({
1141
+ types: true,
1142
+ typesOptions: {
1143
+ comments: "descriptions",
1144
+ },
1145
+ });
1146
+ ```
1147
+
1148
+ `@internal`/`@ignore` members are removed from every output regardless of this option — see [`@ignore` / `@internal`](#ignore--internal). `comments` only controls how much JSDoc survives for members that *do* get emitted.
1149
+
1150
+ Also available as `--types-comments=<all|descriptions|none>` on the CLI.
1151
+
1152
+ #### `typesOptions.propsDeclaration`
1153
+
1154
+ By default sveld emits the props type as a `type` alias. `typesOptions.propsDeclaration: "interface"` emits an `interface` instead, for consumers who want to extend it with `interface MyProps extends ButtonProps`, rely on declaration merging, or just prefer the shorter editor hover an `interface` gets.
1155
+
1156
+ ```js
1157
+ sveld({
1158
+ types: true,
1159
+ typesOptions: {
1160
+ propsDeclaration: "interface",
1161
+ },
1162
+ });
1163
+ ```
1164
+
1165
+ **Button.svelte.d.ts** before / after:
1166
+
1167
+ ```diff
1168
+ - export type ButtonProps = { label?: string };
1169
+ + export interface ButtonProps { label?: string }
1170
+ ```
1171
+
1172
+ Only a plain object props type can become an `interface` safely. These shapes are intersections instead, and always stay a `type` alias regardless of this option:
1173
+
1174
+ - a component with [`@restProps`](#restprops) (`Omit<$RestProps, keyof $Props> & $Props`)
1175
+ - a component with [`@extendProps`](#extendprops) (`Omit<Extended, keyof $Props> & $Props`)
1176
+ - a component with a whole-object `$props()` type resolved via [`resolveTypes`](#opt-in-semantic-resolution-resolvetypes) (`CanonicalPropsType & { ... }`)
1177
+ - a component with no props at all (`Record<string, never>`; an empty `interface` trips `noEmptyInterface` in consumer lint setups)
1178
+
1179
+ Also available as `--types-props-declaration=<type|interface>` on the CLI.
1180
+
1181
+ #### `typesOptions.transform`
1182
+
1183
+ `typesOptions.transform` is an escape hatch for one-off edits no other option covers - appending a `/// <reference>` directive, rewriting an import specifier for a monorepo, stripping a banner. It runs on every generated `.d.ts` file's text, immediately before it's written, and receives the block's `kind` (`"component"` or `"index"`), and for `"component"` the parsed `ComponentDocApi` too, plus the output `filePath` relative to `outDir` (e.g. `"Button.svelte.d.ts"` or `"index.d.ts"`). Return the new text, synchronously or via a `Promise`.
1184
+
1185
+ ```js
1186
+ sveld({
1187
+ types: true,
1188
+ typesOptions: {
1189
+ transform: (text, context) => {
1190
+ if (context.kind !== "component") return text;
1191
+ return `/// <reference types="svelte" />\n${text}`;
1192
+ },
1193
+ },
1194
+ });
1195
+ ```
1196
+
1197
+ ```ts
1198
+ // Button.svelte.d.ts
1199
+ /// <reference types="svelte" />
1200
+ export type ButtonProps = { label?: string };
1201
+ // ...
1202
+ ```
1203
+
1204
+ `transform` runs after the [persistent parse cache](#persistent-parse-cache-cache)'s generated-text cache, so a changed transform is never served stale cached output - it always re-applies, even when the underlying `.d.ts` text was reused from a previous run. A transform that throws, or resolves to something other than a string, fails the whole `sveld` run with an error naming the file that failed.
1205
+
1206
+ There's no CLI flag for `transform`; set it via a config file or the programmatic `sveld()` API.
1207
+
1208
+ #### `typesOptions.indexTypes`
1209
+
1210
+ By default, `types/index.d.ts` only re-exports components:
1211
+
1212
+ ```ts
1213
+ export { default as Button } from "./Button.svelte";
1214
+ ```
1215
+
1216
+ A consumer who wants `ButtonProps` has to deep-import `my-lib/types/Button.svelte`. `typesOptions.indexTypes` re-exports the generated types from the barrel instead, so `import type { ButtonProps } from "my-lib"` works directly.
1217
+
1218
+ ```js
1219
+ sveld({
1220
+ types: true,
1221
+ typesOptions: {
1222
+ indexTypes: true,
1223
+ },
1224
+ });
1225
+ ```
1226
+
1227
+ ```ts
1228
+ // types/index.d.ts
1229
+ export { default as Button } from "./Button.svelte";
1230
+
1231
+ export type { ButtonProps } from "./Button.svelte";
1232
+ ```
1233
+
1234
+ ```ts
1235
+ import type { ButtonProps } from "my-lib";
1236
+ ```
1237
+
1238
+ `true` is shorthand for `{ props: true, exports: true }`: it re-exports each component's `Props` type, and (under [`format: "component"`](#dts-output-format-typesoptionsformat)) its `Exports` type. Pass an object to also re-export typedefs and/or contexts:
1239
+
1240
+ ```js
1241
+ typesOptions: {
1242
+ indexTypes: { props: true, typedefs: true, contexts: true },
1243
+ }
1244
+ ```
1245
+
1246
+ `Props`/`Exports` names are unique per component by construction (they're derived from the module name), so they're always safe to re-export together. Typedef and context names are user-authored and can collide across components - when two components generate the same name, the first one in barrel order wins and every later collision is dropped with a one-line warning to `stderr`:
1247
+
1248
+ ```
1249
+ sveld: index.d.ts skips duplicate type export "TabsContext" from "./Tabs2.svelte" (already exported from "./Tabs.svelte").
1250
+ ```
1251
+
1252
+ `indexTypes` composes with [`exportTypes`](#typesoptionsexporttypes): a type that `exportTypes` keeps local to its component's `.d.ts` is never re-exported from the barrel either, since it wouldn't resolve.
1253
+
1254
+ Also available as `--types-index-types` on the CLI, mapped to the boolean form (`true` re-exports `Props`/`Exports` only) — the CLI can't express the per-kind object form. Pass `--types-index-types=false` to disable it explicitly.
1255
+
1256
+ #### `typesOptions.inline`
1257
+
1258
+ A TypeScript component that imports a type keeps that import in its `.d.ts`:
1259
+
1260
+ ```svelte
1261
+ <script lang="ts">
1262
+ import type { Size } from "./types";
1263
+ let { size }: { size: Size } = $props();
1264
+ </script>
1265
+ ```
1266
+
1267
+ ```ts
1268
+ import type { Component } from "svelte";
1269
+ import type { Size } from "./types";
1270
+
1271
+ type $Props = { size: Size };
1272
+ export type MyComponentProps = $Props;
1273
+ ```
1274
+
1275
+ Publishers who don't ship their `.svelte` sources need `.d.ts` files without relative imports:
1276
+ `./types.ts` might sit outside the published `types/` output directory, or the package might be
1277
+ bundled to a single file. `typesOptions.inline: "local"` copies the imported declaration into
1278
+ the `.d.ts` instead of importing it:
1279
+
1280
+ ```js
1281
+ sveld({
1282
+ types: true,
1283
+ typesOptions: {
1284
+ inline: "local",
1285
+ },
1286
+ });
1287
+ ```
1288
+
1289
+ ```ts
1290
+ import type { Component } from "svelte";
1291
+
1292
+ type Size = "sm" | "md" | "lg";
1293
+
1294
+ type $Props = { size: Size };
1295
+ export type MyComponentProps = $Props;
1296
+ ```
1297
+
1298
+ `"local"` follows:
1299
+
1300
+ - relative sources (`./types`) and tsconfig/jsconfig `paths` aliases;
1301
+ - re-exports (`export { X as Y } from "./z"` and `export * from "./z"`);
1302
+ - same-file dependencies (a copied type that itself references another type or interface
1303
+ declared in the same file copies that one too, before the type that references it).
1304
+
1305
+ It leaves alone:
1306
+
1307
+ - bare/package imports (`import type { CSSProperties } from "some-package"`) and `.svelte`
1308
+ sources — `"all"` covers bare imports, see below;
1309
+ - `@extendProps`/`@extends` imports and `import("./x")` inline import types inside typedefs,
1310
+ which are unrelated mechanisms;
1311
+ - `enum`, `class`, and `function` exports, which can't be safely copied as a `type`/`interface`.
1312
+
1313
+ An import that can't be safely inlined (a missing file, a missing export, one of the unsupported
1314
+ export kinds above, or a name collision with something the component already declares — a
1315
+ typedef, a context type, a local `type`/`interface`, or its `Props`/`Exports` type name) is left
1316
+ as an import, with a [`types-inline-unresolved`](#diagnostic-codes) warning explaining why. If an
1317
+ `import type { A, B } from "./x"` statement imports several names and even one of them can't be
1318
+ inlined, the whole statement is kept and nothing from it is inlined — simpler, and always correct.
1319
+
1320
+ **`"all"`** additionally inlines bare/package imports:
1321
+
1322
+ ```svelte
1323
+ <script lang="ts">
1324
+ import type { HTMLButtonAttributes } from "svelte/elements";
1325
+ import type { Alignment } from "some-design-system";
1326
+ let { rest, align }: { rest: HTMLButtonAttributes; align: Alignment } = $props();
1327
+ </script>
1328
+ ```
1329
+
1330
+ ```js
1331
+ sveld({
1332
+ types: true,
1333
+ typesOptions: {
1334
+ inline: "all",
1335
+ },
1336
+ });
1337
+ ```
1338
+
1339
+ ```ts
1340
+ import type { Component } from "svelte";
1341
+ import type { HTMLButtonAttributes } from "svelte/elements";
1342
+
1343
+ type Alignment = "start" | "center" | "end";
1344
+
1345
+ type $Props = { rest: HTMLButtonAttributes; align: Alignment };
1346
+ export type MyComponentProps = $Props;
1347
+ ```
1348
+
1349
+ `some-design-system`'s `Alignment` got copied in, exactly like a `"local"` relative import would.
1350
+ `svelte`/`svelte/elements` did not, even though `HTMLButtonAttributes` is itself a bare import a
1351
+ real TypeScript checker could resolve and copy just as easily: those two specifiers are a
1352
+ hard-coded allow-list and always stay imports under `"all"`, regardless of what they resolve to.
1353
+ Copying framework types would freeze whatever Svelte version happened to be installed at
1354
+ generation time into every consumer's `.d.ts` output, which defeats the point of importing them
1355
+ from `svelte` in the first place.
1356
+
1357
+ Resolving a bare specifier to a file needs a real module resolver, so `"all"` uses the actual
1358
+ TypeScript checker (the same one behind [`resolveTypes`](#opt-in-semantic-resolution-resolvetypes)
1359
+ and [`checkExamples`](#compile-checked-example-blocks-checkexamples), shared across all three when
1360
+ more than one is enabled) rather than sveld's own AST-only pass. This makes `"all"` a **hard
1361
+ requirement** on `typescript` 7+ and a resolvable `tsconfig.json` — same contract `resolveTypes`
1362
+ already has (see [Requirements](#requirements)): if TypeScript can't be started, the run fails
1363
+ loudly rather than silently falling back to `"local"` behavior. The requirement only actually
1364
+ kicks in when there's at least one non-allow-listed bare import somewhere in the bundle to
1365
+ resolve; an `"all"` run with nothing bare to inline never loads TypeScript at all.
1366
+
1367
+ A reference inside a copied bare declaration is chased exactly like a local one: a same-file
1368
+ helper type is copied and recursed into, a relative/aliased import is followed the same way
1369
+ `"local"` already does, and a further bare import goes back through the checker (again skipping
1370
+ the svelte/svelte-elements allow-list). A reference that resolves to a TypeScript default-lib file
1371
+ (e.g. `Element`, `EventTarget` from `lib.dom.d.ts`) is left alone — it's already global and needs
1372
+ no import — the same way a local pass leaves an unimported name alone.
1373
+
1374
+ `@extendProps`/`@extends` inlining (replacing `import type { ButtonProps } from "./Button.svelte"`
1375
+ with a copy of `Button`'s own generated declaration) is out of scope for both `"local"` and
1376
+ `"all"`; that's a distinct, deferred mechanism, not covered here.
1377
+
1378
+ Copying from a large package can produce a large `.d.ts`: `svelte/elements`'s attribute-map
1379
+ interfaces (`HTMLButtonAttributes` and friends) are individually sizable, and every type they
1380
+ transitively reference gets copied too. Prefer `"local"` if you don't specifically need bare
1381
+ imports inlined.
1382
+
1383
+ A component with at least one inlined declaration skips the generated-text cache (its output now
1384
+ depends on another file's contents, not just its own source hash), though its *parse* is still
1385
+ cached as usual. Also available as `--types-inline=<local|all>` on the CLI; `--types-inline=false`
1386
+ resets to the default.
1387
+
993
1388
  #### `markdownOptions.onAppend`
994
1389
 
995
1390
  `markdownOptions.onAppend` fires on every heading, quote, paragraph, divider, and raw block written to the Markdown document, and receives the block's `type`, the in-progress `WriterMarkdown` document, and the full component map. Use it to inject extra content, e.g. a summary line under the `h1` title.
@@ -2274,6 +2669,16 @@ function render(value: unknown, props: ComponentProps) {
2274
2669
 
2275
2670
  Both forms support the same modifiers as typedef properties elsewhere in this doc: optional properties (`[name]`), default values (`[name=value]`), and nested/discriminated-union shapes. See the linked sections above for full signatures and worked examples with generated output.
2276
2671
 
2672
+ A description can wrap onto continuation lines, which run until the next tag. Indent them past the `*` gutter to keep them attached to the tag unambiguously; an unindented line right above an `@event`/`@typedef`/`@slot` with no description of its own is read as that tag's description instead, and an unindented line after an event's last `@property` describes the event.
2673
+
2674
+ ```js
2675
+ /**
2676
+ * @typedef {object} Config
2677
+ * @property {number} itemHeight Height of each item in pixels, used for
2678
+ * virtualization math.
2679
+ */
2680
+ ```
2681
+
2277
2682
  ### `@callback`
2278
2683
 
2279
2684
  The `@callback` tag defines a function type with `@param` and `@returns`, following the [TypeScript JSDoc `@callback` spec](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#callback). Like `@typedef`, callbacks are exported from the generated `.d.ts`.
@@ -3509,6 +3914,8 @@ export const secondary = true;
3509
3914
  import Button from "./Button.svelte";
3510
3915
  ```
3511
3916
 
3917
+ The named interface must match the target's generated props type name exactly — the default `<Name>Props`, or whatever [`typesOptions.typeNames`](#typesoptionstypenames) templates it to.
3918
+
3512
3919
  ### `@template`
3513
3920
 
3514
3921
  Svelte supports defining generics via the [`generics` attribute](https://svelte.dev/docs/svelte/typescript) on the script tag, but this requires `lang="ts"`: