sveld 0.37.9 → 0.38.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/lib/index.d.ts CHANGED
@@ -1,8 +1,51 @@
1
- /// <reference types="node" />
1
+ import type { Property } from "estree";
2
2
 
3
- import type { Node, Property } from "estree";
3
+ import type { Dirent } from "node:fs";
4
4
 
5
- import type { FunctionDeclaration, VariableDeclaration } from "estree";
5
+ import { type Program } from "acorn";
6
+
7
+ interface ComponentParserDiagnostics {
8
+ moduleName: string;
9
+ filePath: string;
10
+ }
11
+
12
+ export class ComponentParser {
13
+ /**
14
+ * All per-parse mutable state (props, slots, events, scopes, source, etc.).
15
+ * See {@link ParserContext} for field-by-field documentation. Replaced
16
+ * wholesale by `cleanup()` between parses.
17
+ */
18
+ private ctx;
19
+ /**
20
+ * Resets parser state for reuse between parses.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * parser.parseSvelteComponent(source1, diagnostics1);
25
+ * parser.cleanup();
26
+ * parser.parseSvelteComponent(source2, diagnostics2);
27
+ * ```
28
+ */
29
+ cleanup(): void;
30
+ /**
31
+ * @example
32
+ * ```ts
33
+ * const parser = new ComponentParser();
34
+ * const result = parser.parseSvelteComponent(source, {
35
+ * moduleName: "Button",
36
+ * filePath: "./Button.svelte"
37
+ * });
38
+ * // { props, slots, events, typedefs, ... }
39
+ * ```
40
+ */
41
+ parseSvelteComponent(source: string, diagnostics: ComponentParserDiagnostics): ParsedComponent;
42
+ /**
43
+ * Like {@link parseSvelteComponent}, but returns the candidates only a
44
+ * pass with file access can resolve beside the component rather than
45
+ * inside its metadata.
46
+ */
47
+ parse(source: string, diagnostics: ComponentParserDiagnostics): ComponentParseResult;
48
+ }
6
49
 
7
50
  interface JsDocPassthroughTag {
8
51
  name: string;
@@ -76,31 +119,18 @@ interface PendingDispatchEscapeCandidate {
76
119
  ignored?: boolean;
77
120
  }
78
121
 
79
- interface ParsedComponentTypeScriptMetadata {
80
- canonicalPropsType?: string;
81
- canonicalPropNames: string[];
82
- localTypeDeclarations: string[];
83
- /** Types the module script exports (`export interface Item`), emitted with `export`. */
84
- moduleTypeDeclarations?: string[];
85
- typeImportStatements: string[];
86
- /**
87
- * Whether `canonicalPropsType` mentions one of the component's own
88
- * `<script generics="...">` parameters (e.g. `Props<T>`). The semantic
89
- * resolver has no binding for `T`, so `resolveTypes` must leave this
90
- * component's props as their AST-derived text rather than expand them.
91
- */
92
- referencesComponentGenerics?: boolean;
93
- /** Unresolved CallExpression defaults for the cross-file pass in `generateBundle`. */
122
+ interface PendingCrossFileCandidates {
123
+ /** Unresolved CallExpression defaults. */
94
124
  pendingCallDefaultCandidates?: PendingCallDefaultCandidate[];
95
- /** Imported-identifier defaults for the cross-file pass in `generateBundle`. */
125
+ /** Imported-identifier defaults. */
96
126
  pendingConstDefaultCandidates?: PendingConstDefaultCandidate[];
97
- /** Unresolved `setContext` import keys for the cross-file pass in `generateBundle`. */
127
+ /** Unresolved `setContext` import keys. */
98
128
  pendingContextKeyCandidates?: PendingContextKeyCandidate[];
99
- /** Dispatchers passed to imported functions, for the cross-file pass in `generateBundle`. */
129
+ /** Dispatchers passed to imported functions. */
100
130
  pendingDispatchEscapeCandidates?: PendingDispatchEscapeCandidate[];
101
131
  /**
102
132
  * `event-no-source` diagnostics held back while the dispatcher escapes to
103
- * imported functions: `generateBundle` keeps those the functions don't dispatch.
133
+ * imported functions: the cross-file pass keeps those the functions don't dispatch.
104
134
  */
105
135
  deferredEventNoSourceDiagnostics?: SveldDiagnostic[];
106
136
  /**
@@ -110,6 +140,21 @@ interface ParsedComponentTypeScriptMetadata {
110
140
  untypedJsDocEventNames?: string[];
111
141
  }
112
142
 
143
+ interface ParsedComponentTypeScriptMetadata extends PendingCrossFileCandidates {
144
+ canonicalPropsType?: string;
145
+ canonicalPropNames: string[];
146
+ localTypeDeclarations: string[];
147
+ /** Types the module script exports (`export interface Item`), emitted with `export`. */
148
+ moduleTypeDeclarations?: string[];
149
+ typeImportStatements: string[];
150
+ }
151
+
152
+ interface ComponentParseResult {
153
+ component: ParsedComponent;
154
+ /** Undefined when the component depends on no other file's contents. */
155
+ pending?: PendingCrossFileCandidates;
156
+ }
157
+
113
158
  type SyntaxMode = "legacy" | "runes";
114
159
 
115
160
  type ScriptLanguage = "js" | "ts";
@@ -124,25 +169,6 @@ interface ComponentPropDefaultValue {
124
169
  value?: unknown;
125
170
  }
126
171
 
127
- type ModernScriptAttribute = {
128
- name?: string;
129
- value?: Array<{
130
- data?: string;
131
- raw?: string;
132
- }> | boolean;
133
- start?: number;
134
- end?: number;
135
- };
136
-
137
- type ModernScriptNode = {
138
- attributes?: ModernScriptAttribute[];
139
- };
140
-
141
- interface ComponentParserDiagnostics {
142
- moduleName: string;
143
- filePath: string;
144
- }
145
-
146
172
  type ComponentPropBinding = "readonly" | "writable";
147
173
 
148
174
  interface ComponentPropParam {
@@ -481,154 +507,7 @@ interface ParsedComponent {
481
507
  [PARSED_COMPONENT_TYPE_SCRIPT_METADATA]?: ParsedComponentTypeScriptMetadata;
482
508
  }
483
509
 
484
- export class ComponentParser {
485
- /**
486
- * All per-parse mutable state (props, slots, events, scopes, source, etc.).
487
- * See {@link ParserContext} for field-by-field documentation. Replaced
488
- * wholesale by `cleanup()` between parses.
489
- */
490
- private ctx;
491
- private static mapToArray;
492
- private static getStaticAttributeValue;
493
- resolveScriptLanguage(parsed: {
494
- instance?: ModernScriptNode;
495
- module?: ModernScriptNode;
496
- }): ScriptLanguage | undefined;
497
- /**
498
- * Reads the `generics` attribute off the instance script (Svelte only allows
499
- * it there, and only alongside `lang="ts"`). Returns the raw value for later
500
- * precedence resolution against `@generics`/`@template` JSDoc tags, or
501
- * `undefined` if absent. Records a `syntax-skipped` diagnostic and returns
502
- * `undefined` if the attribute is present without `lang="ts"`, since sveld
503
- * can't safely guess how to parse it as plain JavaScript.
504
- */
505
- resolveScriptGenericsAttribute(parsed: {
506
- instance?: ModernScriptNode;
507
- }): {
508
- value: string;
509
- source?: SourceRange;
510
- } | undefined;
511
- private resolvePublicPropName;
512
- trackPropLocalName(propName: string, localName?: string): void;
513
- private getPropByLocalOrPublic;
514
- getPropTypeByLocalOrPublic(name: string): string | undefined;
515
- getExplicitPropType(name: string): string | undefined;
516
- getPropertyName(node: Property["key"]): string | undefined;
517
- isNumericConstant(memberExpr: unknown): boolean;
518
- resolveLocalVarJSDoc(name: string): {
519
- type?: string;
520
- params?: ComponentPropParam[];
521
- returnType?: string;
522
- description?: string;
523
- binding?: ComponentPropBinding;
524
- deprecated?: DeprecatedValue;
525
- tags?: JsDocPassthroughTag[];
526
- sveldIgnore?: string[];
527
- internal: boolean;
528
- typeParameters?: string;
529
- } | undefined;
530
- private addModuleExport;
531
- /**
532
- * Resolves one `export { local as exported }` specifier to the top-level
533
- * function, class, or variable declarator (including one destructured
534
- * from a pattern) it names. Each specifier resolves on its own, so
535
- * `export { a, b }` exports both, and `const a = 1, b = ""; export { b }`
536
- * exports `b`'s declarator rather than the first one in the declaration.
537
- *
538
- * `program` is the script the export sits in: only its top-level
539
- * declarations count, not a same-named variable inside a function. An
540
- * instance-script export can also name a module-script declaration, or a
541
- * variable that a `$: local = ...` reactive declaration declares implicitly.
542
- */
543
- private resolveExportSpecifier;
544
- private recordUnresolvedExportSpecifier;
545
- /**
546
- * Doc comment for a declaration exported by `node`. A specifier uses the
547
- * comment on the declaration it names. An `export { ... }` list's own
548
- * comment documents it too, but only when the list has a single specifier;
549
- * its tags and description then override the declaration's.
550
- */
551
- private exportJSDoc;
552
- /** An instance-script `export class Foo {}` or `export { Foo }` of a class: neither a prop nor a documented accessor. */
553
- private recordClassExport;
554
- /**
555
- * The `.d.ts` can only say `extends Base` when `Base` is in scope there:
556
- * imported, or another exported class. A class extending anything else
557
- * (a local class, a call like `mixin(Base)`) is declared without it, and
558
- * flagged, since consumers won't see its inherited members.
559
- */
560
- private dropUndeclaredClassBases;
561
- /** A module-script `export class Foo {}` or `export { Foo }` of a class, with its public members. */
562
- private addModuleClassExport;
563
- /**
564
- * @example
565
- * ```ts
566
- * aliasType("*"); // "any"
567
- * aliasType(" string "); // "string"
568
- * ```
569
- */
570
- aliasType(type: string): string;
571
- /**
572
- * @example
573
- * ```ts
574
- * // Given:
575
- * // /**
576
- * // * @type {number}
577
- * // * The count value
578
- * // *\/
579
- * // const count = 0;
580
- *
581
- * findVariableTypeAndDescription("count");
582
- * // { type: "number", description: "The count value" }
583
- * ```
584
- */
585
- findVariableTypeAndDescription(varName: string): {
586
- type: string;
587
- description?: string;
588
- internal?: boolean;
589
- } | null;
590
- /**
591
- * The description and `@internal` flag of the JSDoc above `varName`,
592
- * whether or not it has a `@type`. For a variable typed some other way,
593
- * such as from its initializer.
594
- */
595
- findVariableJsDoc(varName: string): {
596
- description?: string;
597
- internal?: boolean;
598
- };
599
- /** The JSDoc table entry for `varName`, building the table on first use. */
600
- private variableJsDocEntry;
601
- accumulateGeneric(name: string, constraint: string): void;
602
- /**
603
- * Resets parser state for reuse between parses.
604
- *
605
- * @example
606
- * ```ts
607
- * parser.parseSvelteComponent(source1, diagnostics1);
608
- * parser.cleanup();
609
- * parser.parseSvelteComponent(source2, diagnostics2);
610
- * ```
611
- */
612
- cleanup(): void;
613
- private static readonly SCRIPT_BLOCK_REGEX;
614
- /** A `// @ts-...` comment, but not one on a `*` line of a JSDoc block (e.g. in an `@example`). */
615
- private static readonly TS_DIRECTIVE_REGEX;
616
- private static stripTypeScriptDirectivesFromScripts;
617
- /**
618
- * @example
619
- * ```ts
620
- * const parser = new ComponentParser();
621
- * const result = parser.parseSvelteComponent(source, {
622
- * moduleName: "Button",
623
- * filePath: "./Button.svelte"
624
- * });
625
- * // { props, slots, events, typedefs, ... }
626
- * ```
627
- */
628
- parseSvelteComponent(source: string, diagnostics: ComponentParserDiagnostics): ParsedComponent;
629
- }
630
-
631
- export type SveldDiagnosticKind = "prop-unknown-type" | "context-any-type" | "slot-missing-type" | "event-no-source" | "dispatch-escapes" | "example-compile-error" | "example-syntax-error" | "syntax-skipped" | "rest-props-unresolved" | "context-duplicate-key" | "context-key-unresolved" | "context-value-unresolved" | "spread-unresolved" | "export-unresolved" | "module-export-conflict" | "extend-props-target-missing" | "extend-props-duplicate" | "extend-props-override" | "jsdoc-unknown-tag" | "typedef-duplicate" | "property-duplicate" | "generics-conflict" | "event-description-ambiguous" | "jsdoc-tag-dropped" | "internal-typedef-referenced" | "types-inline-unresolved" | "cross-file-unresolved" | "export-ambiguous";
510
+ export type SveldDiagnosticKind = "prop-unknown-type" | "context-any-type" | "slot-missing-type" | "event-no-source" | "dispatch-escapes" | "example-compile-error" | "example-syntax-error" | "syntax-skipped" | "type-syntax-error" | "rest-props-unresolved" | "context-duplicate-key" | "context-key-unresolved" | "context-value-unresolved" | "spread-unresolved" | "export-unresolved" | "module-export-conflict" | "extend-props-target-missing" | "extend-props-duplicate" | "extend-props-override" | "jsdoc-unknown-tag" | "typedef-duplicate" | "property-duplicate" | "generics-conflict" | "event-description-ambiguous" | "jsdoc-tag-dropped" | "internal-typedef-referenced" | "cross-file-unresolved" | "export-ambiguous";
632
511
 
633
512
  export type SveldDiagnosticSeverity = "error" | "warning";
634
513
 
@@ -735,11 +614,6 @@ interface GenerateBundleOptions {
735
614
  * the failure and continuing with the remaining components.
736
615
  */
737
616
  failFast?: boolean;
738
- /**
739
- * Load the TypeScript program to expand opaque imported whole-object `$props()`
740
- * types into JSON/Markdown props. Off by default; requires `typescript`.
741
- */
742
- resolveTypes?: boolean;
743
617
  /** Record consts, functions, and types from the entry barrel. Off by default. */
744
618
  documentExports?: boolean;
745
619
  /**
@@ -759,11 +633,6 @@ interface GenerateBundleOptions {
759
633
  * even when TS/JS examples exist. Off by default.
760
634
  */
761
635
  checkExamples?: boolean | "syntax";
762
- /**
763
- * Parse as usual (so cache reads and real errors still apply) but skip
764
- * persisting the parse cache to disk. Set by the CLI's `--dry-run`.
765
- */
766
- dryRun?: boolean;
767
636
  /**
768
637
  * `ignore`: diagnostics matching at least one `{ code?, component?, name? }`
769
638
  * matcher are marked `ignored` (an omitted field matches anything;
@@ -774,16 +643,6 @@ interface GenerateBundleOptions {
774
643
  diagnostics?: {
775
644
  ignore?: DiagnosticIgnoreMatcher[];
776
645
  };
777
- /**
778
- * Mirrors `typesOptions.typeNames`: templates for the `<Name>Props`
779
- * interface name that `@extends`/`@extendProps` validation checks against.
780
- */
781
- typesTypeNames?: WriteTsDefinitionOptions["typeNames"];
782
- /**
783
- * Mirrors `typesOptions.inline`: `"local"`/`"all"` runs the cross-file
784
- * inlining pass (see `inline-types.ts`) after every component has parsed.
785
- */
786
- typesInline?: WriteTsDefinitionOptions["inline"];
787
646
  }
788
647
 
789
648
  declare const brand: unique symbol;
@@ -796,84 +655,75 @@ export type SvelteEntryPoint = Brand<string, "SvelteEntryPoint">;
796
655
 
797
656
  type NormalizedPath = Brand<string, "NormalizedPath">;
798
657
 
799
- type RelativeSourcePath = Brand<string, "RelativeSourcePath">;
800
-
801
- interface InlinedTypes {
802
- /** Exact `typeImportStatements` entries the writer must drop. */
803
- droppedImportStatements: string[];
804
- /** Declarations to emit (already stripped of `export`), in dependency order. */
805
- declarations: string[];
806
- /** Absolute paths of every file read, for watch-mode invalidation. */
807
- dependencies: string[];
808
- }
809
-
810
- interface WriteTsDefinitionOptions {
658
+ interface EntryExport {
659
+ name: string;
660
+ kind: "const" | "let" | "var" | "function" | "class" | "type" | "interface" | "enum";
811
661
  /**
812
- * `"class"` (default) extends the deprecated `SvelteComponentTyped`.
813
- * `"component"` emits `declare const X: Component<Props, Exports, Bindings>`
814
- * instead, for Svelte 5+ consumers. Generic components get a per-component
815
- * interface with a generic call signature instead of `Component<...>`
816
- * directly, since a `declare const` can't itself carry a generic type
817
- * parameter (see `genGenericComponentDeclaration`).
662
+ * Type text from the source, when present. A namespace export
663
+ * (`export * as ns from "./x"`) gets `typeof import("./x.ts")`, the
664
+ * wrapped module relative to the entry file.
818
665
  */
819
- format?: "class" | "component";
666
+ type?: string;
667
+ /** Initializer text for simple constants. */
668
+ value?: string;
669
+ description?: string;
670
+ /** From `@deprecated` JSDoc. */
671
+ deprecated?: DeprecatedValue;
672
+ /** `@since` / `@example` / `@see` tags in source order. */
673
+ tags?: JsDocPassthroughTag[];
674
+ /** True from `@ignore`/`@internal` JSDoc; excluded from every output by `buildComponentApiDocument`. */
675
+ internal?: boolean;
676
+ /** Declaring module, relative to the entry file. */
677
+ source?: string;
678
+ isTypeOnly: boolean;
679
+ }
680
+
681
+ type EntryExports = EntryExport[];
682
+
683
+ export interface SveldRuntimeOptions extends PluginSveldOptions {
684
+ /** Print unresolved-type diagnostics to stderr. */
685
+ reportDiagnostics?: boolean;
820
686
  /**
821
- * Which generated type declarations get an `export` keyword. `true`
822
- * (default) exports all; `false` exports none; an object picks per kind.
823
- * Module-script exports (`export declare const/function`) are runtime
824
- * exports and are always emitted as exports.
687
+ * Exit code 4 when diagnostics exist. Implies `reportDiagnostics`. Pass
688
+ * `"errors"` to fail only on `severity: "error"` diagnostics
689
+ * (`example-compile-error`, `syntax-skipped`), letting warnings
690
+ * (`prop-unknown-type`, `context-any-type`, `event-no-source`) through.
825
691
  */
826
- exportTypes?: boolean | {
827
- props?: boolean;
828
- exports?: boolean;
829
- typedefs?: boolean;
830
- contexts?: boolean;
831
- };
832
- /** @internal Set by `writeTsDefinitions` for `@extends` targets; overrides `exportTypes.props`. */
833
- forceExportProps?: boolean;
692
+ strict?: boolean | "errors";
834
693
  /**
835
- * Templates for generated type names. `{name}` is replaced with the
836
- * component's module name. Defaults: `"{name}Props"`, `"{name}Exports"`.
694
+ * Diff the parsed component API against a committed snapshot (default:
695
+ * the `json` writer's `outFile`, or `COMPONENT_API.json`) and assign a
696
+ * semver bump to each change. Exits `3` on a breaking change. Pass a
697
+ * string for a custom snapshot path.
837
698
  */
838
- typeNames?: {
839
- props?: string;
840
- exports?: string;
841
- };
699
+ check?: boolean | string;
842
700
  /**
843
- * How much JSDoc to emit. `"all"` (default) keeps descriptions,
844
- * `@deprecated`, `@default`, and passthrough tags (`@since`, `@see`,
845
- * `@example`, `@link`). `"descriptions"` keeps descriptions and
846
- * `@deprecated` only. `"none"` emits no comments at all.
701
+ * Minimum bump `--check` fails the run (exit `3`) on: `"major"` (default,
702
+ * preserves prior behavior), `"minor"`, or `"patch"`.
847
703
  */
848
- comments?: "all" | "descriptions" | "none";
704
+ checkLevel?: "major" | "minor" | "patch";
705
+ /** Suppress writer progress logs (`created "..."` / `unchanged "..."`). */
706
+ quiet?: boolean;
849
707
  /**
850
- * `"type"` (default) emits the props type as a type alias.
851
- * `"interface"` emits `interface <Name>Props { ... }` when the props are a
852
- * plain object (no `@restProps`, no `@extendProps`, no whole-object
853
- * `$props()` type); other shapes are intersections and stay aliases.
708
+ * Print the single selected `json` / `markdown` document to stdout
709
+ * instead of writing it to disk. Requires exactly one of those two
710
+ * outputs; CLI-only (the Vite plugin ignores it).
854
711
  */
855
- propsDeclaration?: "type" | "interface";
712
+ stdout?: boolean;
856
713
  /**
857
- * Copies `type`/`interface` declarations imported from a relative source (or a
858
- * tsconfig/jsconfig path alias) directly into the `.d.ts`, dropping the import. `"local"`
859
- * follows relative sources, path aliases, re-exports, and same-file dependencies; bare package
860
- * imports, `.svelte` sources, and unsupported exports (enums, classes, functions, consts,
861
- * namespaces) stay imports and get a `types-inline-unresolved` warning. `"all"` additionally
862
- * inlines bare/package imports (e.g. `import type { Foo } from "some-lib"`) using the real
863
- * TypeScript checker - same unsupported-export/collision rules, same warning on failure - with
864
- * two exceptions kept as plain imports regardless: `svelte`/`svelte/elements` (a hard-coded
865
- * allow-list; copying framework types would freeze a Svelte version into consumer output) and
866
- * `@extendProps`/`@extends` targets (deferred; unrelated mechanism). `"all"` needs `typescript`
867
- * 7+ and a `tsconfig.json`, same hard requirement as `resolveTypes`. `false` (default)
868
- * preserves every import as-is.
869
- * @default false
714
+ * Output format for the `--check` report and the `--report-diagnostics` /
715
+ * `--strict` diagnostics summary: `"text"` (default) or `"json"`.
716
+ * Channels are unchanged, the check report on stdout and diagnostics on
717
+ * stderr. CLI-only; `sveld()` ignores `format` for its own console output.
870
718
  */
871
- inline?: false | "local" | "all";
872
- /** @internal Set by `writeTsDefinitions` from `GenerateBundleResult.inlinedTypesByFilePath` when `inline` resolved something for this component. */
873
- inlined?: InlinedTypes;
719
+ format?: "text" | "json";
874
720
  }
875
721
 
876
- interface PluginSveldOptions extends Pick<GenerateBundleOptions, "resolveTypes" | "cache" | "checkExamples" | "diagnostics"> {
722
+ export type SveldConfig = SveldRuntimeOptions;
723
+
724
+ export declare function defineConfig(config: SveldConfig): SveldConfig;
725
+
726
+ interface PluginSveldOptions extends Pick<GenerateBundleOptions, "cache" | "checkExamples" | "diagnostics"> {
877
727
  /**
878
728
  * Specify the entry point to uncompiled Svelte source.
879
729
  * If not provided, sveld will use the "svelte" field from package.json.
@@ -893,23 +743,11 @@ interface PluginSveldOptions extends Pick<GenerateBundleOptions, "resolveTypes"
893
743
  /** Record consts, functions, and types from the entry barrel. Off by default. */
894
744
  documentExports?: boolean;
895
745
  types?: boolean;
896
- typesOptions?: Partial<Omit<WriteTsDefinitionsOptions, "inputDir">>;
746
+ typesOptions?: TypesOptions;
897
747
  json?: boolean;
898
- jsonOptions?: Partial<Omit<WriteJsonOptions, "inputDir">>;
748
+ jsonOptions?: JsonOptions;
899
749
  markdown?: boolean;
900
- markdownOptions?: Partial<WriteMarkdownOptions>;
901
- /** Generate a Custom Elements Manifest (`custom-elements.json`, schemaVersion "1.0.0"). */
902
- customElements?: boolean;
903
- customElementsOptions?: Partial<Omit<WriteCustomElementsOptions, "inputDir">>;
904
- /** Generate a first-party `llms.txt` / `llms-full.txt` pair (per https://llmstxt.org). */
905
- llms?: boolean;
906
- llmsOptions?: Partial<WriteLlmsOptions>;
907
- /**
908
- * Run additional, userland-registered writers (via `registerWriter` from
909
- * "sveld") beyond the built-in `json`/`markdown`/`types` outputs. Keyed by
910
- * the writer's registered `name`, valued by that writer's options.
911
- */
912
- additionalWriters?: Record<string, unknown>;
750
+ markdownOptions?: MarkdownOptions;
913
751
  /**
914
752
  * Abort the entire run when a single component fails to parse.
915
753
  * When `false` (the default), parse failures are collected as diagnostics
@@ -919,9 +757,10 @@ interface PluginSveldOptions extends Pick<GenerateBundleOptions, "resolveTypes"
919
757
  /**
920
758
  * Regenerate output incrementally when relevant source changes during
921
759
  * `vite dev` / `vite build --watch`: a component, the entry barrel itself
922
- * (adding/removing an export), or a non-`.svelte` file a component depends
923
- * on via `@extendProps` / `@extends` or a typedef `import("./x")`
924
- * reference. Only the affected components are re-parsed.
760
+ * (adding/removing an export), a module a component reads a value from,
761
+ * or a non-`.svelte` file a component names via `@extendProps` /
762
+ * `@extends`. Only the edited components and those that read an edited
763
+ * module are re-parsed.
925
764
  * @default false
926
765
  */
927
766
  watch?: boolean;
@@ -956,27 +795,18 @@ interface SveldPlugin {
956
795
 
957
796
  export default function pluginSveld(opts?: PluginSveldOptions): SveldPlugin;
958
797
 
959
- interface WriteCustomElementsOptions {
960
- /** @internal Resolved from `entry` and always injected by the caller (`plugin.ts`); not user-configurable via `customElementsOptions`. */
961
- inputDir: string;
962
- outFile: string;
963
- /** @internal Report the resolved path instead of writing. Always set by the caller from `sveld --dry-run`. */
964
- dryRun?: boolean;
965
- }
966
-
967
- interface WriteJsonOptions {
968
- /** @internal Unused by this writer; kept for backward compatibility. Always set by the caller. */
969
- input: string;
970
- /** @internal Resolved from `entry` and always injected by the caller (`plugin.ts`); not user-configurable via `jsonOptions`. */
971
- inputDir: string;
972
- outFile: string;
973
- outDir?: string;
798
+ export interface JsonOptions {
974
799
  /**
975
- * @internal Entry-barrel exports when `documentExports` is on. Always
976
- * computed from the parsed bundle and injected by the caller; setting it
977
- * via `jsonOptions` has no effect.
800
+ * Path (relative to the project root) for the single combined JSON
801
+ * document. Ignored when `outDir` is set.
802
+ * @default "COMPONENT_API.json"
978
803
  */
979
- entryExports?: EntryExports;
804
+ outFile?: string;
805
+ /**
806
+ * Emit one `<ComponentName>.api.json` file per component into this
807
+ * directory instead of the single combined `outFile`.
808
+ */
809
+ outDir?: string;
980
810
  /**
981
811
  * Include `source`/`componentCommentSource` position ranges in the
982
812
  * output. These are the bulk of a large component library's
@@ -986,52 +816,36 @@ interface WriteJsonOptions {
986
816
  * @default true
987
817
  */
988
818
  source?: boolean;
989
- /** @internal Report resolved paths instead of writing. Always set by the caller from `sveld --dry-run`. */
990
- dryRun?: boolean;
991
819
  }
992
820
 
993
- interface EntryExport {
994
- name: string;
995
- kind: "const" | "let" | "var" | "function" | "class" | "type" | "interface" | "enum";
996
- /**
997
- * Type text from the source, when present. A namespace export
998
- * (`export * as ns from "./x"`) gets `typeof import("./x.ts")`, the
999
- * wrapped module relative to the entry file.
1000
- */
1001
- type?: string;
1002
- /** Initializer text for simple constants. */
1003
- value?: string;
1004
- description?: string;
1005
- /** From `@deprecated` JSDoc. */
1006
- deprecated?: DeprecatedValue;
1007
- /** `@since` / `@example` / `@see` tags in source order. */
1008
- tags?: JsDocPassthroughTag[];
1009
- /** True from `@ignore`/`@internal` JSDoc; excluded from every output by `buildComponentApiDocument`. */
1010
- internal?: boolean;
1011
- /** Declaring module, relative to the entry file. */
1012
- source?: string;
1013
- isTypeOnly: boolean;
821
+ export interface ComponentApiDocument {
822
+ schemaVersion: 1;
823
+ generator: {
824
+ name: string;
825
+ version: string;
826
+ svelteVersion: string;
827
+ };
828
+ total: number;
829
+ components: ComponentDocApi[];
830
+ /** Only when `documentExports` is on. */
831
+ totalExports?: number;
832
+ exports?: EntryExports;
1014
833
  }
1015
834
 
1016
- type EntryExports = EntryExport[];
1017
-
1018
- interface WriteLlmsOptions {
1019
- outDir?: string;
1020
- /** Prefixed to each component's link path, e.g. `[Name](<linkBase>/Name)`. @default "" */
1021
- linkBase?: string;
1022
- /** @default the "name" field from the project's package.json */
1023
- title?: string;
1024
- /** @default the "description" field from the project's package.json */
1025
- summary?: string;
1026
- /** @internal Entry-barrel exports when `documentExports` is on. Always computed from the parsed bundle and injected by the caller. */
835
+ interface BuildComponentApiDocumentOptions {
836
+ /** Entry-barrel exports when `documentExports` is on. */
1027
837
  entryExports?: EntryExports;
1028
- /** @internal Report the resolved paths instead of writing. Always set by the caller from `sveld --dry-run`. */
1029
- dryRun?: boolean;
1030
838
  }
1031
839
 
1032
- interface WriteMarkdownOptions {
1033
- write?: boolean;
1034
- outFile: string;
840
+ export declare function buildComponentApiDocument(components: ComponentDocs, options?: BuildComponentApiDocumentOptions): ComponentApiDocument;
841
+
842
+ export interface MarkdownOptions {
843
+ /**
844
+ * Path (relative to the project root) for the single combined Markdown
845
+ * document. Ignored when `outDir` is set.
846
+ * @default "COMPONENT_INDEX.md"
847
+ */
848
+ outFile?: string;
1035
849
  /**
1036
850
  * Emit one `<ModuleName>.md` file per component into this directory,
1037
851
  * plus an index `README.md` linking to each, instead of the single
@@ -1040,33 +854,10 @@ interface WriteMarkdownOptions {
1040
854
  */
1041
855
  outDir?: string;
1042
856
  /**
1043
- * @internal Entry-barrel exports when `documentExports` is on. Always
1044
- * computed from the parsed bundle and injected by the caller; setting it
1045
- * via `markdownOptions` has no effect.
857
+ * Called every time a heading, quote, paragraph, divider, or raw block is
858
+ * appended to the document, to inject extra content.
1046
859
  */
1047
- entryExports?: EntryExports;
1048
- onAppend?: (type: AppendType, document: WriterMarkdown, components: ComponentDocs) => void;
1049
- /** @internal Report the resolved path instead of writing. Always set by the caller from `sveld --dry-run`. */
1050
- dryRun?: boolean;
1051
- }
1052
-
1053
- type OnAppend = (type: AppendType, document: WriterMarkdown) => void;
1054
-
1055
- interface MarkdownOptions {
1056
- onAppend?: OnAppend;
1057
- }
1058
-
1059
- declare class WriterMarkdown extends Writer {
1060
- onAppend?: OnAppend;
1061
- private markdownBase;
1062
- constructor(options: MarkdownOptions);
1063
- get source(): string;
1064
- get hasToC(): boolean;
1065
- get toc(): TocLine[];
1066
- appendLineBreaks(): this;
1067
- append(type: AppendType, raw?: string): this;
1068
- tableOfContents(): this;
1069
- end(): string;
860
+ onAppend?: (type: AppendType, document: MarkdownDocument, components: ComponentDocs) => void;
1070
861
  }
1071
862
 
1072
863
  type AppendType = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "quote" | "p" | "divider" | "raw";
@@ -1077,30 +868,23 @@ interface TocLine {
1077
868
  raw: string;
1078
869
  }
1079
870
 
1080
- interface WriterOptions {
1081
- /** Report the resolved path to stdout instead of writing. Set by `sveld --dry-run`. */
1082
- dryRun?: boolean;
871
+ type MarkdownAppendCallback = (type: AppendType, document: MarkdownDocument) => void;
872
+
873
+ interface MarkdownDocumentOptions {
874
+ onAppend?: MarkdownAppendCallback;
1083
875
  }
1084
876
 
1085
- declare class Writer {
1086
- private readonly dryRun;
1087
- /** Directories already created by this writer, so sibling files skip the `mkdir` round trip. */
1088
- private readonly ensuredDirs;
1089
- constructor(options?: WriterOptions);
1090
- /**
1091
- * Skips the write when `filePath` already contains `raw`, so repeated runs
1092
- * over unchanged sources don't touch the file (or its mtime). In dry-run
1093
- * mode, prints `would write "<path>"` to stdout and touches nothing.
1094
- *
1095
- * @returns `true` if the file was written, `false` if it was already up to date.
1096
- *
1097
- * @example
1098
- * ```ts
1099
- * const writer = new Writer();
1100
- * await writer.write("./dist/index.d.ts", "export type Props = {};");
1101
- * ```
1102
- */
1103
- write(filePath: string, raw: string): Promise<boolean>;
877
+ declare class MarkdownDocument {
878
+ sourceParts: string[];
879
+ hasToC: boolean;
880
+ toc: TocLine[];
881
+ onAppend?: MarkdownAppendCallback;
882
+ constructor(options?: MarkdownDocumentOptions);
883
+ get source(): string;
884
+ appendLineBreaks(): this;
885
+ append(type: AppendType, raw?: string): this;
886
+ tableOfContents(): this;
887
+ end(): string;
1104
888
  }
1105
889
 
1106
890
  type TransformContext = {
@@ -1112,34 +896,19 @@ type TransformContext = {
1112
896
  filePath: string;
1113
897
  };
1114
898
 
1115
- interface WriteTsDefinitionsOptions extends WriteTsDefinitionOptions {
1116
- outDir: string;
1117
- /** @internal Resolved from `entry` and always injected by the caller (`plugin.ts`); not user-configurable via `typesOptions`. */
1118
- inputDir: string;
1119
- preamble: string;
1120
- /** @internal Always computed from the parsed bundle and injected by the caller; not user-configurable via `typesOptions`. */
1121
- exports: ParsedExports;
1122
- /** @internal Report resolved paths instead of writing. Always set by the caller from `sveld --dry-run`. */
1123
- dryRun?: boolean;
1124
- /**
1125
- * @internal Reuses generated `.d.ts` text across runs for components whose
1126
- * source (and every emit option from `serializeEmitOptions`) hasn't
1127
- * changed. Requires `resolvedPathByFilePath` to key lookups; both come
1128
- * from `GenerateBundleResult`.
1129
- */
1130
- cache?: ParseCache;
1131
- /** @internal See `cache`. Lookups use `component.filePath`. */
1132
- resolvedPathByFilePath?: Map<string, string>;
899
+ export interface TypesOptions extends WriteTsDefinitionOptions {
1133
900
  /**
1134
- * @internal See `cache`. For components whose output was resolved from
1135
- * other files, so their text is keyed on their content too.
901
+ * Output directory for generated `.d.ts` files, relative to the project
902
+ * root.
903
+ * @default "types"
1136
904
  */
1137
- crossFileResolvedPathByFilePath?: Map<string, string>;
905
+ outDir?: string;
1138
906
  /**
1139
- * @internal From `GenerateBundleResult.inlinedTypesByFilePath`, populated when
1140
- * `typesOptions.inline` is `"local"`/`"all"`. Lookups use `component.filePath`.
907
+ * Raw text prepended to the generated `index.d.ts` barrel, e.g. a license
908
+ * header.
909
+ * @default ""
1141
910
  */
1142
- inlinedTypesByFilePath?: Map<string, InlinedTypes>;
911
+ preamble?: string;
1143
912
  /**
1144
913
  * Post-processes each generated file's text before it is written. Runs
1145
914
  * after the generated-text cache, so it applies on every run. Config file
@@ -1147,159 +916,24 @@ interface WriteTsDefinitionsOptions extends WriteTsDefinitionOptions {
1147
916
  */
1148
917
  transform?: (text: string, context: TransformContext) => string | Promise<string>;
1149
918
  /**
1150
- * Also re-export generated types from `index.d.ts`. `true` re-exports each
1151
- * component's `Props` type (and `Exports` under `format: "component"`); an
1152
- * object can additionally include typedefs and contexts. Skips any type
1153
- * that `exportTypes` keeps local.
919
+ * Also re-export generated types from `index.d.ts`: each component's
920
+ * `Props` type, and its `Exports` type under `format: "component"`.
1154
921
  */
1155
- indexTypes?: boolean | {
1156
- props?: boolean;
1157
- exports?: boolean;
1158
- typedefs?: boolean;
1159
- contexts?: boolean;
1160
- };
922
+ indexTypes?: boolean;
1161
923
  }
1162
924
 
1163
- declare class ParseCache {
1164
- private readonly cacheFilePath;
1165
- private readonly file;
1166
- private readonly next;
1167
- /** Paths forced to miss this run (e.g. dependents of a changed `@extends` target). */
1168
- private readonly blocked;
1169
- /**
1170
- * Whether `next` differs from what's on disk: an entry was added or its
1171
- * generated text changed. Dropped entries show up as `next` holding fewer
1172
- * entries than `savedEntryCount`, since without a `set()` every entry in
1173
- * `next` came from the file.
1174
- */
1175
- private dirty;
1176
- private savedEntryCount;
1177
- constructor(cacheFilePath: string);
1178
- /** True when `get()` would return a hit for `resolvedPath` and `hash`. */
1179
- has(resolvedPath: string, hash: string): boolean;
1180
- /** Returns the cached parse for `resolvedPath` when its content hash still matches. */
1181
- get(resolvedPath: string, hash: string): ParsedComponent | null;
1182
- /**
1183
- * Records a freshly parsed component so it can be reused on a future run.
1184
- * Stores a copy, for the same reason `get()` returns one.
1185
- */
1186
- set(resolvedPath: string, hash: string, parsed: ParsedComponent): void;
1187
- /** Skip cache for `resolvedPath` this run (e.g. an @extends dependent). */
1188
- invalidate(resolvedPath: string): void;
1189
- /**
1190
- * Returns the cached generated `.d.ts` text for `resolvedPath`, if this
1191
- * run's parse entry for it (a fresh parse or a hash-verified hit - see
1192
- * `get()`/`set()`) already carries text generated for `key`, the
1193
- * serialized emit options (see `serializeEmitOptions`).
1194
- */
1195
- getGeneratedText(resolvedPath: string, key: string): string | undefined;
1196
- /**
1197
- * Records generated `.d.ts` text against this run's parse entry for
1198
- * `resolvedPath`. No-op if that entry hasn't been recorded via `get()`/`set()`
1199
- * (shouldn't happen: the write phase only runs after every component has
1200
- * been parsed).
1201
- */
1202
- setGeneratedText(resolvedPath: string, key: string, text: string): void;
1203
- /**
1204
- * Persists this run's cache entries back to disk. Writes to a pid-suffixed
1205
- * temp file and renames it over the target so concurrent sveld processes
1206
- * sharing a cache dir can't interleave writes into a truncated file; a
1207
- * failed rename (e.g. read-only cache dir) falls back to a direct write so
1208
- * generation never fails just because the cache couldn't be saved.
1209
- * Skipped when nothing changed since the file was read or last saved.
1210
- */
1211
- save(): void;
1212
- }
1213
-
1214
- type ParsedExports = Record<string, {
1215
- source: RelativeSourcePath;
1216
- default: boolean;
1217
- mixed?: boolean;
1218
- }>;
1219
-
1220
- export interface SveldRuntimeOptions extends PluginSveldOptions {
1221
- /** Print unresolved-type diagnostics to stderr. */
1222
- reportDiagnostics?: boolean;
1223
- /**
1224
- * Exit code 4 when diagnostics exist. Implies `reportDiagnostics`. Pass
1225
- * `"errors"` to fail only on `severity: "error"` diagnostics
1226
- * (`example-compile-error`, `syntax-skipped`), letting warnings
1227
- * (`prop-unknown-type`, `context-any-type`, `event-no-source`) through.
1228
- *
1229
- * `"ci"` and `"local"` are strictness profiles, expanded by
1230
- * {@link expandStrictProfile} into a set of other options before this
1231
- * object's own explicit keys are applied (so they can still opt back out
1232
- * of one, e.g. `{ strict: "ci", checkExamples: false }`):
1233
- * - `"ci"`: `{ strict: true, reportDiagnostics: true, check: true, checkExamples: true }`.
1234
- * - `"local"`: `{ reportDiagnostics: true }` (does not itself enable `strict`).
1235
- */
1236
- strict?: boolean | "errors" | "ci" | "local";
1237
- /**
1238
- * Diff the parsed component API against a committed snapshot (default:
1239
- * the `json` writer's `outFile`, or `COMPONENT_API.json`) and assign a
1240
- * semver bump to each change. Exits `3` on a breaking change. Pass a
1241
- * string for a custom snapshot path.
1242
- */
1243
- check?: boolean | string;
1244
- /**
1245
- * Minimum bump `--check` fails the run (exit `3`) on: `"major"` (default,
1246
- * preserves prior behavior), `"minor"`, or `"patch"`.
1247
- */
1248
- checkLevel?: "major" | "minor" | "patch";
1249
- /** Suppress writer progress logs (`created "..."` / `unchanged "..."`). */
1250
- quiet?: boolean;
1251
- /**
1252
- * Print the single selected `json` / `markdown` / `customElements` document
1253
- * to stdout instead of writing it to disk. Requires exactly one of those
1254
- * three outputs; CLI-only (the Vite plugin ignores it). `"ndjson"` is only
1255
- * valid with `json` and prints one minified JSON object per component per
1256
- * line instead of the single combined document.
1257
- */
1258
- stdout?: boolean | "json" | "ndjson";
1259
- /**
1260
- * Output format for the `--check` report and the `--report-diagnostics` /
1261
- * `--strict` diagnostics summary: `"text"` (default), `"json"`, or
1262
- * `"github"` (GitHub Actions `::error`/`::warning` workflow commands, plus
1263
- * a `GITHUB_STEP_SUMMARY` Markdown table when that env var is set).
1264
- * Channels are unchanged, the check report on stdout and diagnostics on
1265
- * stderr. CLI-only; `sveld()` ignores `format` for its own console output.
1266
- */
1267
- format?: "text" | "json" | "github";
925
+ interface WriteTsDefinitionOptions {
1268
926
  /**
1269
- * Resolve the entry, load config, and parse components as usual, but print
1270
- * `would write "<path>"` for each output file to stdout instead of writing
1271
- * it (including the parse cache). CLI-only; the Vite plugin ignores it.
927
+ * `"class"` (default) extends the deprecated `SvelteComponentTyped`.
928
+ * `"component"` emits `declare const X: Component<Props, Exports, Bindings>`
929
+ * instead, for Svelte 5+ consumers. Generic components get a per-component
930
+ * interface with a generic call signature instead of `Component<...>`
931
+ * directly, since a `declare const` can't itself carry a generic type
932
+ * parameter (see `genGenericComponentDeclaration`).
1272
933
  */
1273
- dryRun?: boolean;
1274
- }
1275
-
1276
- export type SveldConfig = SveldRuntimeOptions;
1277
-
1278
- export declare function defineConfig(config: SveldConfig): SveldConfig;
1279
-
1280
- export interface ComponentApiDocument {
1281
- schemaVersion: 1;
1282
- generator: {
1283
- name: string;
1284
- version: string;
1285
- svelteVersion: string;
1286
- };
1287
- total: number;
1288
- components: ComponentDocApi[];
1289
- /** Only when `documentExports` is on. */
1290
- totalExports?: number;
1291
- exports?: EntryExports;
1292
- }
1293
-
1294
- interface BuildComponentApiDocumentOptions {
1295
- /** Entry-barrel exports when `documentExports` is on. */
1296
- entryExports?: EntryExports;
934
+ format?: "class" | "component";
1297
935
  }
1298
936
 
1299
- export declare function buildComponentApiDocument(components: ComponentDocs, options?: BuildComponentApiDocumentOptions): ComponentApiDocument;
1300
-
1301
- export declare function cli(process: NodeJS.Process): Promise<void>;
1302
-
1303
937
  type SveldOptions = SveldRuntimeOptions;
1304
938
 
1305
939
  export interface SveldResult {
@@ -1310,41 +944,19 @@ export interface SveldResult {
1310
944
  /** Parse errors for components that failed to parse (empty unless `failFast` is disabled and a component errors). */
1311
945
  errors: ComponentParseError[];
1312
946
  /**
1313
- * Suggested process exit code for this run, using the same mapping as the
1314
- * CLI (a breaking `check` result wins over `strict` diagnostics): `0` on
1315
- * success, `3` on a breaking API change, `4` when `strict` diagnostics
1316
- * exist. `sveld()` never mutates `process.exitCode` itself; assign this
1317
- * value yourself if you want the process to exit non-zero.
947
+ * The component API document for the exported components, exactly as the
948
+ * `json` writer writes `COMPONENT_API.json`. Populated whether or not
949
+ * `json` is enabled, so custom output can be rendered from it directly.
1318
950
  */
1319
- exitCode: 0 | 3 | 4;
1320
- }
1321
-
1322
- export declare function sveld(opts?: SveldOptions): Promise<SveldResult>;
1323
-
1324
- type WriterComponentSet = "exported" | "all";
1325
-
1326
- export interface OutputWriter<TOptions = unknown> {
1327
- name: string;
1328
- /** Which component set this writer expects — see {@link WriterComponentSet}. @default "exported" */
1329
- componentSet?: WriterComponentSet;
951
+ document: ComponentApiDocument;
1330
952
  /**
1331
- * `options` always carries `dryRun: true` under `sveld --dry-run` (or
1332
- * `{ dryRun: true }` from the programmatic API), alongside whatever
1333
- * `TOptions` fields the writer defines. `write` must check it and skip
1334
- * touching disk; sveld does not do this for you. A thrown error (sync or
1335
- * async) is re-thrown by the caller as `sveld: writer "<name>" failed: ...`
1336
- * with the original error as `cause`.
953
+ * Suggested process exit code for this run, using the same mapping as the
954
+ * CLI (see {@link resolveExitCode}). `sveld()` never mutates `process.exitCode` itself; assign this
955
+ * value yourself if you want the process to exit non-zero.
1337
956
  */
1338
- write(components: ComponentDocs, options: TOptions): Promise<unknown> | unknown;
1339
- }
1340
-
1341
- export interface RegisterWriterOptions {
1342
- /** Overwrite an existing writer registered under the same `name` instead of throwing. @default false */
1343
- replace?: boolean;
957
+ exitCode: ExitCode;
1344
958
  }
1345
959
 
1346
- export declare function registerWriter<TOptions = unknown>(writer: OutputWriter<TOptions>, options?: RegisterWriterOptions): void;
960
+ type ExitCode = 0 | 1 | 2 | 3 | 4;
1347
961
 
1348
- export declare function getWriter(name: string): OutputWriter<unknown> | undefined;
1349
-
1350
- export declare function listWriters(): OutputWriter<unknown>[];
962
+ export declare function sveld(opts?: SveldOptions): Promise<SveldResult>;