sveld 0.25.11 → 0.25.12
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 +34 -19
- package/lib/ComponentParser.js +103 -7
- package/lib/element-tag-map.d.ts +1 -2
- package/lib/element-tag-map.js +1 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
The purpose of this project is to make third party Svelte component libraries compatible with the Svelte Language Server and TypeScript with minimal effort required by the author. For example, TypeScript definitions may be used during development via intelligent code completion in Integrated Development Environments (IDE) like VSCode.
|
|
10
10
|
|
|
11
|
-
[Carbon Components Svelte](https://github.com/
|
|
11
|
+
[Carbon Components Svelte](https://github.com/carbon-design-system/carbon-components-svelte) uses this library to auto-generate component types and API metadata:
|
|
12
12
|
|
|
13
|
-
- [TypeScript definitions](https://github.com/
|
|
14
|
-
- [Component Index](https://github.com/
|
|
15
|
-
- [Component API](https://github.com/
|
|
13
|
+
- [TypeScript definitions](https://github.com/carbon-design-system/carbon-components-svelte/blob/master/types): Component TypeScript definitions
|
|
14
|
+
- [Component Index](https://github.com/carbon-design-system/carbon-components-svelte/blob/master/COMPONENT_INDEX.md): Markdown file documenting component props, slots, and events
|
|
15
|
+
- [Component API](https://github.com/carbon-design-system/carbon-components-svelte/blob/master/docs/src/COMPONENT_API.json): Component API metadata in JSON format
|
|
16
16
|
|
|
17
17
|
**Note:** `sveld` supports Svelte 3, 4, and 5, but does not support Svelte 5-specific syntax or runes-only usage. Components must use traditional Svelte syntax (e.g., `export let` for props, not `$props()`).
|
|
18
18
|
|
|
@@ -430,9 +430,12 @@ Output:
|
|
|
430
430
|
|
|
431
431
|
```ts
|
|
432
432
|
export type User = {
|
|
433
|
-
/** The user's full name */
|
|
434
|
-
|
|
435
|
-
/** The user's
|
|
433
|
+
/** The user's full name */
|
|
434
|
+
name: string;
|
|
435
|
+
/** The user's email address */
|
|
436
|
+
email: string;
|
|
437
|
+
/** The user's age in years */
|
|
438
|
+
age: number;
|
|
436
439
|
};
|
|
437
440
|
|
|
438
441
|
export type ComponentProps = {
|
|
@@ -478,10 +481,14 @@ Output:
|
|
|
478
481
|
|
|
479
482
|
```ts
|
|
480
483
|
export type ComponentConfig = {
|
|
481
|
-
/** Whether the component is enabled */
|
|
482
|
-
|
|
483
|
-
/**
|
|
484
|
-
|
|
484
|
+
/** Whether the component is enabled */
|
|
485
|
+
enabled: boolean;
|
|
486
|
+
/** The component theme */
|
|
487
|
+
theme: string;
|
|
488
|
+
/** Optional timeout in milliseconds @default 5000 */
|
|
489
|
+
timeout?: number;
|
|
490
|
+
/** Optional debug mode flag */
|
|
491
|
+
debug?: boolean;
|
|
485
492
|
};
|
|
486
493
|
|
|
487
494
|
export type ComponentProps = {
|
|
@@ -735,9 +742,12 @@ export default class Component extends SvelteComponentTyped<
|
|
|
735
742
|
{
|
|
736
743
|
/** Fired when the user submits the form */
|
|
737
744
|
submit: CustomEvent<{
|
|
738
|
-
/** The user's name */
|
|
739
|
-
|
|
740
|
-
/**
|
|
745
|
+
/** The user's name */
|
|
746
|
+
name: string;
|
|
747
|
+
/** The user's email address */
|
|
748
|
+
email: string;
|
|
749
|
+
/** Whether the user opted into the newsletter */
|
|
750
|
+
newsletter: boolean;
|
|
741
751
|
}>;
|
|
742
752
|
},
|
|
743
753
|
Record<string, never>
|
|
@@ -782,10 +792,14 @@ export default class Component extends SvelteComponentTyped<
|
|
|
782
792
|
{
|
|
783
793
|
/** Snowball event fired when throwing a snowball */
|
|
784
794
|
snowball: CustomEvent<{
|
|
785
|
-
/** Indicates whether the snowball is tightly packed */
|
|
786
|
-
|
|
787
|
-
/**
|
|
788
|
-
|
|
795
|
+
/** Indicates whether the snowball is tightly packed */
|
|
796
|
+
isPacked: boolean;
|
|
797
|
+
/** The speed of the snowball in mph */
|
|
798
|
+
speed: number;
|
|
799
|
+
/** Optional color of the snowball */
|
|
800
|
+
color?: string;
|
|
801
|
+
/** Optional density with default value @default 0.9 */
|
|
802
|
+
density?: number;
|
|
789
803
|
}>;
|
|
790
804
|
},
|
|
791
805
|
Record<string, never>
|
|
@@ -1171,7 +1185,8 @@ Output:
|
|
|
1171
1185
|
|
|
1172
1186
|
```ts
|
|
1173
1187
|
export type NotificationData = {
|
|
1174
|
-
/** Optional id for deduplication */
|
|
1188
|
+
/** Optional id for deduplication */
|
|
1189
|
+
id?: string;
|
|
1175
1190
|
kind?: "error" | "info" | "success";
|
|
1176
1191
|
};
|
|
1177
1192
|
|
package/lib/ComponentParser.js
CHANGED
|
@@ -526,8 +526,72 @@ class ComponentParser {
|
|
|
526
526
|
typeof unaryExpr.end === "number") {
|
|
527
527
|
value = this.sourceAtPos(unaryExpr.start, unaryExpr.end);
|
|
528
528
|
}
|
|
529
|
-
if (unaryExpr.argument
|
|
530
|
-
|
|
529
|
+
if (unaryExpr.argument) {
|
|
530
|
+
// If the argument is another UnaryExpression, recursively resolve the type
|
|
531
|
+
if (typeof unaryExpr.argument === "object" &&
|
|
532
|
+
"type" in unaryExpr.argument &&
|
|
533
|
+
unaryExpr.argument.type === "UnaryExpression") {
|
|
534
|
+
const nestedResult = this.processInitializer(unaryExpr.argument);
|
|
535
|
+
type = nestedResult.type;
|
|
536
|
+
}
|
|
537
|
+
else if (typeof unaryExpr.argument === "object" && "value" in unaryExpr.argument) {
|
|
538
|
+
// Direct literal argument
|
|
539
|
+
type = typeof unaryExpr.argument.value;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
else if (init.type === "NewExpression") {
|
|
544
|
+
const newExpr = init;
|
|
545
|
+
if ("start" in newExpr &&
|
|
546
|
+
"end" in newExpr &&
|
|
547
|
+
typeof newExpr.start === "number" &&
|
|
548
|
+
typeof newExpr.end === "number") {
|
|
549
|
+
value = this.sourceAtPos(newExpr.start, newExpr.end);
|
|
550
|
+
}
|
|
551
|
+
// Infer type from callee if it's an Identifier (e.g., new Date() -> Date)
|
|
552
|
+
if (newExpr.callee &&
|
|
553
|
+
typeof newExpr.callee === "object" &&
|
|
554
|
+
"type" in newExpr.callee &&
|
|
555
|
+
newExpr.callee.type === "Identifier") {
|
|
556
|
+
const calleeName = newExpr.callee.name;
|
|
557
|
+
// Common built-in constructors
|
|
558
|
+
if (calleeName === "Date") {
|
|
559
|
+
type = "Date";
|
|
560
|
+
}
|
|
561
|
+
else if (calleeName === "Map") {
|
|
562
|
+
type = "Map<any, any>";
|
|
563
|
+
}
|
|
564
|
+
else if (calleeName === "Set") {
|
|
565
|
+
type = "Set<any>";
|
|
566
|
+
}
|
|
567
|
+
else if (calleeName === "WeakMap") {
|
|
568
|
+
type = "WeakMap<object, any>";
|
|
569
|
+
}
|
|
570
|
+
else if (calleeName === "WeakSet") {
|
|
571
|
+
type = "WeakSet<object>";
|
|
572
|
+
}
|
|
573
|
+
else if (calleeName === "Array") {
|
|
574
|
+
type = "any[]";
|
|
575
|
+
}
|
|
576
|
+
else if (calleeName === "RegExp" || calleeName === "Regexp") {
|
|
577
|
+
type = "RegExp";
|
|
578
|
+
}
|
|
579
|
+
else if (calleeName === "Error") {
|
|
580
|
+
type = "Error";
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
// For other constructors, use the constructor name as the type
|
|
584
|
+
type = calleeName;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
else if (init.type === "CallExpression") {
|
|
589
|
+
const callExpr = init;
|
|
590
|
+
if ("start" in callExpr &&
|
|
591
|
+
"end" in callExpr &&
|
|
592
|
+
typeof callExpr.start === "number" &&
|
|
593
|
+
typeof callExpr.end === "number") {
|
|
594
|
+
value = this.sourceAtPos(callExpr.start, callExpr.end);
|
|
531
595
|
}
|
|
532
596
|
}
|
|
533
597
|
else if (init.type === "Identifier") {
|
|
@@ -958,7 +1022,7 @@ class ComponentParser {
|
|
|
958
1022
|
if (currentEventName !== undefined) {
|
|
959
1023
|
let detailType;
|
|
960
1024
|
if (eventProperties.length > 0) {
|
|
961
|
-
detailType = this.buildEventDetailFromProperties(eventProperties, currentEventName);
|
|
1025
|
+
detailType = this.buildEventDetailFromProperties(eventProperties, currentEventName, true);
|
|
962
1026
|
}
|
|
963
1027
|
else {
|
|
964
1028
|
detailType = currentEventType || "";
|
|
@@ -1008,8 +1072,9 @@ class ComponentParser {
|
|
|
1008
1072
|
if (typedefProperties.length > 0) {
|
|
1009
1073
|
/**
|
|
1010
1074
|
* Build type alias with property descriptions from `@property` tags.
|
|
1075
|
+
* Use multiline formatting for better readability.
|
|
1011
1076
|
*/
|
|
1012
|
-
typedefType = this.buildEventDetailFromProperties(typedefProperties);
|
|
1077
|
+
typedefType = this.buildEventDetailFromProperties(typedefProperties, undefined, true);
|
|
1013
1078
|
typedefTs = `type ${currentTypedefName} = ${typedefType}`;
|
|
1014
1079
|
}
|
|
1015
1080
|
else if (currentTypedefType) {
|
|
@@ -1199,7 +1264,7 @@ class ComponentParser {
|
|
|
1199
1264
|
* "{ /** The new value *\/ value: string; /** @default 0 *\/ count?: number; }"
|
|
1200
1265
|
* ```
|
|
1201
1266
|
*/
|
|
1202
|
-
buildEventDetailFromProperties(properties, _eventName) {
|
|
1267
|
+
buildEventDetailFromProperties(properties, _eventName, multiline = false) {
|
|
1203
1268
|
if (properties.length === 0)
|
|
1204
1269
|
return "null";
|
|
1205
1270
|
/**
|
|
@@ -1221,12 +1286,15 @@ class ComponentParser {
|
|
|
1221
1286
|
comment = `@default ${defaultValue}`;
|
|
1222
1287
|
}
|
|
1223
1288
|
if (comment) {
|
|
1289
|
+
if (multiline) {
|
|
1290
|
+
return `/** ${comment} */\n ${name}${optionalMarker}: ${type};`;
|
|
1291
|
+
}
|
|
1224
1292
|
return `/** ${comment} */ ${name}${optionalMarker}: ${type};`;
|
|
1225
1293
|
}
|
|
1226
1294
|
return `${name}${optionalMarker}: ${type};`;
|
|
1227
1295
|
})
|
|
1228
|
-
.join(" ");
|
|
1229
|
-
return `{ ${props} }`;
|
|
1296
|
+
.join(multiline ? "\n " : " ");
|
|
1297
|
+
return multiline ? `{\n ${props}\n}` : `{ ${props} }`;
|
|
1230
1298
|
}
|
|
1231
1299
|
/**
|
|
1232
1300
|
* Generates a TypeScript type name for a context key.
|
|
@@ -1919,6 +1987,20 @@ class ComponentParser {
|
|
|
1919
1987
|
description = jsdocInfo.description;
|
|
1920
1988
|
}
|
|
1921
1989
|
}
|
|
1990
|
+
// Merge returnType into type for function declarations if not overridden by @type
|
|
1991
|
+
if (isFunctionDeclaration && type === "() => any" && returnType) {
|
|
1992
|
+
if (params && params.length > 0) {
|
|
1993
|
+
const paramStrings = params.map((param) => {
|
|
1994
|
+
const optional = param.optional ? "?" : "";
|
|
1995
|
+
return `${param.name}${optional}: ${param.type}`;
|
|
1996
|
+
});
|
|
1997
|
+
const paramsString = paramStrings.join(", ");
|
|
1998
|
+
type = `(${paramsString}) => ${returnType}`;
|
|
1999
|
+
}
|
|
2000
|
+
else {
|
|
2001
|
+
type = `() => ${returnType}`;
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
1922
2004
|
if (!description && type && this.typedefs.has(type)) {
|
|
1923
2005
|
description = this.typedefs.get(type)?.description;
|
|
1924
2006
|
}
|
|
@@ -2138,6 +2220,20 @@ class ComponentParser {
|
|
|
2138
2220
|
description = jsdocInfo.description;
|
|
2139
2221
|
}
|
|
2140
2222
|
}
|
|
2223
|
+
// Merge returnType into type for function declarations if not overridden by @type
|
|
2224
|
+
if (isFunctionDeclaration && type === "() => any" && returnType) {
|
|
2225
|
+
if (params && params.length > 0) {
|
|
2226
|
+
const paramStrings = params.map((param) => {
|
|
2227
|
+
const optional = param.optional ? "?" : "";
|
|
2228
|
+
return `${param.name}${optional}: ${param.type}`;
|
|
2229
|
+
});
|
|
2230
|
+
const paramsString = paramStrings.join(", ");
|
|
2231
|
+
type = `(${paramsString}) => ${returnType}`;
|
|
2232
|
+
}
|
|
2233
|
+
else {
|
|
2234
|
+
type = `() => ${returnType}`;
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2141
2237
|
if (!description && type && this.typedefs.has(type)) {
|
|
2142
2238
|
description = this.typedefs.get(type)?.description;
|
|
2143
2239
|
}
|
package/lib/element-tag-map.d.ts
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Maps HTML element tag names to their corresponding TypeScript element types.
|
|
5
5
|
* Used for generating proper TypeScript types for element bindings and rest props.
|
|
6
|
-
*
|
|
7
|
-
* @see {@link https://github.com/microsoft/TypeScript/blob/master/lib/lib.dom.d.ts#L19263 | TypeScript lib.dom.d.ts}
|
|
6
|
+
* See the TypeScript lib.dom.d.ts for the original source.
|
|
8
7
|
*
|
|
9
8
|
* @example
|
|
10
9
|
* ```ts
|
package/lib/element-tag-map.js
CHANGED
|
@@ -6,8 +6,7 @@ exports.getElementByTag = getElementByTag;
|
|
|
6
6
|
*
|
|
7
7
|
* Maps HTML element tag names to their corresponding TypeScript element types.
|
|
8
8
|
* Used for generating proper TypeScript types for element bindings and rest props.
|
|
9
|
-
*
|
|
10
|
-
* @see {@link https://github.com/microsoft/TypeScript/blob/master/lib/lib.dom.d.ts#L19263 | TypeScript lib.dom.d.ts}
|
|
9
|
+
* See the TypeScript lib.dom.d.ts for the original source.
|
|
11
10
|
*
|
|
12
11
|
* @example
|
|
13
12
|
* ```ts
|