sveld 0.30.3 → 0.32.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
@@ -127,6 +127,7 @@ export default class Button extends SvelteComponentTyped<
127
127
  - [CLI](#cli)
128
128
  - [Publishing to NPM](#publishing-to-npm)
129
129
  - [Available Options](#available-options)
130
+ - [JSON Output](#json-output)
130
131
  - [API Reference](#api-reference)
131
132
  - [@type](#type)
132
133
  - [@default](#default)
@@ -139,6 +140,7 @@ export default class Button extends SvelteComponentTyped<
139
140
  - [Context API](#context-api)
140
141
  - [@restProps](#restprops)
141
142
  - [@extendProps](#extendprops)
143
+ - [@template](#template)
142
144
  - [@generics](#generics)
143
145
  - [@component comments](#component-comments)
144
146
  - [Accessor Props](#accessor-props)
@@ -332,6 +334,121 @@ sveld({
332
334
  })
333
335
  ```
334
336
 
337
+ ## JSON Output
338
+
339
+ When `json: true` is enabled, `sveld` emits a `COMPONENT_API.json` file with schema and generator metadata plus the parsed
340
+ component API.
341
+
342
+ The public JSON Schema for the combined output is hosted on GitHub ([path to file](https://github.com/carbon-design-system/sveld/blob/main/schema/component-api.schema.json), [raw URL](https://raw.githubusercontent.com/carbon-design-system/sveld/main/schema/component-api.schema.json)). Use it to document or validate
343
+ generated `COMPONENT_API.json` files. The schema describes the emitted metadata contract; optional fields may be absent when
344
+ the parser does not have a stable source for that metadata.
345
+
346
+ ```ts
347
+ interface ComponentApiJson {
348
+ schemaVersion: 1;
349
+ generator: {
350
+ name: string;
351
+ version: string;
352
+ svelteVersion: string;
353
+ };
354
+ total: number;
355
+ components: ComponentDocApi[];
356
+ }
357
+
358
+ interface SourceRange {
359
+ start: SourcePosition;
360
+ end: SourcePosition;
361
+ }
362
+
363
+ interface SourcePosition {
364
+ line: number;
365
+ column: number;
366
+ }
367
+
368
+ interface ComponentDocApi {
369
+ moduleName: string;
370
+ filePath: string;
371
+ source?: SourceRange;
372
+ syntaxMode: "legacy" | "runes";
373
+ scriptLanguage?: "js" | "ts";
374
+ props: ComponentProp[];
375
+ moduleExports: ComponentProp[];
376
+ slots: ComponentSlot[];
377
+ events: ComponentEvent[];
378
+ typedefs: TypeDef[];
379
+ generics: null | [name: string, type: string];
380
+ rest_props?: RestProps;
381
+ extends?: { interface: string; import: string };
382
+ componentComment?: string;
383
+ componentCommentSource?: SourceRange;
384
+ contexts?: ComponentContext[];
385
+ }
386
+
387
+ interface ComponentProp {
388
+ name: string;
389
+ localName?: string;
390
+ kind: "let" | "const" | "function";
391
+ constant: boolean;
392
+ type?: string;
393
+ typeSource?: "typescript" | "jsdoc" | "default" | "inferred" | "unknown";
394
+ value?: string;
395
+ defaultValue?: {
396
+ raw: string;
397
+ kind: "literal" | "array" | "object" | "expression" | "function" | "unknown";
398
+ value?: unknown;
399
+ };
400
+ description?: string;
401
+ params?: Array<{ name: string; type: string; description?: string; optional?: boolean }>;
402
+ returnType?: string;
403
+ isFunction: boolean;
404
+ isFunctionDeclaration: boolean;
405
+ isRequired: boolean;
406
+ reactive: boolean;
407
+ binding?: "readonly" | "writable";
408
+ bindable?: true;
409
+ source?: SourceRange;
410
+ }
411
+
412
+ interface ComponentSlot {
413
+ name?: string | null;
414
+ default: boolean;
415
+ fallback?: string;
416
+ slot_props?: string;
417
+ description?: string;
418
+ tags?: Array<{ name: string; body: string }>;
419
+ source?: SourceRange;
420
+ }
421
+
422
+ type ComponentEvent =
423
+ | {
424
+ type: "forwarded";
425
+ name: string;
426
+ element: string;
427
+ description?: string;
428
+ detail?: string;
429
+ source?: SourceRange;
430
+ }
431
+ | {
432
+ type: "dispatched";
433
+ name: string;
434
+ detail?: string;
435
+ description?: string;
436
+ source?: SourceRange;
437
+ };
438
+ ```
439
+
440
+ `source` fields are optional and are included only when the Svelte or JavaScript AST provides stable positions. They do not
441
+ include source text or raw character offsets.
442
+
443
+ Note that `SourcePosition.line` is 1-based and `SourcePosition.column` is 0-based.
444
+
445
+ Prop metadata is additive and preserves the older public fields:
446
+
447
+ - `name` is always the public prop name. For runes `$props()` aliases such as `let { class: className } = $props()`, `localName` is emitted only when the local binding differs.
448
+ - `typeSource` identifies the conservative source of the emitted `type`: TypeScript annotation, JSDoc, initializer/default inference, other parser inference, or unknown fallback.
449
+ - `value` remains the raw default expression string. `defaultValue` adds structured metadata with the same raw expression, a coarse `kind`, and a parsed `value` only for JSON-safe literals, arrays, and plain objects. `sveld` does not evaluate arbitrary code.
450
+ - `bindable: true` is emitted only for props explicitly declared with Svelte 5 `$bindable(...)`. Missing `bindable` should be treated as false.
451
+
335
452
  ## API Reference
336
453
 
337
454
  ### `reactive`
@@ -349,6 +466,38 @@ Local variables or parameters that shadow a prop name do not count as writes to
349
466
 
350
467
  `reactive: false` means `sveld` found no such evidence. It does not imply that parent-side `bind:` usage is impossible.
351
468
 
469
+ ### `binding`
470
+
471
+ The optional `binding` field in generated JSON is explicit documentation metadata for a prop's intended `bind:` contract. It is separate from `reactive`, and it is never inferred from internal writes or `$bindable()`.
472
+
473
+ Use `@bindable readonly` for component-owned or output-style bindings where the consumer binds to the current value emitted by the component:
474
+
475
+ ```svelte
476
+ <script>
477
+ /**
478
+ * Bind to the current value emitted by the component.
479
+ * @bindable readonly
480
+ */
481
+ export let size = undefined;
482
+ </script>
483
+ ```
484
+
485
+ Use `@bindable writable` for two-way or shared state bindings where either the consumer or component may control the value:
486
+
487
+ ```svelte
488
+ <script>
489
+ /**
490
+ * Bind to state controlled by either the consumer or component.
491
+ * @bindable writable
492
+ */
493
+ export let open = false;
494
+ </script>
495
+ ```
496
+
497
+ Generated JSON includes `"binding": "readonly"` or `"binding": "writable"` for annotated props. Unannotated props omit the field.
498
+
499
+ This is documentation metadata only. Generated `.svelte.d.ts` prop types are unchanged because TypeScript cannot reliably express Svelte component binding direction.
500
+
352
501
  For stable output, generated `events` arrays are emitted in deterministic sorted order.
353
502
 
354
503
  ### `@type`
@@ -1544,24 +1693,22 @@ export const secondary = true;
1544
1693
  import Button from "./Button.svelte";
1545
1694
  ```
1546
1695
 
1547
- ### `@generics`
1696
+ ### `@template`
1548
1697
 
1549
- Currently, to define generics for a Svelte component, you must use [`generics` attribute](https://github.com/dummdidumm/rfcs/blob/bfb14dc56a70ec6ddafebf2242b8e1500e06a032/text/ts-typing-props-slots-events.md#generics) on the script tag. Note that this feature is [experimental](https://svelte.dev/docs/typescript#experimental-advanced-typings) and may change in the future.
1550
-
1551
- However, the `generics` attribute only works if using `lang="ts"`; the language server will produce an error if `generics` is used without specifying `lang="ts"`.
1698
+ Svelte supports defining generics via the [`generics` attribute](https://svelte.dev/docs/svelte/typescript) on the script tag, but this requires `lang="ts"`.
1552
1699
 
1553
1700
  ```svelte
1554
- <!-- This causes an error because `lang="ts"` must be used. -->
1555
- <script generics="Row extends DataTableRow = any"></script>
1701
+ <!-- Requires lang="ts" -->
1702
+ <script lang="ts" generics="Row extends DataTableRow = any"></script>
1556
1703
  ```
1557
1704
 
1558
- Because `sveld` is designed to support JavaScript-only usage as a baseline, the API design to specify generics uses a custom JSDoc tag `@generics`.
1705
+ Because `sveld` is designed to support JavaScript-only usage as a baseline, the API design to specify generics uses the standard JSDoc `@template` tag. The `@generics` tag is also supported as an alias.
1559
1706
 
1560
- **Signature:**
1707
+ **Signature:** Uses standard [JSDoc `@template` syntax](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#template):
1561
1708
 
1562
1709
  ```js
1563
1710
  /**
1564
- * @generics {GenericParameter} GenericName
1711
+ * @template {Constraint} [Name=Default]
1565
1712
  */
1566
1713
  ```
1567
1714
 
@@ -1569,7 +1716,7 @@ Because `sveld` is designed to support JavaScript-only usage as a baseline, the
1569
1716
 
1570
1717
  ```js
1571
1718
  /**
1572
- * @generics {Row extends DataTableRow = any} Row
1719
+ * @template {DataTableRow} [Row=DataTableRow]
1573
1720
  */
1574
1721
  ```
1575
1722
 
@@ -1624,13 +1771,12 @@ Because `sveld` is designed to support JavaScript-only usage as a baseline, the
1624
1771
  The generated TypeScript definition will resemble the following:
1625
1772
 
1626
1773
  ```ts
1627
- // Props type includes the full constraint, enabling indexed access types like Row["id"]
1628
- export type ComponentProps<Row extends DataTableRow = any> = {
1774
+ export type ComponentProps<Row extends DataTableRow = DataTableRow> = {
1629
1775
  rows?: ReadonlyArray<Row>;
1630
1776
  };
1631
1777
 
1632
1778
  export default class Component<
1633
- Row extends DataTableRow = any,
1779
+ Row extends DataTableRow = DataTableRow,
1634
1780
  > extends SvelteComponentTyped<
1635
1781
  ComponentProps<Row>,
1636
1782
  Record<string, any>,
@@ -1638,24 +1784,57 @@ export default class Component<
1638
1784
  > {}
1639
1785
  ```
1640
1786
 
1641
- For a parameter list, the name should be comma-separated but not include spaces.
1787
+ For multiple generics, use separate `@template` tags:
1642
1788
 
1643
1789
  ```js
1644
1790
  /**
1645
- * @generics {Param1, Param2} Name1,Name2
1791
+ * @template {DataTableRow} [Row=DataTableRow]
1792
+ * @template {DataTableRow} [Header=DataTableRow]
1646
1793
  */
1647
1794
  ```
1648
1795
 
1649
1796
  ```ts
1650
- export type ComponentProps<Param1, Param2> = { ... };
1797
+ export type ComponentProps<
1798
+ Row extends DataTableRow = DataTableRow,
1799
+ Header extends DataTableRow = DataTableRow,
1800
+ > = { ... };
1651
1801
 
1652
- export default class Component<Param1, Param2> extends SvelteComponentTyped<
1653
- ComponentProps<Name1, Name2>,
1802
+ export default class Component<
1803
+ Row extends DataTableRow = DataTableRow,
1804
+ Header extends DataTableRow = DataTableRow,
1805
+ > extends SvelteComponentTyped<
1806
+ ComponentProps<Row, Header>,
1654
1807
  Record<string, any>,
1655
1808
  Record<string, any>
1656
1809
  > {}
1657
1810
  ```
1658
1811
 
1812
+ ### `@generics`
1813
+
1814
+ As an alternative to `@template`, sveld also supports a custom `@generics` tag. Unlike `@template`, which is [officially supported by JSDoc/TypeScript](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#template), `@generics` is sveld-specific. However, its syntax can be more readable since the full constraint is written inline:
1815
+
1816
+ ```js
1817
+ /**
1818
+ * @generics {Row extends DataTableRow = DataTableRow} Row
1819
+ */
1820
+ ```
1821
+
1822
+ This is equivalent to:
1823
+
1824
+ ```js
1825
+ /**
1826
+ * @template {DataTableRow} [Row=DataTableRow]
1827
+ */
1828
+ ```
1829
+
1830
+ For multiple generics, use a single `@generics` tag with comma-separated names:
1831
+
1832
+ ```js
1833
+ /**
1834
+ * @generics {Row extends DataTableRow = DataTableRow, Header extends DataTableRow = DataTableRow} Row,Header
1835
+ */
1836
+ ```
1837
+
1659
1838
  ### `@component` comments
1660
1839
 
1661
1840
  The Svelte Language Server supports component-level comments through the following syntax: `<!-- @component [comment] -->`.