sveld 0.25.10 → 0.25.11
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/ComponentParser.d.ts +714 -5
- package/lib/ComponentParser.js +1542 -330
- package/lib/cli.d.ts +14 -0
- package/lib/cli.js +14 -0
- package/lib/create-exports.d.ts +41 -0
- package/lib/create-exports.js +107 -16
- package/lib/element-tag-map.d.ts +70 -0
- package/lib/element-tag-map.js +74 -6
- package/lib/index.js +4 -4
- package/lib/parse-exports.d.ts +22 -0
- package/lib/parse-exports.js +22 -0
- package/lib/resolve-alias.d.ts +48 -0
- package/lib/resolve-alias.js +83 -15
- package/lib/rollup-plugin.d.ts +41 -0
- package/lib/rollup-plugin.js +97 -8
- package/lib/sveld.d.ts +21 -0
- package/lib/sveld.js +21 -0
- package/lib/writer/MarkdownWriterBase.d.ts +29 -0
- package/lib/writer/MarkdownWriterBase.js +70 -0
- package/lib/writer/Writer.d.ts +77 -0
- package/lib/writer/Writer.js +78 -0
- package/lib/writer/WriterMarkdown.d.ts +28 -9
- package/lib/writer/WriterMarkdown.js +37 -48
- package/lib/writer/markdown-format-utils.d.ts +106 -0
- package/lib/writer/markdown-format-utils.js +108 -3
- package/lib/writer/markdown-render-utils.d.ts +16 -0
- package/lib/writer/markdown-render-utils.js +89 -0
- package/lib/writer/writer-json.d.ts +26 -0
- package/lib/writer/writer-json.js +80 -3
- package/lib/writer/writer-markdown-core.d.ts +19 -14
- package/lib/writer/writer-markdown-core.js +22 -114
- package/lib/writer/writer-markdown.d.ts +22 -0
- package/lib/writer/writer-markdown.js +24 -54
- package/lib/writer/writer-ts-definitions-core.d.ts +22 -0
- package/lib/writer/writer-ts-definitions-core.js +337 -104
- package/lib/writer/writer-ts-definitions.d.ts +58 -0
- package/lib/writer/writer-ts-definitions.js +43 -7
- package/package.json +1 -1
package/lib/ComponentParser.d.ts
CHANGED
|
@@ -1,157 +1,866 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagnostic information for component parsing.
|
|
3
|
+
*
|
|
4
|
+
* Used to provide context about the component being parsed for error
|
|
5
|
+
* messages and logging.
|
|
6
|
+
*/
|
|
1
7
|
interface ComponentParserDiagnostics {
|
|
8
|
+
/** The module/component name (e.g., "Button", "App") */
|
|
2
9
|
moduleName: string;
|
|
10
|
+
/** The file path to the component (e.g., "./Button.svelte") */
|
|
3
11
|
filePath: string;
|
|
4
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Options for configuring the ComponentParser behavior.
|
|
15
|
+
*/
|
|
5
16
|
interface ComponentParserOptions {
|
|
17
|
+
/** Enable verbose logging for debugging parsing issues */
|
|
6
18
|
verbose?: boolean;
|
|
7
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Parameter information for function props.
|
|
22
|
+
*
|
|
23
|
+
* Extracted from JSDoc `@param` tags to provide detailed function signatures.
|
|
24
|
+
*/
|
|
8
25
|
interface ComponentPropParam {
|
|
26
|
+
/** The parameter name */
|
|
9
27
|
name: string;
|
|
28
|
+
/** The parameter type (e.g., "string", "number", "CustomType") */
|
|
10
29
|
type: string;
|
|
30
|
+
/** Optional description from JSDoc */
|
|
11
31
|
description?: string;
|
|
32
|
+
/** Whether the parameter is optional */
|
|
12
33
|
optional?: boolean;
|
|
13
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Component prop definition extracted from Svelte component.
|
|
37
|
+
*
|
|
38
|
+
* Represents a single prop that can be passed to the component, including
|
|
39
|
+
* its type, default value, description, and metadata about whether it's
|
|
40
|
+
* required, reactive, or a function.
|
|
41
|
+
*/
|
|
14
42
|
interface ComponentProp {
|
|
43
|
+
/** The prop name as declared in the component */
|
|
15
44
|
name: string;
|
|
45
|
+
/** The declaration kind: "let" (required), "const" (optional with default), or "function" */
|
|
16
46
|
kind: "let" | "const" | "function";
|
|
47
|
+
/** Whether this prop is declared as `const` (has a default value) */
|
|
17
48
|
constant: boolean;
|
|
49
|
+
/** The TypeScript type of the prop (e.g., "string", "number | string") */
|
|
18
50
|
type?: string;
|
|
51
|
+
/** The default value as a string representation of the source code */
|
|
19
52
|
value?: string;
|
|
53
|
+
/** Description extracted from JSDoc comments */
|
|
20
54
|
description?: string;
|
|
55
|
+
/** Function parameters (for function props) extracted from `@param` tags */
|
|
21
56
|
params?: ComponentPropParam[];
|
|
57
|
+
/** Return type (for function props) extracted from `@returns` tag */
|
|
22
58
|
returnType?: string;
|
|
59
|
+
/** Whether this prop is a function (arrow function or function expression) */
|
|
23
60
|
isFunction: boolean;
|
|
61
|
+
/** Whether this prop is a function declaration (not an expression) */
|
|
24
62
|
isFunctionDeclaration: boolean;
|
|
63
|
+
/** Whether this prop is required (no default value, declared with `let`) */
|
|
25
64
|
isRequired: boolean;
|
|
65
|
+
/** Whether this prop is reactive (can change and trigger reactivity) */
|
|
26
66
|
reactive: boolean;
|
|
27
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Component slot definition.
|
|
70
|
+
*
|
|
71
|
+
* Represents a slot that can be used to pass content into the component.
|
|
72
|
+
* Includes information about slot props, fallback content, and descriptions.
|
|
73
|
+
*/
|
|
28
74
|
interface ComponentSlot {
|
|
75
|
+
/** The slot name (null or undefined for default slot) */
|
|
29
76
|
name?: string | null;
|
|
77
|
+
/** Whether this is the default slot */
|
|
30
78
|
default: boolean;
|
|
79
|
+
/** Fallback content to display when slot is not provided */
|
|
31
80
|
fallback?: string;
|
|
81
|
+
/** TypeScript type definition for slot props (e.g., "{ title: string }") */
|
|
32
82
|
slot_props?: string;
|
|
83
|
+
/** Description extracted from JSDoc `@slot` tags */
|
|
33
84
|
description?: string;
|
|
34
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Event that is forwarded from a child component or element.
|
|
88
|
+
*
|
|
89
|
+
* Forwarded events are those that use `on:eventname` syntax without
|
|
90
|
+
* a handler, passing the event through to the parent.
|
|
91
|
+
*/
|
|
35
92
|
interface ForwardedEvent {
|
|
93
|
+
/** Always "forwarded" for forwarded events */
|
|
36
94
|
type: "forwarded";
|
|
95
|
+
/** The event name (e.g., "click", "change") */
|
|
37
96
|
name: string;
|
|
97
|
+
/** The element or component that forwards this event */
|
|
38
98
|
element: ComponentInlineElement | ComponentElement;
|
|
99
|
+
/** Description extracted from JSDoc `@event` tags */
|
|
39
100
|
description?: string;
|
|
101
|
+
/** The detail type if explicitly specified in `@event` tag */
|
|
40
102
|
detail?: string;
|
|
41
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Event that is dispatched by the component.
|
|
106
|
+
*
|
|
107
|
+
* Dispatched events are those created with `createEventDispatcher()`
|
|
108
|
+
* and dispatched via `dispatch("eventname", detail)`.
|
|
109
|
+
*/
|
|
42
110
|
interface DispatchedEvent {
|
|
111
|
+
/** Always "dispatched" for dispatched events */
|
|
43
112
|
type: "dispatched";
|
|
113
|
+
/** The event name (e.g., "click", "change") */
|
|
44
114
|
name: string;
|
|
115
|
+
/** The detail type (e.g., "{ value: string }", "null", "CustomEvent<...>") */
|
|
45
116
|
detail?: string;
|
|
117
|
+
/** Description extracted from JSDoc `@event` tags */
|
|
46
118
|
description?: string;
|
|
47
119
|
}
|
|
48
120
|
type ComponentEvent = ForwardedEvent | DispatchedEvent;
|
|
121
|
+
/**
|
|
122
|
+
* Type definition extracted from JSDoc `@typedef` tags.
|
|
123
|
+
*
|
|
124
|
+
* Represents custom types defined in component comments that can be
|
|
125
|
+
* referenced by props, events, and other type annotations.
|
|
126
|
+
*/
|
|
49
127
|
interface TypeDef {
|
|
128
|
+
/** The type string representation (e.g., "{ x: number; y: number }") */
|
|
50
129
|
type: string;
|
|
130
|
+
/** The type name (e.g., "Point", "User") */
|
|
51
131
|
name: string;
|
|
132
|
+
/** Description extracted from JSDoc comments */
|
|
52
133
|
description?: string;
|
|
134
|
+
/** The full TypeScript type definition string (e.g., "type Point = { x: number; y: number }") */
|
|
53
135
|
ts: string;
|
|
54
136
|
}
|
|
55
|
-
type ComponentGenerics = [name: string, type: string];
|
|
137
|
+
type ComponentGenerics = [name: string, type: string] | null;
|
|
138
|
+
/**
|
|
139
|
+
* Represents an inline Svelte component element.
|
|
140
|
+
*
|
|
141
|
+
* Used to identify which component forwards an event or accepts rest props.
|
|
142
|
+
*/
|
|
56
143
|
interface ComponentInlineElement {
|
|
144
|
+
/** Always "InlineComponent" for component elements */
|
|
57
145
|
type: "InlineComponent";
|
|
146
|
+
/** The component name (e.g., "Button", "Modal") */
|
|
58
147
|
name: string;
|
|
59
148
|
}
|
|
60
149
|
interface ComponentElement {
|
|
61
150
|
type: "Element";
|
|
62
151
|
name: string;
|
|
152
|
+
/**
|
|
153
|
+
* For `svelte:element`, stores the hardcoded element tag if `this` is a literal string.
|
|
154
|
+
*
|
|
155
|
+
* When `svelte:element` is used with a static tag (e.g., `svelte:element this="div"`),
|
|
156
|
+
* this property contains the tag name. If the tag is dynamic, this property is undefined.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```svelte
|
|
160
|
+
* <!-- Static tag -->
|
|
161
|
+
* <svelte:element this="div" bind:this={elementRef} />
|
|
162
|
+
* // thisValue: "div"
|
|
163
|
+
*
|
|
164
|
+
* <!-- Dynamic tag -->
|
|
165
|
+
* <svelte:element this={tagName} bind:this={elementRef} />
|
|
166
|
+
* // thisValue: undefined
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
63
169
|
thisValue?: string;
|
|
64
170
|
}
|
|
65
171
|
type RestProps = undefined | ComponentInlineElement | ComponentElement;
|
|
172
|
+
/**
|
|
173
|
+
* Interface extension information from JSDoc `@extends` tag.
|
|
174
|
+
*
|
|
175
|
+
* Allows components to extend external TypeScript interfaces for
|
|
176
|
+
* better type safety and code reuse.
|
|
177
|
+
*/
|
|
66
178
|
interface Extends {
|
|
179
|
+
/** The interface name to extend (e.g., "ButtonProps") */
|
|
67
180
|
interface: string;
|
|
181
|
+
/** The import path for the interface (e.g., "./types" or "carbon-components-svelte") */
|
|
68
182
|
import: string;
|
|
69
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Property definition for a component context.
|
|
186
|
+
*
|
|
187
|
+
* Represents a single property in a context object created with `setContext`.
|
|
188
|
+
*/
|
|
70
189
|
interface ComponentContextProp {
|
|
190
|
+
/** The property name */
|
|
71
191
|
name: string;
|
|
192
|
+
/** The property type (inferred from JSDoc or variable types) */
|
|
72
193
|
type: string;
|
|
194
|
+
/** Description extracted from JSDoc comments on the variable */
|
|
73
195
|
description?: string;
|
|
196
|
+
/** Whether the property is optional */
|
|
74
197
|
optional: boolean;
|
|
75
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Component context definition.
|
|
201
|
+
*
|
|
202
|
+
* Represents a context created with `setContext(key, value)` that can be
|
|
203
|
+
* accessed by child components via `getContext(key)`.
|
|
204
|
+
*/
|
|
76
205
|
interface ComponentContext {
|
|
206
|
+
/** The context key (e.g., "modal", "tabs") */
|
|
77
207
|
key: string;
|
|
208
|
+
/** The generated TypeScript type name (e.g., "ModalContext", "TabsContext") */
|
|
78
209
|
typeName: string;
|
|
210
|
+
/** Description extracted from JSDoc comments */
|
|
79
211
|
description?: string;
|
|
212
|
+
/** Properties available in this context */
|
|
80
213
|
properties: ComponentContextProp[];
|
|
81
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Complete parsed component metadata.
|
|
217
|
+
*
|
|
218
|
+
* This is the main return type from {@link ComponentParser.parseSvelteComponent}.
|
|
219
|
+
* Contains all extracted information about a Svelte component including props,
|
|
220
|
+
* slots, events, types, and more.
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```ts
|
|
224
|
+
* const parser = new ComponentParser();
|
|
225
|
+
* const parsed = parser.parseSvelteComponent(source, {
|
|
226
|
+
* moduleName: "Button",
|
|
227
|
+
* filePath: "./Button.svelte"
|
|
228
|
+
* });
|
|
229
|
+
*
|
|
230
|
+
* // Access component metadata:
|
|
231
|
+
* parsed.props // Array of component props
|
|
232
|
+
* parsed.slots // Array of component slots
|
|
233
|
+
* parsed.events // Array of component events
|
|
234
|
+
* parsed.typedefs // Array of custom type definitions
|
|
235
|
+
* parsed.contexts // Array of context definitions
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
82
238
|
export interface ParsedComponent {
|
|
239
|
+
/** Component props that can be passed to the component */
|
|
83
240
|
props: ComponentProp[];
|
|
241
|
+
/** Exports from `<script context="module">` block */
|
|
84
242
|
moduleExports: ComponentProp[];
|
|
243
|
+
/** Slots available in the component template */
|
|
85
244
|
slots: ComponentSlot[];
|
|
245
|
+
/** Events that the component can dispatch or forward */
|
|
86
246
|
events: ComponentEvent[];
|
|
247
|
+
/** Custom type definitions from JSDoc `@typedef` tags */
|
|
87
248
|
typedefs: TypeDef[];
|
|
249
|
+
/** Generic type parameters (e.g., `[name: "T", type: "string"]`) or null */
|
|
88
250
|
generics: null | ComponentGenerics;
|
|
251
|
+
/** Rest props configuration (which elements/components accept rest props) */
|
|
89
252
|
rest_props: RestProps;
|
|
253
|
+
/** Interface extension from JSDoc `@extends` tag */
|
|
90
254
|
extends?: Extends;
|
|
255
|
+
/** Component-level description from `@component` HTML comment */
|
|
91
256
|
componentComment?: string;
|
|
257
|
+
/** Contexts created with `setContext` in the component */
|
|
92
258
|
contexts?: ComponentContext[];
|
|
93
259
|
}
|
|
94
260
|
export default class ComponentParser {
|
|
261
|
+
/** Parser configuration options (e.g., verbose logging) */
|
|
95
262
|
private options?;
|
|
263
|
+
/** Raw source code of the Svelte component being parsed */
|
|
96
264
|
private source?;
|
|
265
|
+
/** Compiled Svelte code containing extracted variables and AST */
|
|
97
266
|
private compiled?;
|
|
267
|
+
/** Parsed abstract syntax tree from the Svelte compiler */
|
|
98
268
|
private parsed?;
|
|
269
|
+
/** Rest props configuration (e.g., `$$restProps`) if present in component */
|
|
99
270
|
private rest_props?;
|
|
271
|
+
/** Component extension information (e.g., `extends` attribute) */
|
|
100
272
|
private extends?;
|
|
273
|
+
/** Component-level description extracted from `@component` HTML comment */
|
|
101
274
|
private componentComment?;
|
|
275
|
+
/** Set of reactive variable names found in the component */
|
|
102
276
|
private readonly reactive_vars;
|
|
277
|
+
/** Set of all variable declarations found in the component script */
|
|
103
278
|
private readonly vars;
|
|
279
|
+
/** Map of component props keyed by prop name */
|
|
104
280
|
private readonly props;
|
|
281
|
+
/** Map of module exports (functions/variables exported from script) keyed by name */
|
|
105
282
|
private readonly moduleExports;
|
|
283
|
+
/** Map of component slots keyed by slot name (null for default slot) */
|
|
106
284
|
private readonly slots;
|
|
285
|
+
/** Map of component events (dispatched events) keyed by event name */
|
|
107
286
|
private readonly events;
|
|
287
|
+
/** Map of event descriptions extracted from JSDoc comments keyed by event name */
|
|
108
288
|
private readonly eventDescriptions;
|
|
289
|
+
/** Map of forwarded events (events forwarded from child components) keyed by event name */
|
|
109
290
|
private readonly forwardedEvents;
|
|
291
|
+
/** Map of type definitions (typedefs) extracted from JSDoc comments keyed by type name */
|
|
110
292
|
private readonly typedefs;
|
|
111
|
-
|
|
293
|
+
/** Component generic type parameters (null if no generics) */
|
|
294
|
+
private generics;
|
|
295
|
+
/** Map of prop bindings (e.g., `bind:value`) keyed by prop name */
|
|
112
296
|
private readonly bindings;
|
|
297
|
+
/** Map of component contexts (created with `setContext`) keyed by context name */
|
|
113
298
|
private readonly contexts;
|
|
299
|
+
/** Cache for variable type and description information to avoid redundant lookups */
|
|
114
300
|
private variableInfoCache;
|
|
301
|
+
/** Cached array of source code lines split by newline for efficient line-based operations */
|
|
115
302
|
private sourceLinesCache?;
|
|
116
303
|
constructor(options?: ComponentParserOptions);
|
|
117
304
|
private static mapToArray;
|
|
118
305
|
private static assignValue;
|
|
119
306
|
private static formatComment;
|
|
307
|
+
/**
|
|
308
|
+
* Extracts and categorizes JSDoc tags from a parsed comment.
|
|
309
|
+
*
|
|
310
|
+
* Separates tags into type, param, returns, and additional categories while
|
|
311
|
+
* excluding tags that are handled separately (extends, restProps, slot, event, typedef).
|
|
312
|
+
*
|
|
313
|
+
* @param parsed - The parsed comment result from comment-parser
|
|
314
|
+
* @returns An object containing categorized tags and the comment description
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```ts
|
|
318
|
+
* // Input: Parsed comment with tags
|
|
319
|
+
* // Output:
|
|
320
|
+
* {
|
|
321
|
+
* type: { tag: "type", type: "string" },
|
|
322
|
+
* param: [
|
|
323
|
+
* { tag: "param", name: "value", type: "string" }
|
|
324
|
+
* ],
|
|
325
|
+
* returns: { tag: "returns", type: "void" },
|
|
326
|
+
* additional: [{ tag: "since", name: "1.0.0" }],
|
|
327
|
+
* description: "Main description text"
|
|
328
|
+
* }
|
|
329
|
+
* ```
|
|
330
|
+
*/
|
|
120
331
|
private getCommentTags;
|
|
121
332
|
/**
|
|
122
333
|
* Finds the last comment from an array of leading comments.
|
|
123
|
-
*
|
|
334
|
+
*
|
|
335
|
+
* TypeScript directives are stripped before parsing, so we can safely take
|
|
336
|
+
* the last comment as it will be the JSDoc comment if present.
|
|
337
|
+
*
|
|
338
|
+
* @param leadingComments - Array of comment nodes from the AST
|
|
339
|
+
* @returns The last comment's value if found, undefined otherwise
|
|
340
|
+
*
|
|
341
|
+
* @example
|
|
342
|
+
* ```ts
|
|
343
|
+
* // Given leadingComments with multiple comments:
|
|
344
|
+
* // [/* regular comment *\/, /** JSDoc comment *\/]
|
|
345
|
+
* // Returns: { value: " JSDoc comment " }
|
|
346
|
+
*
|
|
347
|
+
* // If no comments:
|
|
348
|
+
* // Returns: undefined
|
|
349
|
+
* ```
|
|
124
350
|
*/
|
|
125
351
|
private static findJSDocComment;
|
|
126
352
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
353
|
+
* Processes JSDoc comments from leadingComments and extracts structured information.
|
|
354
|
+
*
|
|
355
|
+
* Parses JSDoc comments to extract type information, parameters, return types,
|
|
356
|
+
* and descriptions. Handles both inline and block-level descriptions.
|
|
357
|
+
*
|
|
358
|
+
* @param leadingComments - Array of comment nodes from the AST
|
|
359
|
+
* @returns Structured JSDoc information or undefined if no JSDoc comment is found
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```ts
|
|
363
|
+
* // Input JSDoc:
|
|
364
|
+
* /**
|
|
365
|
+
* * @type {string}
|
|
366
|
+
* * @param {number} x - The x coordinate
|
|
367
|
+
* * @param {number} y - The y coordinate
|
|
368
|
+
* * @returns {void}
|
|
369
|
+
* * Description text
|
|
370
|
+
* *\/
|
|
371
|
+
*
|
|
372
|
+
* // Output:
|
|
373
|
+
* {
|
|
374
|
+
* type: "string",
|
|
375
|
+
* params: [
|
|
376
|
+
* { name: "x", type: "number", description: "The x coordinate", optional: false },
|
|
377
|
+
* { name: "y", type: "number", description: "The y coordinate", optional: false }
|
|
378
|
+
* ],
|
|
379
|
+
* returnType: "void",
|
|
380
|
+
* description: "Description text"
|
|
381
|
+
* }
|
|
382
|
+
* ```
|
|
383
|
+
*/
|
|
384
|
+
private processJSDocComment;
|
|
385
|
+
/**
|
|
386
|
+
* Checks if a MemberExpression represents a well-known numeric constant.
|
|
387
|
+
*
|
|
388
|
+
* Identifies constants from the Number and Math objects that should be
|
|
389
|
+
* typed as `number` rather than their literal values.
|
|
390
|
+
*
|
|
391
|
+
* @param memberExpr - The AST node to check
|
|
392
|
+
* @returns True if the expression is a recognized numeric constant
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* ```ts
|
|
396
|
+
* // Recognized constants:
|
|
397
|
+
* Number.POSITIVE_INFINITY // true
|
|
398
|
+
* Number.MAX_VALUE // true
|
|
399
|
+
* Math.PI // true
|
|
400
|
+
* Math.E // true
|
|
401
|
+
*
|
|
402
|
+
* // Not recognized:
|
|
403
|
+
* Custom.CONSTANT // false
|
|
404
|
+
* Number.UNKNOWN // false
|
|
405
|
+
* ```
|
|
129
406
|
*/
|
|
130
407
|
private isNumericConstant;
|
|
408
|
+
/**
|
|
409
|
+
* Extracts source code at the given position range.
|
|
410
|
+
*
|
|
411
|
+
* @param start - Start position in the source
|
|
412
|
+
* @param end - End position in the source
|
|
413
|
+
* @returns The source code substring, or undefined if source is not available
|
|
414
|
+
*/
|
|
131
415
|
private sourceAtPos;
|
|
416
|
+
/**
|
|
417
|
+
* Processes an initializer expression to extract its value, type, and function status.
|
|
418
|
+
*
|
|
419
|
+
* Handles various expression types including object literals, arrays, binary expressions,
|
|
420
|
+
* arrow functions, unary expressions, identifiers, member expressions, template literals,
|
|
421
|
+
* and primitive literals. Extracts the source code representation and infers types
|
|
422
|
+
* where possible.
|
|
423
|
+
*
|
|
424
|
+
* @param init - The initializer AST node
|
|
425
|
+
* @returns An object containing the value (source code), inferred type, and whether it's a function
|
|
426
|
+
*
|
|
427
|
+
* @example
|
|
428
|
+
* ```ts
|
|
429
|
+
* // ObjectExpression: { x: 1, y: 2 }
|
|
430
|
+
* // Returns: { value: "{ x: 1, y: 2 }", type: "{ x: 1, y: 2 }", isFunction: false }
|
|
431
|
+
*
|
|
432
|
+
* // ArrowFunctionExpression: () => {}
|
|
433
|
+
* // Returns: { value: undefined, type: "(...args: any[]) => any", isFunction: true }
|
|
434
|
+
*
|
|
435
|
+
* // Literal: "hello"
|
|
436
|
+
* // Returns: { value: '"hello"', type: "string", isFunction: false }
|
|
437
|
+
*
|
|
438
|
+
* // BinaryExpression: "a" + "b"
|
|
439
|
+
* // Returns: { value: '"a" + "b"', type: "string", isFunction: false }
|
|
440
|
+
*
|
|
441
|
+
* // MemberExpression: Math.PI
|
|
442
|
+
* // Returns: { value: "Math.PI", type: "number" (if numeric constant), isFunction: false }
|
|
443
|
+
* ```
|
|
444
|
+
*/
|
|
132
445
|
private processInitializer;
|
|
446
|
+
/**
|
|
447
|
+
* Collects reactive variables from the compiled Svelte component.
|
|
448
|
+
*
|
|
449
|
+
* Reactive variables are those that are both reassigned and writable,
|
|
450
|
+
* indicating they can change and trigger reactivity in Svelte.
|
|
451
|
+
*/
|
|
133
452
|
private collectReactiveVars;
|
|
453
|
+
/**
|
|
454
|
+
* Adds or merges a component prop to the props map.
|
|
455
|
+
*
|
|
456
|
+
* If a prop with the same name already exists, the new data is merged
|
|
457
|
+
* with the existing prop, with new values taking precedence.
|
|
458
|
+
*
|
|
459
|
+
* @param prop_name - The name of the prop
|
|
460
|
+
* @param data - The prop data to add or merge
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* ```ts
|
|
464
|
+
* // First call:
|
|
465
|
+
* addProp("count", { name: "count", type: "number", kind: "let" })
|
|
466
|
+
* // Props map: { "count" => { name: "count", type: "number", kind: "let" } }
|
|
467
|
+
*
|
|
468
|
+
* // Second call (merge):
|
|
469
|
+
* addProp("count", { description: "The count value" })
|
|
470
|
+
* // Props map: { "count" => { name: "count", type: "number", kind: "let", description: "The count value" } }
|
|
471
|
+
* ```
|
|
472
|
+
*/
|
|
134
473
|
private addProp;
|
|
474
|
+
/**
|
|
475
|
+
* Adds or merges a module export to the moduleExports map.
|
|
476
|
+
*
|
|
477
|
+
* Similar to {@link addProp}, but for exported values from the module script.
|
|
478
|
+
* If an export with the same name already exists, the new data is merged
|
|
479
|
+
* with the existing export.
|
|
480
|
+
*
|
|
481
|
+
* @param prop_name - The name of the exported value
|
|
482
|
+
* @param data - The export data to add or merge
|
|
483
|
+
*
|
|
484
|
+
* @example
|
|
485
|
+
* ```ts
|
|
486
|
+
* // For: export const API_URL = "https://api.example.com"
|
|
487
|
+
* addModuleExport("API_URL", {
|
|
488
|
+
* name: "API_URL",
|
|
489
|
+
* kind: "const",
|
|
490
|
+
* type: "string",
|
|
491
|
+
* value: '"https://api.example.com"'
|
|
492
|
+
* })
|
|
493
|
+
* ```
|
|
494
|
+
*/
|
|
135
495
|
private addModuleExport;
|
|
496
|
+
/**
|
|
497
|
+
* Normalizes type strings by aliasing common patterns.
|
|
498
|
+
*
|
|
499
|
+
* Converts `*` to `any` (common JSDoc wildcard) and trims whitespace
|
|
500
|
+
* from type annotations.
|
|
501
|
+
*
|
|
502
|
+
* @param type - The type string to normalize
|
|
503
|
+
* @returns The normalized type string
|
|
504
|
+
*
|
|
505
|
+
* @example
|
|
506
|
+
* ```ts
|
|
507
|
+
* aliasType("*") // Returns: "any"
|
|
508
|
+
* aliasType(" string ") // Returns: "string"
|
|
509
|
+
* aliasType("number") // Returns: "number"
|
|
510
|
+
* ```
|
|
511
|
+
*/
|
|
136
512
|
private aliasType;
|
|
513
|
+
/**
|
|
514
|
+
* Adds or merges a slot definition to the slots map.
|
|
515
|
+
*
|
|
516
|
+
* Handles both named slots and the default slot. If a slot with the same
|
|
517
|
+
* name already exists, merges the data with existing values taking precedence
|
|
518
|
+
* where appropriate.
|
|
519
|
+
*
|
|
520
|
+
* @param slot_name - Optional slot name (undefined/empty = default slot)
|
|
521
|
+
* @param slot_props - Optional slot props type definition
|
|
522
|
+
* @param slot_fallback - Optional fallback content for the slot
|
|
523
|
+
* @param slot_description - Optional description for the slot
|
|
524
|
+
*
|
|
525
|
+
* @example
|
|
526
|
+
* ```ts
|
|
527
|
+
* // Default slot:
|
|
528
|
+
* addSlot({ slot_name: undefined, slot_props: "{ children: string }" })
|
|
529
|
+
*
|
|
530
|
+
* // Named slot:
|
|
531
|
+
* addSlot({
|
|
532
|
+
* slot_name: "header",
|
|
533
|
+
* slot_props: "{ title: string }",
|
|
534
|
+
* slot_description: "Header slot with title prop"
|
|
535
|
+
* })
|
|
536
|
+
*
|
|
537
|
+
* // Slot with fallback:
|
|
538
|
+
* addSlot({
|
|
539
|
+
* slot_name: "footer",
|
|
540
|
+
* slot_fallback: "<p>Default footer</p>"
|
|
541
|
+
* })
|
|
542
|
+
* ```
|
|
543
|
+
*/
|
|
137
544
|
private addSlot;
|
|
545
|
+
/**
|
|
546
|
+
* Adds or merges a dispatched event to the events map.
|
|
547
|
+
*
|
|
548
|
+
* Handles event detail type inference: if no argument is provided to the
|
|
549
|
+
* dispatcher and no `@event` tag specifies a detail type, the detail defaults
|
|
550
|
+
* to `null`. Otherwise, uses the provided detail type.
|
|
551
|
+
*
|
|
552
|
+
* @param name - The event name
|
|
553
|
+
* @param detail - The event detail type string
|
|
554
|
+
* @param has_argument - Whether the dispatcher call includes a detail argument
|
|
555
|
+
* @param description - Optional event description
|
|
556
|
+
*
|
|
557
|
+
* @example
|
|
558
|
+
* ```ts
|
|
559
|
+
* // Event without detail:
|
|
560
|
+
* // createEventDispatcher()("click")
|
|
561
|
+
* addDispatchedEvent({
|
|
562
|
+
* name: "click",
|
|
563
|
+
* detail: "",
|
|
564
|
+
* has_argument: false,
|
|
565
|
+
* description: "Fires on click"
|
|
566
|
+
* })
|
|
567
|
+
* // Result: { type: "dispatched", name: "click", detail: "null" }
|
|
568
|
+
*
|
|
569
|
+
* // Event with detail:
|
|
570
|
+
* // dispatch("change", { value: 42 })
|
|
571
|
+
* addDispatchedEvent({
|
|
572
|
+
* name: "change",
|
|
573
|
+
* detail: "{ value: number }",
|
|
574
|
+
* has_argument: true,
|
|
575
|
+
* description: "Fires when value changes"
|
|
576
|
+
* })
|
|
577
|
+
* // Result: { type: "dispatched", name: "change", detail: "{ value: number }" }
|
|
578
|
+
* ```
|
|
579
|
+
*/
|
|
138
580
|
private addDispatchedEvent;
|
|
581
|
+
/**
|
|
582
|
+
* Parses custom types, events, slots, and other JSDoc annotations from component comments.
|
|
583
|
+
*
|
|
584
|
+
* Scans the entire source for JSDoc comment blocks and extracts structured information
|
|
585
|
+
* about events, typedefs, slots, extends, restProps, and generics. Handles complex
|
|
586
|
+
* description extraction logic that supports both inline descriptions and preceding
|
|
587
|
+
* line descriptions.
|
|
588
|
+
*
|
|
589
|
+
* @example
|
|
590
|
+
* ```ts
|
|
591
|
+
* // Parses comments like:
|
|
592
|
+
* /**
|
|
593
|
+
* * @event {CustomEvent} change - Fires when value changes
|
|
594
|
+
* * @property {string} value - The new value
|
|
595
|
+
* * @property {number} timestamp - When it changed
|
|
596
|
+
* *\/
|
|
597
|
+
*
|
|
598
|
+
* // Or:
|
|
599
|
+
* /**
|
|
600
|
+
* * Description for the event
|
|
601
|
+
* * @event change
|
|
602
|
+
* *\/
|
|
603
|
+
* ```
|
|
604
|
+
*/
|
|
139
605
|
private parseCustomTypes;
|
|
606
|
+
/**
|
|
607
|
+
* Builds an event detail type string from an array of property definitions.
|
|
608
|
+
*
|
|
609
|
+
* Creates an inline object type with JSDoc comments for each property,
|
|
610
|
+
* including descriptions and default values. Used for both event details
|
|
611
|
+
* and typedef property definitions.
|
|
612
|
+
*
|
|
613
|
+
* @param properties - Array of property definitions with name, type, description, etc.
|
|
614
|
+
* @param _eventName - Optional event name (unused, kept for API consistency)
|
|
615
|
+
* @returns A string representation of the object type with JSDoc comments
|
|
616
|
+
*
|
|
617
|
+
* @example
|
|
618
|
+
* ```ts
|
|
619
|
+
* // Input:
|
|
620
|
+
* [
|
|
621
|
+
* { name: "value", type: "string", description: "The new value" },
|
|
622
|
+
* { name: "count", type: "number", optional: true, default: "0" }
|
|
623
|
+
* ]
|
|
624
|
+
*
|
|
625
|
+
* // Output:
|
|
626
|
+
* "{ /** The new value *\/ value: string; /** @default 0 *\/ count?: number; }"
|
|
627
|
+
* ```
|
|
628
|
+
*/
|
|
140
629
|
private buildEventDetailFromProperties;
|
|
630
|
+
/**
|
|
631
|
+
* Generates a TypeScript type name for a context key.
|
|
632
|
+
*
|
|
633
|
+
* Converts kebab-case, snake_case, or space-separated keys into PascalCase
|
|
634
|
+
* with "Context" suffix. Splits on dashes, underscores, and spaces, then
|
|
635
|
+
* capitalizes each part.
|
|
636
|
+
*
|
|
637
|
+
* @param key - The context key (e.g., "simple-modal", "tabs_context", "My Context")
|
|
638
|
+
* @returns The generated type name (e.g., "SimpleModalContext", "TabsContext", "MyContextContext")
|
|
639
|
+
*
|
|
640
|
+
* @example
|
|
641
|
+
* ```ts
|
|
642
|
+
* generateContextTypeName("simple-modal") // Returns: "SimpleModalContext"
|
|
643
|
+
* generateContextTypeName("Tabs") // Returns: "TabsContext"
|
|
644
|
+
* generateContextTypeName("user_settings") // Returns: "UserSettingsContext"
|
|
645
|
+
* generateContextTypeName("my context") // Returns: "MyContextContext"
|
|
646
|
+
* ```
|
|
647
|
+
*/
|
|
141
648
|
private generateContextTypeName;
|
|
649
|
+
/**
|
|
650
|
+
* Builds a cache of variable type information from JSDoc comments.
|
|
651
|
+
*
|
|
652
|
+
* Scans the source code for variable declarations and extracts type information
|
|
653
|
+
* from preceding JSDoc comments. This cache is used to infer types for context
|
|
654
|
+
* properties and other variable references.
|
|
655
|
+
*
|
|
656
|
+
* @example
|
|
657
|
+
* ```ts
|
|
658
|
+
* // Source code:
|
|
659
|
+
* /**
|
|
660
|
+
* * @type {string}
|
|
661
|
+
* * The user's name
|
|
662
|
+
* *\/
|
|
663
|
+
* const userName = "John";
|
|
664
|
+
*
|
|
665
|
+
* // Cache entry:
|
|
666
|
+
* // { "userName": { type: "string", description: "The user's name" } }
|
|
667
|
+
* ```
|
|
668
|
+
*/
|
|
142
669
|
private buildVariableInfoCache;
|
|
670
|
+
/**
|
|
671
|
+
* Cache for compiled regex patterns for variable name matching.
|
|
672
|
+
*
|
|
673
|
+
* Stores three regex patterns (const, let, function) per variable name
|
|
674
|
+
* to avoid recreating them on each lookup. Improves performance when
|
|
675
|
+
* searching for the same variable multiple times.
|
|
676
|
+
*/
|
|
143
677
|
private static readonly VAR_NAME_REGEX_CACHE;
|
|
678
|
+
/**
|
|
679
|
+
* Gets or creates cached regex patterns for matching variable declarations.
|
|
680
|
+
*
|
|
681
|
+
* Creates three regex patterns for matching const, let, and function declarations
|
|
682
|
+
* of a specific variable name. The patterns are cached to avoid recreating them
|
|
683
|
+
* for the same variable name.
|
|
684
|
+
*
|
|
685
|
+
* @param varName - The variable name to create regex patterns for
|
|
686
|
+
* @returns A tuple of three RegExp objects for const, let, and function patterns
|
|
687
|
+
*
|
|
688
|
+
* @example
|
|
689
|
+
* ```ts
|
|
690
|
+
* getVarNameRegexes("count")
|
|
691
|
+
* // Returns:
|
|
692
|
+
* // [
|
|
693
|
+
* // /\bconst\s+count\s*=/,
|
|
694
|
+
* // /\blet\s+count\s*=/,
|
|
695
|
+
* // /\bfunction\s+count\s*\(/
|
|
696
|
+
* // ]
|
|
697
|
+
* ```
|
|
698
|
+
*/
|
|
144
699
|
private static getVarNameRegexes;
|
|
700
|
+
/**
|
|
701
|
+
* Finds the type and description for a variable by searching for its JSDoc comment.
|
|
702
|
+
*
|
|
703
|
+
* First checks the cache built by {@link buildVariableInfoCache}. If not found,
|
|
704
|
+
* searches the source code directly for the variable declaration and its
|
|
705
|
+
* preceding JSDoc comment.
|
|
706
|
+
*
|
|
707
|
+
* @param varName - The variable name to look up
|
|
708
|
+
* @returns The type and description if found, null otherwise
|
|
709
|
+
*
|
|
710
|
+
* @example
|
|
711
|
+
* ```ts
|
|
712
|
+
* // Source:
|
|
713
|
+
* /**
|
|
714
|
+
* * @type {number}
|
|
715
|
+
* * The count value
|
|
716
|
+
* *\/
|
|
717
|
+
* const count = 0;
|
|
718
|
+
*
|
|
719
|
+
* findVariableTypeAndDescription("count")
|
|
720
|
+
* // Returns: { type: "number", description: "The count value" }
|
|
721
|
+
* ```
|
|
722
|
+
*/
|
|
145
723
|
private findVariableTypeAndDescription;
|
|
724
|
+
/**
|
|
725
|
+
* Parses a context value from an AST node to extract type information.
|
|
726
|
+
*
|
|
727
|
+
* Handles two cases:
|
|
728
|
+
* 1. ObjectExpression: Parses object literal properties and infers types from variable references
|
|
729
|
+
* 2. Identifier: Looks up the variable's type from JSDoc comments
|
|
730
|
+
*
|
|
731
|
+
* @param node - The AST node representing the context value
|
|
732
|
+
* @param key - The context key name
|
|
733
|
+
* @returns A ComponentContext object with parsed properties, or null if parsing fails
|
|
734
|
+
*
|
|
735
|
+
* @example
|
|
736
|
+
* ```ts
|
|
737
|
+
* // Case 1: Object literal
|
|
738
|
+
* // setContext('modal', { open, close })
|
|
739
|
+
* // Returns: { key: "modal", typeName: "ModalContext", properties: [...] }
|
|
740
|
+
*
|
|
741
|
+
* // Case 2: Variable reference
|
|
742
|
+
* // setContext('tabs', tabContext)
|
|
743
|
+
* // Returns: { key: "tabs", typeName: "TabsContext", properties: [...] }
|
|
744
|
+
* ```
|
|
745
|
+
*/
|
|
146
746
|
private parseContextValue;
|
|
747
|
+
/**
|
|
748
|
+
* Parses a `setContext` call expression to extract context information.
|
|
749
|
+
*
|
|
750
|
+
* Extracts the context key from the first argument (must be a string literal
|
|
751
|
+
* or simple template literal) and the context value from the second argument.
|
|
752
|
+
* Only processes static keys - dynamic keys are skipped with a warning.
|
|
753
|
+
*
|
|
754
|
+
* @param node - The AST node (should be a CallExpression)
|
|
755
|
+
* @param _parent - The parent node (unused)
|
|
756
|
+
*
|
|
757
|
+
* @example
|
|
758
|
+
* ```ts
|
|
759
|
+
* // Parses: setContext('modal', { open, close })
|
|
760
|
+
* // Extracts: key = "modal", value = { open, close }
|
|
761
|
+
*
|
|
762
|
+
* // Skips: setContext(dynamicKey, value) // key is not a literal
|
|
763
|
+
* ```
|
|
764
|
+
*/
|
|
147
765
|
private parseSetContextCall;
|
|
766
|
+
/**
|
|
767
|
+
* Cleans up all parser state, resetting the instance for reuse.
|
|
768
|
+
*
|
|
769
|
+
* Clears all maps, caches, and resets all state variables to their initial
|
|
770
|
+
* values. Should be called before parsing a new component or when the
|
|
771
|
+
* parser instance needs to be reset.
|
|
772
|
+
*
|
|
773
|
+
* @example
|
|
774
|
+
* ```ts
|
|
775
|
+
* parser.parseSvelteComponent(source1, diagnostics1);
|
|
776
|
+
* parser.cleanup(); // Reset state
|
|
777
|
+
* parser.parseSvelteComponent(source2, diagnostics2); // Fresh parse
|
|
778
|
+
* ```
|
|
779
|
+
*/
|
|
148
780
|
cleanup(): void;
|
|
781
|
+
/**
|
|
782
|
+
* Pre-compiled regex for matching script blocks in Svelte components.
|
|
783
|
+
*
|
|
784
|
+
* Matches `<script>` tags and their content, capturing the opening tag,
|
|
785
|
+
* script content, and closing tag. Global and case-insensitive flags
|
|
786
|
+
* allow matching multiple script blocks.
|
|
787
|
+
*
|
|
788
|
+
* @example
|
|
789
|
+
* ```ts
|
|
790
|
+
* // Matches:
|
|
791
|
+
* // "<script>const x = 1;</script>"
|
|
792
|
+
* // "<script lang='ts'>...</script>"
|
|
793
|
+
* ```
|
|
794
|
+
*/
|
|
149
795
|
private static readonly SCRIPT_BLOCK_REGEX;
|
|
796
|
+
/**
|
|
797
|
+
* Pre-compiled regex for matching TypeScript directive comments.
|
|
798
|
+
*
|
|
799
|
+
* Matches TypeScript directive comments like ts-ignore, ts-expect-error,
|
|
800
|
+
* etc. Used to remove these directives from script blocks before JSDoc parsing.
|
|
801
|
+
*
|
|
802
|
+
* @example
|
|
803
|
+
* ```ts
|
|
804
|
+
* // Matches:
|
|
805
|
+
* // "// ts-ignore"
|
|
806
|
+
* // "// ts-expect-error: reason"
|
|
807
|
+
* // "// ts-nocheck"
|
|
808
|
+
* ```
|
|
809
|
+
*/
|
|
150
810
|
private static readonly TS_DIRECTIVE_REGEX;
|
|
151
811
|
/**
|
|
152
812
|
* Strips TypeScript directive comments from script blocks only.
|
|
813
|
+
*
|
|
814
|
+
* Removes TypeScript directive comments (e.g., ts-ignore, ts-expect-error directives)
|
|
815
|
+
* from within `<script>` blocks to prevent them from interfering with JSDoc parsing.
|
|
816
|
+
* Directives outside script blocks are left untouched.
|
|
817
|
+
*
|
|
818
|
+
* @param source - The Svelte component source code
|
|
819
|
+
* @returns The source code with TypeScript directives removed from script blocks
|
|
820
|
+
*
|
|
821
|
+
* @example
|
|
822
|
+
* ```ts
|
|
823
|
+
* // Input (with TypeScript directive):
|
|
824
|
+
* <script>
|
|
825
|
+
* const x: string = 123; // directive removed
|
|
826
|
+
* </script>
|
|
827
|
+
*
|
|
828
|
+
* // Output (directive stripped):
|
|
829
|
+
* <script>
|
|
830
|
+
* const x: string = 123;
|
|
831
|
+
* </script>
|
|
832
|
+
* ```
|
|
153
833
|
*/
|
|
154
834
|
private static stripTypeScriptDirectivesFromScripts;
|
|
835
|
+
/**
|
|
836
|
+
* Parses a Svelte component and extracts all component metadata.
|
|
837
|
+
*
|
|
838
|
+
* This is the main entry point that orchestrates the entire parsing process:
|
|
839
|
+
* 1. Cleans up previous state
|
|
840
|
+
* 2. Strips TypeScript directives that might interfere with JSDoc
|
|
841
|
+
* 3. Compiles the component to get the AST
|
|
842
|
+
* 4. Collects reactive variables
|
|
843
|
+
* 5. Builds variable type cache
|
|
844
|
+
* 6. Parses custom types from JSDoc comments
|
|
845
|
+
* 7. Walks the AST to extract props, slots, events, bindings, and contexts
|
|
846
|
+
* 8. Post-processes events to distinguish dispatched vs forwarded
|
|
847
|
+
* 9. Processes props with bindings and slots with prop references
|
|
848
|
+
* 10. Returns the complete parsed component structure
|
|
849
|
+
*
|
|
850
|
+
* @param source - The Svelte component source code
|
|
851
|
+
* @param diagnostics - Diagnostic information (module name and file path)
|
|
852
|
+
* @returns A ParsedComponent object containing all extracted metadata
|
|
853
|
+
*
|
|
854
|
+
* @example
|
|
855
|
+
* ```ts
|
|
856
|
+
* const parser = new ComponentParser();
|
|
857
|
+
* const result = parser.parseSvelteComponent(source, {
|
|
858
|
+
* moduleName: "Button",
|
|
859
|
+
* filePath: "./Button.svelte"
|
|
860
|
+
* });
|
|
861
|
+
* // Returns: { props: [...], slots: [...], events: [...], ... }
|
|
862
|
+
* ```
|
|
863
|
+
*/
|
|
155
864
|
parseSvelteComponent(source: string, diagnostics: ComponentParserDiagnostics): ParsedComponent;
|
|
156
865
|
}
|
|
157
866
|
export {};
|