sveld 0.29.1 → 0.30.0

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
@@ -11,6 +11,8 @@ The purpose of this project is to make third party Svelte component libraries co
11
11
 
12
12
  `sveld` uses the Svelte 5 compiler to parse `.svelte` files. That single parse path powers docgen and TypeScript output for Svelte 3, Svelte 4, Svelte 5 without runes (`export let`, `<slot>`, `$$restProps`, …), and Svelte 5 Runes (`$props()`, `$bindable()`, `{@render ...}`, callback props such as `onclick`, …).
13
13
 
14
+ For `lang="ts"` components, `sveld` preserves source-level prop type annotations when possible instead of requiring JSDoc as the primary source of truth. This includes legacy `export let` props, typed `$props()` destructuring, typed whole-object `$props()` captures, local `interface`/`type` declarations, and imported type references in emitted `.d.ts` files.
15
+
14
16
  | Syntax mode | Supported |
15
17
  | :------------------- | :-------: |
16
18
  | Svelte 3 | ✓ |
@@ -156,6 +158,15 @@ Extracted metadata include:
156
158
 
157
159
  This library adopts a progressively enhanced approach. Any property type that cannot be inferred (e.g., "hello" is a string) falls back to "any" to minimize incorrectly typed properties or signatures. To mitigate this, the library author can add JSDoc annotations to specify types that cannot be reliably inferred. This represents a progressively enhanced approach because JSDocs are comments that can be ignored by the compiler.
158
160
 
161
+ When both TypeScript syntax and JSDoc are present, `sveld` resolves prop types in this order:
162
+
163
+ 1. explicit TypeScript annotation
164
+ 2. explicit JSDoc annotation
165
+ 3. initializer inference
166
+ 4. `any`
167
+
168
+ `sveld` intentionally stays AST-only. It preserves imported and local type text in generated `.d.ts` output, but it does not perform project-wide semantic resolution with the TypeScript compiler. That means opaque imported whole-object `$props()` types can be preserved in declarations without being fully expanded into JSON metadata.
169
+
159
170
  ## Usage
160
171
 
161
172
  ### Installation
@@ -204,13 +215,15 @@ sveld({
204
215
  When building the library, TypeScript definitions are emitted to the `types` folder by default.
205
216
 
206
217
  Customize the output folder using the `typesOptions.outDir` option.
218
+ Use `typesOptions.printWidth` to control Prettier wrapping for generated `.d.ts` files. The default is `80`.
207
219
 
208
220
  The following example emits the output to the `dist` folder:
209
221
 
210
222
  ```diff
211
223
  sveld({
212
224
  + typesOptions: {
213
- + outDir: 'dist'
225
+ + outDir: 'dist',
226
+ + printWidth: 80
214
227
  + }
215
228
  })
216
229
  ```
@@ -300,7 +313,7 @@ TypeScript definitions are outputted to the `types` folder by default. Don't for
300
313
  - **`entry`** (string, optional): Specify the entry point to uncompiled Svelte source. If not provided, sveld will use the `"svelte"` field from `package.json`.
301
314
  - **`glob`** (boolean, optional): Enable glob mode to analyze all `*.svelte` files.
302
315
  - **`types`** (boolean, optional, default: `true`): Generate TypeScript definitions.
303
- - **`typesOptions`** (object, optional): Options for TypeScript definition generation.
316
+ - **`typesOptions`** (object, optional): Options for TypeScript definition generation, including `outDir`, `preamble`, and `printWidth`.
304
317
  - **`json`** (boolean, optional): Generate component documentation in JSON format.
305
318
  - **`jsonOptions`** (object, optional): Options for JSON output.
306
319
  - **`markdown`** (boolean, optional): Generate component documentation in Markdown format.
@@ -354,6 +367,8 @@ export let id = `ccs-${Math.random().toString(36)}`;
354
367
 
355
368
  Use the `@type` tag to explicitly document the type. In the following example, the `kind` property has an enumerated (enum) type.
356
369
 
370
+ For `lang="ts"` components, prefer native TypeScript annotations when they are already present. `@type` remains useful for JavaScript components, for overriding inferred types, and for cases where the AST cannot recover a more precise type.
371
+
357
372
  **Signature:**
358
373
 
359
374
  ```js
@@ -761,6 +776,8 @@ For Svelte 5 compatibility, `sveld` automatically generates optional snippet pro
761
776
 
762
777
  When parsing runes components, `sveld` maps `{@render ...}` calls back into the same slot metadata used for traditional `<slot>` declarations. Reserved snippet props such as `children`, along with named snippet props discovered from `{@render ...}`, are represented through `slots` metadata and generated snippet prop types rather than duplicated in the `props` output.
763
778
 
779
+ Positional snippet calls such as `{@render row?.(item, index)}` are preserved as typed props when the prop itself has an explicit type like `Snippet<[Item, number]>`. They are not converted into synthetic slot metadata.
780
+
764
781
  For slots with props (e.g., `let:prop`), the generated type uses a Snippet-compatible signature:
765
782
 
766
783
  ```ts
@@ -1,3 +1,13 @@
1
+ export interface ParsedComponentTypeScriptMetadata {
2
+ canonicalPropsType?: string;
3
+ canonicalPropNames: string[];
4
+ localTypeDeclarations: string[];
5
+ typeImportStatements: string[];
6
+ }
7
+ export declare const PARSED_COMPONENT_TYPE_SCRIPT_METADATA: unique symbol;
8
+ export declare function getParsedComponentTypeScriptMetadata(component: {
9
+ [PARSED_COMPONENT_TYPE_SCRIPT_METADATA]?: ParsedComponentTypeScriptMetadata;
10
+ }): ParsedComponentTypeScriptMetadata | undefined;
1
11
  /**
2
12
  * Diagnostic information for component parsing.
3
13
  *
@@ -258,6 +268,8 @@ export interface ParsedComponent {
258
268
  componentComment?: string;
259
269
  /** Contexts created with `setContext` in the component */
260
270
  contexts?: ComponentContext[];
271
+ /** Internal writer-only TypeScript metadata. Not serialized to JSON. */
272
+ [PARSED_COMPONENT_TYPE_SCRIPT_METADATA]?: ParsedComponentTypeScriptMetadata;
261
273
  }
262
274
  export default class ComponentParser {
263
275
  /** Parser configuration options (e.g., verbose logging) */
@@ -306,10 +318,20 @@ export default class ComponentParser {
306
318
  private readonly propLocalToPublicName;
307
319
  /** Tracks `$props()` bindings that are used as spread/rest props */
308
320
  private readonly restPropLocals;
321
+ /** Tracks identifier bindings that capture the entire `$props()` object */
322
+ private readonly wholePropsLocals;
309
323
  /** Tracks prop locals that are used as snippet/render props */
310
324
  private readonly snippetPropLocals;
311
325
  /** Per-declarator type metadata extracted from modern AST `$props()` annotations */
312
- private readonly runesPropTypeMetadataByDeclaratorStart;
326
+ private readonly runesPropsDeclarationMetadataByDeclaratorStart;
327
+ /** Explicit TypeScript prop annotations for legacy `export let` declarations keyed by local name */
328
+ private readonly explicitPropTypesByName;
329
+ /** Type-only imports keyed by their local binding names */
330
+ private readonly typeImportBindingsByLocalName;
331
+ /** Local interface/type declarations keyed by type name */
332
+ private readonly localTypeDeclarationsByName;
333
+ /** Typed `$props()` declarations discovered in source order */
334
+ private readonly typedRunesPropsDeclarations;
313
335
  /** Component-level lexical scope shared by instance script and template */
314
336
  private readonly componentScope;
315
337
  /** Precomputed lexical scopes for nested AST nodes */
@@ -325,7 +347,16 @@ export default class ComponentParser {
325
347
  private trackPropLocalName;
326
348
  private getPropByLocalOrPublic;
327
349
  private getPropTypeByLocalOrPublic;
350
+ private getExplicitPropType;
351
+ private getRunesPropsDeclarationMetadata;
328
352
  private getRunesPropTypeMetadata;
353
+ private getTypeReferenceName;
354
+ private getTypeDependencyName;
355
+ private getTypeAnnotationText;
356
+ private collectReferencedTypeDependencies;
357
+ private buildTypeImportStatements;
358
+ private buildTypeScriptMetadata;
359
+ private buildRunesPropTypeMetadataMap;
329
360
  private declareScopeBinding;
330
361
  private resolveIdentifierToReactiveProp;
331
362
  private collectPatternIdentifiers;
@@ -499,6 +530,7 @@ export default class ComponentParser {
499
530
  private parseRunesPropsDeclaration;
500
531
  private inferSlotPropValueFromExpression;
501
532
  private buildSlotPropsFromObjectExpression;
533
+ private resolveRenderTagPropReference;
502
534
  private extractRenderTagInfo;
503
535
  /**
504
536
  * Adds or merges a component prop to the props map.