sveld 0.24.4 → 0.24.6
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 +91 -0
- package/lib/ComponentParser.d.ts +1 -0
- package/lib/ComponentParser.js +34 -2
- package/lib/writer/writer-ts-definitions-core.js +50 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -131,6 +131,7 @@ export default class Button extends SvelteComponentTyped<
|
|
|
131
131
|
- [@extends](#extends)
|
|
132
132
|
- [@generics](#generics)
|
|
133
133
|
- [@component comments](#component-comments)
|
|
134
|
+
- [Accessor Props](#accessor-props)
|
|
134
135
|
- [Contributing](#contributing)
|
|
135
136
|
- [License](#license)
|
|
136
137
|
|
|
@@ -988,6 +989,96 @@ export default class Button extends SvelteComponentTyped<
|
|
|
988
989
|
> {}
|
|
989
990
|
```
|
|
990
991
|
|
|
992
|
+
### Accessor Props
|
|
993
|
+
|
|
994
|
+
Exported functions and consts become accessor props in generated TypeScript definitions. Use `@type` to document function signatures, or use `@param` and `@returns` (or `@return`) JSDoc tags for richer documentation.
|
|
995
|
+
|
|
996
|
+
Note that `@type` tag annotations take precedence over `@param`/`@returns` tags.
|
|
997
|
+
|
|
998
|
+
Signature:
|
|
999
|
+
|
|
1000
|
+
```js
|
|
1001
|
+
/**
|
|
1002
|
+
* Function description
|
|
1003
|
+
* @param {Type} paramName - Parameter description
|
|
1004
|
+
* @param {Type} [optionalParam] - Optional parameter
|
|
1005
|
+
* @returns {ReturnType} Return value description
|
|
1006
|
+
*/
|
|
1007
|
+
```
|
|
1008
|
+
|
|
1009
|
+
Example:
|
|
1010
|
+
|
|
1011
|
+
```svelte
|
|
1012
|
+
<script>
|
|
1013
|
+
/**
|
|
1014
|
+
* @typedef {object} NotificationData
|
|
1015
|
+
* @property {string} [id] - Optional id for deduplication
|
|
1016
|
+
* @property {"error" | "info" | "success"} [kind]
|
|
1017
|
+
*/
|
|
1018
|
+
|
|
1019
|
+
/**
|
|
1020
|
+
* Add a notification to the queue.
|
|
1021
|
+
* @param {NotificationData} notification
|
|
1022
|
+
* @returns {string} The notification id
|
|
1023
|
+
*/
|
|
1024
|
+
export function add(notification) {
|
|
1025
|
+
const id = notification.id ?? "id";
|
|
1026
|
+
return id;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* Remove a notification by id.
|
|
1031
|
+
* @param {string} id
|
|
1032
|
+
* @returns {boolean} True if the notification was found and removed
|
|
1033
|
+
*/
|
|
1034
|
+
export function remove(id) {
|
|
1035
|
+
return true;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
/**
|
|
1039
|
+
* Get notification count.
|
|
1040
|
+
* @returns {number} The number of notifications
|
|
1041
|
+
*/
|
|
1042
|
+
export function getCount() {
|
|
1043
|
+
return 0;
|
|
1044
|
+
}
|
|
1045
|
+
</script>
|
|
1046
|
+
```
|
|
1047
|
+
|
|
1048
|
+
Output:
|
|
1049
|
+
|
|
1050
|
+
```ts
|
|
1051
|
+
export type NotificationData = {
|
|
1052
|
+
/** Optional id for deduplication */ id?: string;
|
|
1053
|
+
kind?: "error" | "info" | "success";
|
|
1054
|
+
};
|
|
1055
|
+
|
|
1056
|
+
export type ComponentProps = Record<string, never>;
|
|
1057
|
+
|
|
1058
|
+
export default class Component extends SvelteComponentTyped<
|
|
1059
|
+
ComponentProps,
|
|
1060
|
+
Record<string, any>,
|
|
1061
|
+
Record<string, never>
|
|
1062
|
+
> {
|
|
1063
|
+
/**
|
|
1064
|
+
* Add a notification to the queue.
|
|
1065
|
+
*/
|
|
1066
|
+
add: (notification: NotificationData) => string;
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* Remove a notification by id.
|
|
1070
|
+
*/
|
|
1071
|
+
remove: (id: string) => boolean;
|
|
1072
|
+
|
|
1073
|
+
/**
|
|
1074
|
+
* Get notification count.
|
|
1075
|
+
*/
|
|
1076
|
+
getCount: () => number;
|
|
1077
|
+
}
|
|
1078
|
+
```
|
|
1079
|
+
|
|
1080
|
+
When only `@param` tags are present without `@returns`, the return type defaults to `any`. When only `@returns` is present without `@param`, the function signature is `() => returnType`.
|
|
1081
|
+
|
|
991
1082
|
## Contributing
|
|
992
1083
|
|
|
993
1084
|
Refer to the [contributing guidelines](CONTRIBUTING.md).
|
package/lib/ComponentParser.d.ts
CHANGED
package/lib/ComponentParser.js
CHANGED
|
@@ -696,6 +696,7 @@ class ComponentParser {
|
|
|
696
696
|
isFunctionDeclaration = true;
|
|
697
697
|
}
|
|
698
698
|
let params;
|
|
699
|
+
let returnType;
|
|
699
700
|
if (node.leadingComments) {
|
|
700
701
|
const jsdoc_comment = ComponentParser.findJSDocComment(node.leadingComments);
|
|
701
702
|
if (jsdoc_comment) {
|
|
@@ -718,9 +719,23 @@ class ComponentParser {
|
|
|
718
719
|
optional: tag.optional || false,
|
|
719
720
|
}));
|
|
720
721
|
}
|
|
722
|
+
// Extract @returns/@return tag
|
|
723
|
+
const returnsTag = comment[0]?.tags.find((t) => t.tag === "returns" || t.tag === "return");
|
|
724
|
+
if (returnsTag)
|
|
725
|
+
returnType = this.aliasType(returnsTag.type);
|
|
721
726
|
// Build description from comment description and non-param/non-type tags
|
|
722
727
|
const commentDescription = ComponentParser.assignValue(comment[0]?.description?.trim());
|
|
723
|
-
const additionalTags = comment[0]?.tags.filter((tag) => ![
|
|
728
|
+
const additionalTags = comment[0]?.tags.filter((tag) => ![
|
|
729
|
+
"type",
|
|
730
|
+
"param",
|
|
731
|
+
"returns",
|
|
732
|
+
"return",
|
|
733
|
+
"extends",
|
|
734
|
+
"restProps",
|
|
735
|
+
"slot",
|
|
736
|
+
"event",
|
|
737
|
+
"typedef",
|
|
738
|
+
].includes(tag.tag)) ?? [];
|
|
724
739
|
if (commentDescription || additionalTags.length > 0) {
|
|
725
740
|
description = commentDescription || "";
|
|
726
741
|
for (const tag of additionalTags) {
|
|
@@ -739,6 +754,7 @@ class ComponentParser {
|
|
|
739
754
|
type,
|
|
740
755
|
value,
|
|
741
756
|
params,
|
|
757
|
+
returnType,
|
|
742
758
|
isFunction,
|
|
743
759
|
isFunctionDeclaration,
|
|
744
760
|
isRequired: false,
|
|
@@ -866,6 +882,7 @@ class ComponentParser {
|
|
|
866
882
|
isFunctionDeclaration = true;
|
|
867
883
|
}
|
|
868
884
|
let params;
|
|
885
|
+
let returnType;
|
|
869
886
|
if (node.leadingComments) {
|
|
870
887
|
const jsdoc_comment = ComponentParser.findJSDocComment(node.leadingComments);
|
|
871
888
|
if (jsdoc_comment) {
|
|
@@ -888,9 +905,23 @@ class ComponentParser {
|
|
|
888
905
|
optional: tag.optional || false,
|
|
889
906
|
}));
|
|
890
907
|
}
|
|
908
|
+
// Extract @returns/@return tag
|
|
909
|
+
const returnsTag = comment[0]?.tags.find((t) => t.tag === "returns" || t.tag === "return");
|
|
910
|
+
if (returnsTag)
|
|
911
|
+
returnType = this.aliasType(returnsTag.type);
|
|
891
912
|
// Build description from comment description and non-param/non-type tags
|
|
892
913
|
const commentDescription = ComponentParser.assignValue(comment[0]?.description?.trim());
|
|
893
|
-
const additional_tags = comment[0]?.tags.filter((tag) => ![
|
|
914
|
+
const additional_tags = comment[0]?.tags.filter((tag) => ![
|
|
915
|
+
"type",
|
|
916
|
+
"param",
|
|
917
|
+
"returns",
|
|
918
|
+
"return",
|
|
919
|
+
"extends",
|
|
920
|
+
"restProps",
|
|
921
|
+
"slot",
|
|
922
|
+
"event",
|
|
923
|
+
"typedef",
|
|
924
|
+
].includes(tag.tag)) ?? [];
|
|
894
925
|
if (commentDescription || additional_tags.length > 0) {
|
|
895
926
|
description = commentDescription || "";
|
|
896
927
|
for (const tag of additional_tags) {
|
|
@@ -909,6 +940,7 @@ class ComponentParser {
|
|
|
909
940
|
type,
|
|
910
941
|
value,
|
|
911
942
|
params,
|
|
943
|
+
returnType,
|
|
912
944
|
isFunction,
|
|
913
945
|
isFunctionDeclaration,
|
|
914
946
|
isRequired,
|
|
@@ -320,9 +320,35 @@ function genAccessors(def) {
|
|
|
320
320
|
const prop_comments = [addCommentLine(prop.description?.replace(NEWLINE_TO_COMMENT_REGEX, "\n* "))]
|
|
321
321
|
.filter(Boolean)
|
|
322
322
|
.join("");
|
|
323
|
+
// Determine the function signature
|
|
324
|
+
let functionType;
|
|
325
|
+
// Check if this is the default function type (would be overridden by @type or params/returns)
|
|
326
|
+
const isDefaultFunctionType = prop.type === "() => any";
|
|
327
|
+
// If @type tag provides a custom function signature (contains => and is not the default), use it (highest priority)
|
|
328
|
+
if (prop.type && FUNCTION_TYPE_REGEX.test(prop.type) && !isDefaultFunctionType) {
|
|
329
|
+
functionType = prop.type;
|
|
330
|
+
}
|
|
331
|
+
else if (prop.params && prop.params.length > 0) {
|
|
332
|
+
// Build signature from @param tags
|
|
333
|
+
const paramStrings = prop.params.map((param) => {
|
|
334
|
+
const optional = param.optional ? "?" : "";
|
|
335
|
+
return `${param.name}${optional}: ${param.type}`;
|
|
336
|
+
});
|
|
337
|
+
const paramsString = paramStrings.join(", ");
|
|
338
|
+
const returnType = prop.returnType || ANY_TYPE;
|
|
339
|
+
functionType = `(${paramsString}) => ${returnType}`;
|
|
340
|
+
}
|
|
341
|
+
else if (prop.returnType) {
|
|
342
|
+
// Only @returns is present without @param
|
|
343
|
+
functionType = `() => ${prop.returnType}`;
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
// Fall back to current prop.type
|
|
347
|
+
functionType = prop.type || ANY_TYPE;
|
|
348
|
+
}
|
|
323
349
|
return `
|
|
324
350
|
${prop_comments.length > 0 ? `/**\n${prop_comments}*/` : EMPTY_STR}
|
|
325
|
-
${prop.name}: ${
|
|
351
|
+
${prop.name}: ${functionType};`;
|
|
326
352
|
})
|
|
327
353
|
.join("\n");
|
|
328
354
|
}
|
|
@@ -349,7 +375,29 @@ function genModuleExports(def) {
|
|
|
349
375
|
.join("");
|
|
350
376
|
let type_def = `export type ${prop.name} = ${prop.type || ANY_TYPE};`;
|
|
351
377
|
const is_function = prop.type && FUNCTION_TYPE_REGEX.test(prop.type);
|
|
352
|
-
|
|
378
|
+
const isDefaultFunctionType = prop.type === "() => any";
|
|
379
|
+
if (is_function && prop.type && !isDefaultFunctionType) {
|
|
380
|
+
// @type tag provides a custom function signature (highest priority)
|
|
381
|
+
const [first, second, ...rest] = prop.type.split("=>");
|
|
382
|
+
const rest_type = rest.map((item) => `=>${item}`).join("");
|
|
383
|
+
type_def = `export declare function ${prop.name}${first}:${second}${rest_type};`;
|
|
384
|
+
}
|
|
385
|
+
else if (prop.params && prop.params.length > 0) {
|
|
386
|
+
// Build signature from @param tags
|
|
387
|
+
const paramStrings = prop.params.map((param) => {
|
|
388
|
+
const optional = param.optional ? "?" : "";
|
|
389
|
+
return `${param.name}${optional}: ${param.type}`;
|
|
390
|
+
});
|
|
391
|
+
const paramsString = paramStrings.join(", ");
|
|
392
|
+
const returnType = prop.returnType || ANY_TYPE;
|
|
393
|
+
type_def = `export declare function ${prop.name}(${paramsString}): ${returnType};`;
|
|
394
|
+
}
|
|
395
|
+
else if (prop.returnType) {
|
|
396
|
+
// Only @returns is present without @param
|
|
397
|
+
type_def = `export declare function ${prop.name}(): ${prop.returnType};`;
|
|
398
|
+
}
|
|
399
|
+
else if (is_function && prop.type) {
|
|
400
|
+
// Fall back to existing function type handling
|
|
353
401
|
const [first, second, ...rest] = prop.type.split("=>");
|
|
354
402
|
const rest_type = rest.map((item) => `=>${item}`).join("");
|
|
355
403
|
type_def = `export declare function ${prop.name}${first}:${second}${rest_type};`;
|