sveld 0.25.13 → 0.26.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
@@ -112,7 +112,7 @@ export default class Button extends SvelteComponentTyped<
112
112
  - [Approach](#approach)
113
113
  - [Usage](#usage)
114
114
  - [Installation](#installation)
115
- - [Rollup](#rollup)
115
+ - [Vite](#vite)
116
116
  - [Node.js](#nodejs)
117
117
  - [CLI](#cli)
118
118
  - [Publishing to NPM](#publishing-to-npm)
@@ -167,26 +167,23 @@ bun i -D sveld
167
167
  yarn add -D sveld
168
168
  ```
169
169
 
170
- ### Rollup
170
+ ### Vite
171
171
 
172
- Import and add `sveld` as a plugin to your `rollup.config.js`.
172
+ Import and add `sveld` as a plugin to your `vite.config.ts`. The plugin only runs during `vite build` (not the dev server).
173
173
 
174
- ```js
175
- // rollup.config.js
176
- import svelte from "rollup-plugin-svelte";
177
- import resolve from "@rollup/plugin-node-resolve";
174
+ ```ts
175
+ // vite.config.ts
176
+ import { svelte } from "@sveltejs/vite-plugin-svelte";
178
177
  import sveld from "sveld";
178
+ import { defineConfig } from "vite";
179
179
 
180
- export default {
181
- input: "src/index.js",
182
- output: {
183
- format: "es",
184
- file: "lib/index.mjs",
185
- },
186
- plugins: [svelte(), resolve(), sveld()],
187
- };
180
+ export default defineConfig({
181
+ plugins: [svelte(), sveld()],
182
+ });
188
183
  ```
189
184
 
185
+ Since Vite uses Rollup for production builds, `sveld` also works in Rollup configurations.
186
+
190
187
  By default, `sveld` will use the `"svelte"` field from your `package.json` to determine the entry point. You can override this by specifying an explicit `entry` option:
191
188
 
192
189
  ```js
@@ -209,16 +206,6 @@ sveld({
209
206
  })
210
207
  ```
211
208
 
212
- The [tests/e2e](tests/e2e) folder contains example set-ups:
213
-
214
- - [single-export](tests/e2e/single-export): library that exports one component
215
- - [single-export-default-only](tests/e2e/single-export-default-only): library that exports one component using the concise `export { default } ...` syntax
216
- - [multi-export](tests/e2e/multi-export): multi-component library without JSDoc annotations (types are inferred)
217
- - [multi-export-typed](tests/e2e/multi-export-typed): multi-component library with JSDoc annotations
218
- - [multi-export-typed-ts-only](tests/e2e/multi-export-typed-ts-only): multi-component library that only generates TS definitions
219
- - [glob](tests/e2e/glob): library that uses the glob strategy to collect/analyze \*.svelte files
220
- - [carbon](tests/e2e/carbon): full `carbon-components-svelte` example
221
-
222
209
  ### CLI
223
210
 
224
211
  The CLI uses the `"svelte"` field from your `package.json` as the entry point:
@@ -299,7 +286,7 @@ TypeScript definitions are outputted to the `types` folder by default. Don't for
299
286
 
300
287
  ## Available Options
301
288
 
302
- ### Rollup Plugin Options
289
+ ### Plugin Options
303
290
 
304
291
  - **`entry`** (string, optional): Specify the entry point to uncompiled Svelte source. If not provided, sveld will use the `"svelte"` field from `package.json`.
305
292
  - **`glob`** (boolean, optional): Enable glob mode to analyze all `*.svelte` files.
@@ -512,6 +512,23 @@ export default class ComponentParser {
512
512
  * ```
513
513
  */
514
514
  private aliasType;
515
+ /**
516
+ * Extracts a property's type from an object type string.
517
+ *
518
+ * Parses type strings like `{ value: string; other: number }` and returns
519
+ * the type for the requested property name. Handles nested braces, generics,
520
+ * and optional properties.
521
+ *
522
+ * @returns The property type string, or undefined if not found
523
+ */
524
+ private extractPropertyType;
525
+ /**
526
+ * Resolves the type of a MemberExpression (e.g., `obj.value`) by looking up
527
+ * the object's type annotation and extracting the property type.
528
+ *
529
+ * @returns The resolved type string, or undefined if it cannot be resolved
530
+ */
531
+ private resolveMemberExpressionType;
515
532
  /**
516
533
  * Adds or merges a slot definition to the slots map.
517
534
  *
@@ -32,6 +32,8 @@ const VAR_DECLARATION_REGEX = /(?:const|let|function)\s+(\w+)\s*[=(]/;
32
32
  * ```
33
33
  */
34
34
  const DESCRIPTION_DASH_PREFIX_REGEX = /^-\s*/;
35
+ /** Matches a single word character (letter, digit, or underscore). Used for dotted prop access validation. */
36
+ const WORD_CHAR_REGEX = /\w/;
35
37
  /**
36
38
  * Extracts description text after the last dash from JSDoc comments.
37
39
  *
@@ -733,6 +735,77 @@ class ComponentParser {
733
735
  return "any";
734
736
  return type.trim();
735
737
  }
738
+ /**
739
+ * Extracts a property's type from an object type string.
740
+ *
741
+ * Parses type strings like `{ value: string; other: number }` and returns
742
+ * the type for the requested property name. Handles nested braces, generics,
743
+ * and optional properties.
744
+ *
745
+ * @returns The property type string, or undefined if not found
746
+ */
747
+ extractPropertyType(typeStr, propName) {
748
+ const trimmed = typeStr.trim();
749
+ if (!trimmed.startsWith("{") || !trimmed.endsWith("}"))
750
+ return undefined;
751
+ const inner = trimmed.slice(1, -1);
752
+ const segments = [];
753
+ let depth = 0;
754
+ let current = "";
755
+ for (const char of inner) {
756
+ if (char === "{" || char === "<" || char === "(" || char === "[") {
757
+ depth++;
758
+ current += char;
759
+ }
760
+ else if (char === "}" || char === ">" || char === ")" || char === "]") {
761
+ depth--;
762
+ current += char;
763
+ }
764
+ else if ((char === ";" || char === ",") && depth === 0) {
765
+ segments.push(current.trim());
766
+ current = "";
767
+ }
768
+ else {
769
+ current += char;
770
+ }
771
+ }
772
+ if (current.trim())
773
+ segments.push(current.trim());
774
+ for (const segment of segments) {
775
+ if (!segment.startsWith(propName))
776
+ continue;
777
+ const afterName = segment.slice(propName.length);
778
+ if (afterName.length > 0 && WORD_CHAR_REGEX.test(afterName[0]))
779
+ continue;
780
+ let rest = afterName.trimStart();
781
+ if (rest.startsWith("?"))
782
+ rest = rest.slice(1).trimStart();
783
+ if (rest.startsWith(":")) {
784
+ return rest.slice(1).trim();
785
+ }
786
+ }
787
+ return undefined;
788
+ }
789
+ /**
790
+ * Resolves the type of a MemberExpression (e.g., `obj.value`) by looking up
791
+ * the object's type annotation and extracting the property type.
792
+ *
793
+ * @returns The resolved type string, or undefined if it cannot be resolved
794
+ */
795
+ resolveMemberExpressionType(expr) {
796
+ const memberExpr = expr;
797
+ if (memberExpr.computed || memberExpr.object?.type !== "Identifier" || memberExpr.property?.type !== "Identifier") {
798
+ return undefined;
799
+ }
800
+ const objName = memberExpr.object.name;
801
+ const propName = memberExpr.property.name;
802
+ if (!objName || !propName)
803
+ return undefined;
804
+ const objType = this.props.get(objName)?.type ?? this.findVariableTypeAndDescription(objName)?.type;
805
+ if (!objType)
806
+ return undefined;
807
+ return this.extractPropertyType(objType, propName);
808
+ }
736
809
  /**
737
810
  * Adds or merges a slot definition to the slots map.
738
811
  *
@@ -2317,14 +2390,14 @@ class ComponentParser {
2317
2390
  if (expression.type === "Literal" && "value" in expression) {
2318
2391
  slot_prop_value.value = String(expression.value);
2319
2392
  }
2393
+ else if (expression.type === "MemberExpression") {
2394
+ slot_prop_value.value = this.resolveMemberExpressionType(expression);
2395
+ }
2320
2396
  else if (expression.type !== "Identifier") {
2321
2397
  if (start !== undefined && end !== undefined) {
2322
2398
  if (expression.type === "ObjectExpression" || expression.type === "TemplateLiteral") {
2323
2399
  slot_prop_value.value = this.sourceAtPos(start + 1, end - 1);
2324
2400
  }
2325
- else {
2326
- slot_prop_value.value = this.sourceAtPos(start, end);
2327
- }
2328
2401
  }
2329
2402
  }
2330
2403
  }
package/lib/cli.js CHANGED
@@ -8,7 +8,7 @@ const plugin_node_resolve_1 = __importDefault(require("@rollup/plugin-node-resol
8
8
  const rollup_1 = require("rollup");
9
9
  const rollup_plugin_svelte_1 = __importDefault(require("rollup-plugin-svelte"));
10
10
  const get_svelte_entry_1 = require("./get-svelte-entry");
11
- const rollup_plugin_1 = require("./rollup-plugin");
11
+ const plugin_1 = require("./plugin");
12
12
  /**
13
13
  * Command-line interface for sveld.
14
14
  *
@@ -43,6 +43,6 @@ async function cli(process) {
43
43
  plugins: [(0, rollup_plugin_svelte_1.default)(), (0, plugin_node_resolve_1.default)()],
44
44
  });
45
45
  await rollup_bundle.generate({});
46
- const result = await (0, rollup_plugin_1.generateBundle)(input, options?.glob === true);
47
- (0, rollup_plugin_1.writeOutput)(result, options, input);
46
+ const result = await (0, plugin_1.generateBundle)(input, options?.glob === true);
47
+ (0, plugin_1.writeOutput)(result, options, input);
48
48
  }
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { default as ComponentParser } from "./ComponentParser";
2
2
  export { cli } from "./cli";
3
- export { default } from "./rollup-plugin";
3
+ export { default } from "./plugin";
4
4
  export { sveld } from "./sveld";
package/lib/index.js CHANGED
@@ -8,7 +8,7 @@ var ComponentParser_1 = require("./ComponentParser");
8
8
  Object.defineProperty(exports, "ComponentParser", { enumerable: true, get: function () { return __importDefault(ComponentParser_1).default; } });
9
9
  var cli_1 = require("./cli");
10
10
  Object.defineProperty(exports, "cli", { enumerable: true, get: function () { return cli_1.cli; } });
11
- var rollup_plugin_1 = require("./rollup-plugin");
12
- Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(rollup_plugin_1).default; } });
11
+ var plugin_1 = require("./plugin");
12
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(plugin_1).default; } });
13
13
  var sveld_1 = require("./sveld");
14
14
  Object.defineProperty(exports, "sveld", { enumerable: true, get: function () { return sveld_1.sveld; } });
@@ -23,12 +23,15 @@ export interface ComponentDocApi extends ParsedComponent {
23
23
  moduleName: string;
24
24
  }
25
25
  export type ComponentDocs = Map<ComponentModuleName, ComponentDocApi>;
26
- export default function pluginSveld(opts?: PluginSveldOptions): {
26
+ interface SveldPlugin {
27
27
  name: string;
28
+ apply?: "build" | "serve";
29
+ enforce?: "pre" | "post";
28
30
  buildStart(): void;
29
31
  generateBundle(): Promise<void>;
30
32
  writeBundle(): void;
31
- };
33
+ }
34
+ export default function pluginSveld(opts?: PluginSveldOptions): SveldPlugin;
32
35
  interface GenerateBundleResult {
33
36
  exports: ParsedExports;
34
37
  components: ComponentDocs;
@@ -25,7 +25,9 @@ function pluginSveld(opts) {
25
25
  let result;
26
26
  let input;
27
27
  return {
28
- name: "plugin-sveld",
28
+ name: "vite-plugin-sveld",
29
+ apply: "build",
30
+ enforce: "post",
29
31
  buildStart() {
30
32
  input = (0, get_svelte_entry_1.getSvelteEntry)(opts?.entry);
31
33
  },
package/lib/sveld.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type PluginSveldOptions } from "./rollup-plugin";
1
+ import { type PluginSveldOptions } from "./plugin";
2
2
  interface SveldOptions extends PluginSveldOptions {
3
3
  /**
4
4
  * Specify the input to the uncompiled Svelte source.
package/lib/sveld.js CHANGED
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.sveld = sveld;
4
4
  const get_svelte_entry_1 = require("./get-svelte-entry");
5
- const rollup_plugin_1 = require("./rollup-plugin");
5
+ const plugin_1 = require("./plugin");
6
6
  /**
7
7
  * Main entry point for programmatic sveld usage.
8
8
  *
@@ -28,6 +28,6 @@ async function sveld(opts) {
28
28
  const input = (0, get_svelte_entry_1.getSvelteEntry)(opts?.input);
29
29
  if (input === null)
30
30
  return;
31
- const result = await (0, rollup_plugin_1.generateBundle)(input, opts?.glob === true);
32
- (0, rollup_plugin_1.writeOutput)(result, opts || {}, input);
31
+ const result = await (0, plugin_1.generateBundle)(input, opts?.glob === true);
32
+ (0, plugin_1.writeOutput)(result, opts || {}, input);
33
33
  }
@@ -1,4 +1,4 @@
1
- import type { ComponentDocs } from "../rollup-plugin";
1
+ import type { ComponentDocs } from "../plugin";
2
2
  import type { AppendType } from "./MarkdownWriterBase";
3
3
  /**
4
4
  * Interface for markdown documents that can be used for rendering.
@@ -1,4 +1,4 @@
1
- import type { ComponentDocs } from "../rollup-plugin";
1
+ import type { ComponentDocs } from "../plugin";
2
2
  export interface WriteJsonOptions {
3
3
  input: string;
4
4
  inputDir: string;
@@ -1,4 +1,4 @@
1
- import type { ComponentDocs } from "../rollup-plugin";
1
+ import type { ComponentDocs } from "../plugin";
2
2
  import { type AppendType, MarkdownWriterBaseImpl } from "./MarkdownWriterBase";
3
3
  export type { AppendType };
4
4
  type OnAppend = (type: AppendType, document: BrowserWriterMarkdown) => void;
@@ -1,4 +1,4 @@
1
- import type { ComponentDocs } from "../rollup-plugin";
1
+ import type { ComponentDocs } from "../plugin";
2
2
  import WriterMarkdown, { type AppendType } from "./WriterMarkdown";
3
3
  export interface WriteMarkdownOptions {
4
4
  write?: boolean;
@@ -1,4 +1,4 @@
1
- import type { ComponentDocApi } from "../rollup-plugin";
1
+ import type { ComponentDocApi } from "../plugin";
2
2
  export declare function formatTsProps(props?: string): string;
3
3
  export declare function getTypeDefs(def: Pick<ComponentDocApi, "typedefs">): string;
4
4
  /**
@@ -1,5 +1,5 @@
1
1
  import type { ParsedExports } from "../parse-exports";
2
- import type { ComponentDocs } from "../rollup-plugin";
2
+ import type { ComponentDocs } from "../plugin";
3
3
  /**
4
4
  * Re-export browser-compatible functions from core module.
5
5
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sveld",
3
- "version": "0.25.13",
3
+ "version": "0.26.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Generate TypeScript definitions for your Svelte components.",
6
6
  "main": "./lib/index.js",
@@ -37,7 +37,9 @@
37
37
  "docgen",
38
38
  "typescript",
39
39
  "definitions",
40
- "JSDocs"
40
+ "JSDocs",
41
+ "vite",
42
+ "vite-plugin"
41
43
  ],
42
44
  "maintainers": [
43
45
  "Eric Liu (https://github.com/metonym)"