sveld 0.25.8 → 0.25.10
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 -8
- package/lib/ComponentParser.d.ts +1 -0
- package/lib/ComponentParser.js +58 -120
- package/lib/writer/markdown-format-utils.d.ts +11 -0
- package/lib/writer/markdown-format-utils.js +53 -0
- package/lib/writer/writer-json.js +10 -22
- package/lib/writer/writer-markdown-core.js +7 -47
- package/lib/writer/writer-markdown.js +7 -48
- package/lib/writer/writer-ts-definitions-core.js +6 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -196,7 +196,7 @@ By default, `sveld` will use the `"svelte"` field from your `package.json` to de
|
|
|
196
196
|
```js
|
|
197
197
|
sveld({
|
|
198
198
|
entry: "src/index.js",
|
|
199
|
-
})
|
|
199
|
+
});
|
|
200
200
|
```
|
|
201
201
|
|
|
202
202
|
When building the library, TypeScript definitions are emitted to the `types` folder by default.
|
|
@@ -254,7 +254,10 @@ sveld({
|
|
|
254
254
|
markdownOptions: {
|
|
255
255
|
onAppend: (type, document, components) => {
|
|
256
256
|
if (type === "h1")
|
|
257
|
-
document.append(
|
|
257
|
+
document.append(
|
|
258
|
+
"quote",
|
|
259
|
+
`${components.size} components exported from ${pkg.name}@${pkg.version}.`,
|
|
260
|
+
);
|
|
258
261
|
},
|
|
259
262
|
},
|
|
260
263
|
json: true,
|
|
@@ -605,7 +608,14 @@ type DataTableProps<Row> = {
|
|
|
605
608
|
// Snippet prop for Svelte 5 compatibility
|
|
606
609
|
cell?: (
|
|
607
610
|
this: void,
|
|
608
|
-
...args: [
|
|
611
|
+
...args: [
|
|
612
|
+
{
|
|
613
|
+
row: Row;
|
|
614
|
+
cell: DataTableCell<Row>;
|
|
615
|
+
rowIndex: number;
|
|
616
|
+
cellIndex: number;
|
|
617
|
+
},
|
|
618
|
+
]
|
|
609
619
|
) => void;
|
|
610
620
|
|
|
611
621
|
// Default slot as children prop
|
|
@@ -614,11 +624,18 @@ type DataTableProps<Row> = {
|
|
|
614
624
|
|
|
615
625
|
export default class DataTable<Row> extends SvelteComponentTyped<
|
|
616
626
|
DataTableProps<Row>,
|
|
617
|
-
{
|
|
627
|
+
{
|
|
628
|
+
/* events */
|
|
629
|
+
},
|
|
618
630
|
{
|
|
619
631
|
// Traditional slot definition (Svelte 3/4)
|
|
620
632
|
default: Record<string, never>;
|
|
621
|
-
cell: {
|
|
633
|
+
cell: {
|
|
634
|
+
row: Row;
|
|
635
|
+
cell: DataTableCell<Row>;
|
|
636
|
+
rowIndex: number;
|
|
637
|
+
cellIndex: number;
|
|
638
|
+
};
|
|
622
639
|
}
|
|
623
640
|
> {}
|
|
624
641
|
```
|
|
@@ -705,7 +722,7 @@ function handleSubmit() {
|
|
|
705
722
|
dispatch("submit", {
|
|
706
723
|
name: "Jane Doe",
|
|
707
724
|
email: "jane@example.com",
|
|
708
|
-
newsletter: true
|
|
725
|
+
newsletter: true,
|
|
709
726
|
});
|
|
710
727
|
}
|
|
711
728
|
```
|
|
@@ -752,7 +769,7 @@ const dispatch = createEventDispatcher();
|
|
|
752
769
|
function throwSnowball() {
|
|
753
770
|
dispatch("snowball", {
|
|
754
771
|
isPacked: true,
|
|
755
|
-
speed: 50
|
|
772
|
+
speed: 50,
|
|
756
773
|
});
|
|
757
774
|
}
|
|
758
775
|
```
|
|
@@ -1026,7 +1043,14 @@ Example
|
|
|
1026
1043
|
The generated TypeScript definition will resemble the following:
|
|
1027
1044
|
|
|
1028
1045
|
```ts
|
|
1029
|
-
|
|
1046
|
+
// Props type includes the full constraint, enabling indexed access types like Row["id"]
|
|
1047
|
+
export type ComponentProps<Row extends DataTableRow = any> = {
|
|
1048
|
+
rows?: ReadonlyArray<Row>;
|
|
1049
|
+
};
|
|
1050
|
+
|
|
1051
|
+
export default class Component<
|
|
1052
|
+
Row extends DataTableRow = any,
|
|
1053
|
+
> extends SvelteComponentTyped<
|
|
1030
1054
|
ComponentProps<Row>,
|
|
1031
1055
|
Record<string, any>,
|
|
1032
1056
|
Record<string, any>
|
|
@@ -1042,6 +1066,8 @@ For a parameter list, the name should be comma-separated but not include spaces.
|
|
|
1042
1066
|
```
|
|
1043
1067
|
|
|
1044
1068
|
```ts
|
|
1069
|
+
export type ComponentProps<Param1, Param2> = { ... };
|
|
1070
|
+
|
|
1045
1071
|
export default class Component<Param1, Param2> extends SvelteComponentTyped<
|
|
1046
1072
|
ComponentProps<Name1, Name2>,
|
|
1047
1073
|
Record<string, any>,
|
package/lib/ComponentParser.d.ts
CHANGED
package/lib/ComponentParser.js
CHANGED
|
@@ -7,6 +7,12 @@ const compiler_1 = require("svelte/compiler");
|
|
|
7
7
|
const element_tag_map_1 = require("./element-tag-map");
|
|
8
8
|
const COMMENT_BLOCK_DESCRIPTION_REGEX = /^-\s*/;
|
|
9
9
|
const VAR_DECLARATION_REGEX = /(?:const|let|function)\s+(\w+)\s*[=(]/;
|
|
10
|
+
function extractDescriptionAfterDash(description) {
|
|
11
|
+
if (!description)
|
|
12
|
+
return undefined;
|
|
13
|
+
const dashIndex = description.lastIndexOf("-");
|
|
14
|
+
return dashIndex >= 0 ? description.substring(dashIndex + 1).trim() : description.trim();
|
|
15
|
+
}
|
|
10
16
|
const DEFAULT_SLOT_NAME = null;
|
|
11
17
|
const TYPEDEF_END_REGEX = /(\}|\};)$/;
|
|
12
18
|
const PROPERTY_DESCRIPTION_REGEX = /^-\s*/;
|
|
@@ -134,6 +140,50 @@ class ComponentParser {
|
|
|
134
140
|
sourceAtPos(start, end) {
|
|
135
141
|
return this.source?.slice(start, end);
|
|
136
142
|
}
|
|
143
|
+
processInitializer(init) {
|
|
144
|
+
let value;
|
|
145
|
+
let type;
|
|
146
|
+
let isFunction = false;
|
|
147
|
+
if (init.type === "ObjectExpression" ||
|
|
148
|
+
init.type === "BinaryExpression" ||
|
|
149
|
+
init.type === "ArrayExpression" ||
|
|
150
|
+
init.type === "ArrowFunctionExpression") {
|
|
151
|
+
value = this.sourceAtPos(init.start, init.end)?.replace(NEWLINE_CR_REGEX, " ");
|
|
152
|
+
type = value;
|
|
153
|
+
isFunction = init.type === "ArrowFunctionExpression";
|
|
154
|
+
if (init.type === "BinaryExpression") {
|
|
155
|
+
if (init?.left.type === "Literal" && typeof init?.left.value === "string") {
|
|
156
|
+
type = "string";
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (init.type === "ArrowFunctionExpression") {
|
|
160
|
+
type = "(...args: any[]) => any";
|
|
161
|
+
value = undefined;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else if (init.type === "UnaryExpression") {
|
|
165
|
+
value = this.sourceAtPos(init.start, init.end);
|
|
166
|
+
type = typeof init.argument?.value;
|
|
167
|
+
}
|
|
168
|
+
else if (init.type === "Identifier") {
|
|
169
|
+
value = this.sourceAtPos(init.start, init.end);
|
|
170
|
+
}
|
|
171
|
+
else if (init.type === "MemberExpression") {
|
|
172
|
+
value = this.sourceAtPos(init.start, init.end);
|
|
173
|
+
if (this.isNumericConstant(init)) {
|
|
174
|
+
type = "number";
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else if (init.type === "TemplateLiteral") {
|
|
178
|
+
value = this.sourceAtPos(init.start, init.end);
|
|
179
|
+
type = "string";
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
value = init.raw;
|
|
183
|
+
type = init.value == null ? undefined : typeof init.value;
|
|
184
|
+
}
|
|
185
|
+
return { value, type, isFunction };
|
|
186
|
+
}
|
|
137
187
|
collectReactiveVars() {
|
|
138
188
|
const reactiveVars = this.compiled?.vars.filter(({ reassigned, writable }) => reassigned && writable) ?? [];
|
|
139
189
|
for (const { name } of reactiveVars) {
|
|
@@ -178,9 +228,7 @@ class ComponentParser {
|
|
|
178
228
|
const name = default_slot ? DEFAULT_SLOT_NAME : (slot_name ?? "");
|
|
179
229
|
const fallback = ComponentParser.assignValue(slot_fallback);
|
|
180
230
|
const props = ComponentParser.assignValue(slot_props);
|
|
181
|
-
const description = slot_description
|
|
182
|
-
? slot_description.substring(slot_description.lastIndexOf("-") + 1).trim()
|
|
183
|
-
: undefined;
|
|
231
|
+
const description = extractDescriptionAfterDash(slot_description);
|
|
184
232
|
if (this.slots.has(name)) {
|
|
185
233
|
const existing_slot = this.slots.get(name);
|
|
186
234
|
this.slots.set(name, {
|
|
@@ -209,7 +257,7 @@ class ComponentParser {
|
|
|
209
257
|
* `@event` is not specified.
|
|
210
258
|
*/
|
|
211
259
|
const default_detail = !has_argument && !detail ? "null" : ComponentParser.assignValue(detail);
|
|
212
|
-
const event_description =
|
|
260
|
+
const event_description = extractDescriptionAfterDash(description);
|
|
213
261
|
if (this.events.has(name)) {
|
|
214
262
|
const existing_event = this.events.get(name);
|
|
215
263
|
this.events.set(name, {
|
|
@@ -790,65 +838,12 @@ class ComponentParser {
|
|
|
790
838
|
}
|
|
791
839
|
const { type: declaration_type, id, init, } = node.declaration?.declarations ? node.declaration.declarations[0] : node.declaration;
|
|
792
840
|
const prop_name = id.name;
|
|
793
|
-
let value;
|
|
794
|
-
let type;
|
|
795
841
|
let kind = node.declaration.kind;
|
|
796
842
|
let description;
|
|
797
|
-
let isFunction = false;
|
|
798
843
|
let isFunctionDeclaration = false;
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
init.type === "BinaryExpression" ||
|
|
802
|
-
init.type === "ArrayExpression" ||
|
|
803
|
-
init.type === "ArrowFunctionExpression") {
|
|
804
|
-
value = this.sourceAtPos(init.start, init.end)?.replace(NEWLINE_CR_REGEX, " ");
|
|
805
|
-
type = value;
|
|
806
|
-
isFunction = init.type === "ArrowFunctionExpression";
|
|
807
|
-
if (init.type === "BinaryExpression") {
|
|
808
|
-
if (init?.left.type === "Literal" && typeof init?.left.value === "string") {
|
|
809
|
-
type = "string";
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
// For arrow functions, use a generic function type instead of the implementation
|
|
813
|
-
// Don't store the implementation in value - it clutters documentation
|
|
814
|
-
if (init.type === "ArrowFunctionExpression") {
|
|
815
|
-
type = "(...args: any[]) => any";
|
|
816
|
-
value = undefined;
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
else {
|
|
820
|
-
if (init.type === "UnaryExpression") {
|
|
821
|
-
value = this.sourceAtPos(init.start, init.end);
|
|
822
|
-
type = typeof init.argument?.value;
|
|
823
|
-
}
|
|
824
|
-
else if (init.type === "Identifier") {
|
|
825
|
-
// Handle non-literal defaults like variable references and global identifiers.
|
|
826
|
-
// Don't infer type, just preserve existing type annotation.
|
|
827
|
-
value = this.sourceAtPos(init.start, init.end);
|
|
828
|
-
}
|
|
829
|
-
else if (init.type === "MemberExpression") {
|
|
830
|
-
// Handle member expressions like Number.POSITIVE_INFINITY, Math.PI, etc.
|
|
831
|
-
value = this.sourceAtPos(init.start, init.end);
|
|
832
|
-
// Infer type as "number" for well-known numeric constants
|
|
833
|
-
if (this.isNumericConstant(init)) {
|
|
834
|
-
type = "number";
|
|
835
|
-
}
|
|
836
|
-
// Otherwise, don't infer type, just preserve existing type annotation.
|
|
837
|
-
}
|
|
838
|
-
else if (init.type === "TemplateLiteral") {
|
|
839
|
-
// Handle template literals - they always evaluate to strings
|
|
840
|
-
value = this.sourceAtPos(init.start, init.end);
|
|
841
|
-
type = "string";
|
|
842
|
-
}
|
|
843
|
-
else {
|
|
844
|
-
value = init.raw;
|
|
845
|
-
type = init.value == null ? undefined : typeof init.value;
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
}
|
|
844
|
+
const initResult = init != null ? this.processInitializer(init) : { isFunction: false };
|
|
845
|
+
let { value, type, isFunction } = initResult;
|
|
849
846
|
if (declaration_type === "FunctionDeclaration") {
|
|
850
|
-
// Don't store function body in value - it clutters documentation
|
|
851
|
-
// The type signature is what matters for API docs
|
|
852
847
|
value = undefined;
|
|
853
848
|
type = "() => any";
|
|
854
849
|
kind = "function";
|
|
@@ -982,66 +977,13 @@ class ComponentParser {
|
|
|
982
977
|
}
|
|
983
978
|
const { type: declaration_type, id, init, } = node.declaration.declarations ? node.declaration.declarations[0] : node.declaration;
|
|
984
979
|
prop_name ??= id.name;
|
|
985
|
-
let value;
|
|
986
|
-
let type;
|
|
987
980
|
let kind = node.declaration.kind;
|
|
988
981
|
let description;
|
|
989
|
-
let isFunction = false;
|
|
990
982
|
let isFunctionDeclaration = false;
|
|
991
983
|
const isRequired = kind === "let" && init == null;
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
init.type === "BinaryExpression" ||
|
|
995
|
-
init.type === "ArrayExpression" ||
|
|
996
|
-
init.type === "ArrowFunctionExpression") {
|
|
997
|
-
value = this.sourceAtPos(init.start, init.end)?.replace(NEWLINE_CR_REGEX, " ");
|
|
998
|
-
type = value;
|
|
999
|
-
isFunction = init.type === "ArrowFunctionExpression";
|
|
1000
|
-
if (init.type === "BinaryExpression") {
|
|
1001
|
-
if (init?.left.type === "Literal" && typeof init?.left.value === "string") {
|
|
1002
|
-
type = "string";
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
// For arrow functions, use a generic function type instead of the implementation
|
|
1006
|
-
// Don't store the implementation in value - it clutters documentation
|
|
1007
|
-
if (init.type === "ArrowFunctionExpression") {
|
|
1008
|
-
type = "(...args: any[]) => any";
|
|
1009
|
-
value = undefined;
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
else {
|
|
1013
|
-
if (init.type === "UnaryExpression") {
|
|
1014
|
-
value = this.sourceAtPos(init.start, init.end);
|
|
1015
|
-
type = typeof init.argument?.value;
|
|
1016
|
-
}
|
|
1017
|
-
else if (init.type === "Identifier") {
|
|
1018
|
-
// Handle non-literal defaults like variable references and global identifiers.
|
|
1019
|
-
// Don't infer type, just preserve existing type annotation.
|
|
1020
|
-
value = this.sourceAtPos(init.start, init.end);
|
|
1021
|
-
}
|
|
1022
|
-
else if (init.type === "MemberExpression") {
|
|
1023
|
-
// Handle member expressions like Number.POSITIVE_INFINITY, Math.PI, etc.
|
|
1024
|
-
value = this.sourceAtPos(init.start, init.end);
|
|
1025
|
-
// Infer type as "number" for well-known numeric constants
|
|
1026
|
-
if (this.isNumericConstant(init)) {
|
|
1027
|
-
type = "number";
|
|
1028
|
-
}
|
|
1029
|
-
// Otherwise, don't infer type, just preserve existing type annotation.
|
|
1030
|
-
}
|
|
1031
|
-
else if (init.type === "TemplateLiteral") {
|
|
1032
|
-
// Handle template literals - they always evaluate to strings
|
|
1033
|
-
value = this.sourceAtPos(init.start, init.end);
|
|
1034
|
-
type = "string";
|
|
1035
|
-
}
|
|
1036
|
-
else {
|
|
1037
|
-
value = init.raw;
|
|
1038
|
-
type = init.value == null ? undefined : typeof init.value;
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
984
|
+
const initResult = init != null ? this.processInitializer(init) : { isFunction: false };
|
|
985
|
+
let { value, type, isFunction } = initResult;
|
|
1042
986
|
if (declaration_type === "FunctionDeclaration") {
|
|
1043
|
-
// Don't store function body in value - it clutters documentation
|
|
1044
|
-
// The type signature is what matters for API docs
|
|
1045
987
|
value = undefined;
|
|
1046
988
|
type = "() => any";
|
|
1047
989
|
kind = "function";
|
|
@@ -1167,9 +1109,7 @@ class ComponentParser {
|
|
|
1167
1109
|
const existing_event = this.events.get(node.name);
|
|
1168
1110
|
// Check if this event has a JSDoc description
|
|
1169
1111
|
const description = this.eventDescriptions.get(node.name);
|
|
1170
|
-
const event_description = description
|
|
1171
|
-
? description.substring(description.lastIndexOf("-") + 1).trim()
|
|
1172
|
-
: undefined;
|
|
1112
|
+
const event_description = extractDescriptionAfterDash(description);
|
|
1173
1113
|
if (!existing_event) {
|
|
1174
1114
|
// Add new forwarded event
|
|
1175
1115
|
this.events.set(node.name, {
|
|
@@ -1239,9 +1179,7 @@ class ComponentParser {
|
|
|
1239
1179
|
// If event is marked as dispatched but is NOT actually dispatched, convert it to forwarded
|
|
1240
1180
|
if (event && event.type === "dispatched" && !actuallyDispatchedEvents.has(eventName)) {
|
|
1241
1181
|
const description = this.eventDescriptions.get(eventName);
|
|
1242
|
-
const event_description = description
|
|
1243
|
-
? description.substring(description.lastIndexOf("-") + 1).trim()
|
|
1244
|
-
: undefined;
|
|
1182
|
+
const event_description = extractDescriptionAfterDash(description);
|
|
1245
1183
|
const forwardedEvent = {
|
|
1246
1184
|
type: "forwarded",
|
|
1247
1185
|
name: eventName,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const MD_TYPE_UNDEFINED = "--";
|
|
2
|
+
export declare const PROP_TABLE_HEADER = "| Prop name | Required | Kind | Reactive | Type | Default value | Description |\n| :- | :- | :- | :- |\n";
|
|
3
|
+
export declare const SLOT_TABLE_HEADER = "| Slot name | Default | Props | Fallback |\n| :- | :- | :- | :- |\n";
|
|
4
|
+
export declare const EVENT_TABLE_HEADER = "| Event name | Type | Detail | Description |\n| :- | :- | :- | :- |\n";
|
|
5
|
+
export declare function formatPropType(type?: string): string;
|
|
6
|
+
export declare function escapeHtml(text: string): string;
|
|
7
|
+
export declare function formatPropValue(value: string | undefined): string;
|
|
8
|
+
export declare function formatPropDescription(description: string | undefined): string;
|
|
9
|
+
export declare function formatSlotProps(props?: string): string;
|
|
10
|
+
export declare function formatSlotFallback(fallback?: string): string;
|
|
11
|
+
export declare function formatEventDetail(detail?: string): string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EVENT_TABLE_HEADER = exports.SLOT_TABLE_HEADER = exports.PROP_TABLE_HEADER = exports.MD_TYPE_UNDEFINED = void 0;
|
|
4
|
+
exports.formatPropType = formatPropType;
|
|
5
|
+
exports.escapeHtml = escapeHtml;
|
|
6
|
+
exports.formatPropValue = formatPropValue;
|
|
7
|
+
exports.formatPropDescription = formatPropDescription;
|
|
8
|
+
exports.formatSlotProps = formatSlotProps;
|
|
9
|
+
exports.formatSlotFallback = formatSlotFallback;
|
|
10
|
+
exports.formatEventDetail = formatEventDetail;
|
|
11
|
+
const writer_ts_definitions_core_1 = require("./writer-ts-definitions-core");
|
|
12
|
+
exports.MD_TYPE_UNDEFINED = "--";
|
|
13
|
+
exports.PROP_TABLE_HEADER = "| Prop name | Required | Kind | Reactive | Type | Default value | Description |\n| :- | :- | :- | :- |\n";
|
|
14
|
+
exports.SLOT_TABLE_HEADER = "| Slot name | Default | Props | Fallback |\n| :- | :- | :- | :- |\n";
|
|
15
|
+
exports.EVENT_TABLE_HEADER = "| Event name | Type | Detail | Description |\n| :- | :- | :- | :- |\n";
|
|
16
|
+
const PIPE_REGEX = /\|/g;
|
|
17
|
+
const LT_REGEX = /</g;
|
|
18
|
+
const GT_REGEX = />/g;
|
|
19
|
+
const BACKTICK_REGEX = /`/g;
|
|
20
|
+
const NEWLINE_REGEX = /\n/g;
|
|
21
|
+
function formatPropType(type) {
|
|
22
|
+
if (type === undefined)
|
|
23
|
+
return exports.MD_TYPE_UNDEFINED;
|
|
24
|
+
return `<code>${type.replace(PIPE_REGEX, "|")}</code>`;
|
|
25
|
+
}
|
|
26
|
+
function escapeHtml(text) {
|
|
27
|
+
return text.replace(LT_REGEX, "<").replace(GT_REGEX, ">");
|
|
28
|
+
}
|
|
29
|
+
function formatPropValue(value) {
|
|
30
|
+
if (value === undefined)
|
|
31
|
+
return exports.MD_TYPE_UNDEFINED;
|
|
32
|
+
return `<code>${value.replace(BACKTICK_REGEX, "\\`").replace(PIPE_REGEX, "|")}</code>`;
|
|
33
|
+
}
|
|
34
|
+
function formatPropDescription(description) {
|
|
35
|
+
if (description === undefined || description.trim().length === 0)
|
|
36
|
+
return exports.MD_TYPE_UNDEFINED;
|
|
37
|
+
return escapeHtml(description).replace(NEWLINE_REGEX, "<br />");
|
|
38
|
+
}
|
|
39
|
+
function formatSlotProps(props) {
|
|
40
|
+
if (props === undefined || props === "{}")
|
|
41
|
+
return exports.MD_TYPE_UNDEFINED;
|
|
42
|
+
return formatPropType((0, writer_ts_definitions_core_1.formatTsProps)(props).replace(NEWLINE_REGEX, " "));
|
|
43
|
+
}
|
|
44
|
+
function formatSlotFallback(fallback) {
|
|
45
|
+
if (fallback === undefined)
|
|
46
|
+
return exports.MD_TYPE_UNDEFINED;
|
|
47
|
+
return formatPropType(escapeHtml(fallback).replace(NEWLINE_REGEX, "<br />"));
|
|
48
|
+
}
|
|
49
|
+
function formatEventDetail(detail) {
|
|
50
|
+
if (detail === undefined)
|
|
51
|
+
return exports.MD_TYPE_UNDEFINED;
|
|
52
|
+
return formatPropType(detail.replace(NEWLINE_REGEX, " "));
|
|
53
|
+
}
|
|
@@ -7,37 +7,25 @@ exports.default = writeJson;
|
|
|
7
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
8
|
const path_1 = require("../path");
|
|
9
9
|
const Writer_1 = __importDefault(require("./Writer"));
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
function transformAndSortComponents(components, inputDir) {
|
|
11
|
+
return Array.from(components, ([_moduleName, component]) => ({
|
|
12
12
|
...component,
|
|
13
|
-
filePath: (0, path_1.normalizeSeparators)(node_path_1.default.join(
|
|
14
|
-
})).sort((a, b) =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return 0;
|
|
20
|
-
});
|
|
21
|
-
output.map((c) => {
|
|
13
|
+
filePath: (0, path_1.normalizeSeparators)(node_path_1.default.join(inputDir, node_path_1.default.normalize(component.filePath))),
|
|
14
|
+
})).sort((a, b) => a.moduleName.localeCompare(b.moduleName));
|
|
15
|
+
}
|
|
16
|
+
async function writeJsonComponents(components, options) {
|
|
17
|
+
const output = transformAndSortComponents(components, options.inputDir);
|
|
18
|
+
await Promise.all(output.map((c) => {
|
|
22
19
|
const outFile = node_path_1.default.resolve(node_path_1.default.join(options.outDir || "", `${c.moduleName}.api.json`));
|
|
23
20
|
const writer = new Writer_1.default({ parser: "json", printWidth: 80 });
|
|
24
21
|
console.log(`created ${outFile}"\n`);
|
|
25
22
|
return writer.write(outFile, JSON.stringify(c));
|
|
26
|
-
});
|
|
23
|
+
}));
|
|
27
24
|
}
|
|
28
25
|
async function writeJsonLocal(components, options) {
|
|
29
26
|
const output = {
|
|
30
27
|
total: components.size,
|
|
31
|
-
components:
|
|
32
|
-
...component,
|
|
33
|
-
filePath: (0, path_1.normalizeSeparators)(node_path_1.default.join(options.inputDir, node_path_1.default.normalize(component.filePath))),
|
|
34
|
-
})).sort((a, b) => {
|
|
35
|
-
if (a.moduleName < b.moduleName)
|
|
36
|
-
return -1;
|
|
37
|
-
if (a.moduleName > b.moduleName)
|
|
38
|
-
return 1;
|
|
39
|
-
return 0;
|
|
40
|
-
}),
|
|
28
|
+
components: transformAndSortComponents(components, options.inputDir),
|
|
41
29
|
};
|
|
42
30
|
const output_path = node_path_1.default.join(process.cwd(), options.outFile);
|
|
43
31
|
const writer = new Writer_1.default({ parser: "json", printWidth: 80 });
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.BrowserWriterMarkdown = void 0;
|
|
4
4
|
exports.writeMarkdownCore = writeMarkdownCore;
|
|
5
|
+
const markdown_format_utils_1 = require("./markdown-format-utils");
|
|
5
6
|
const writer_ts_definitions_core_1 = require("./writer-ts-definitions-core");
|
|
6
7
|
const BACKTICK_REGEX = /`/g;
|
|
7
8
|
const WHITESPACE_REGEX = /\s+/g;
|
|
@@ -73,47 +74,6 @@ class BrowserWriterMarkdown {
|
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
exports.BrowserWriterMarkdown = BrowserWriterMarkdown;
|
|
76
|
-
const PROP_TABLE_HEADER = "| Prop name | Required | Kind | Reactive | Type | Default value | Description |\n| :- | :- | :- | :- |\n";
|
|
77
|
-
const SLOT_TABLE_HEADER = "| Slot name | Default | Props | Fallback |\n| :- | :- | :- | :- |\n";
|
|
78
|
-
const EVENT_TABLE_HEADER = "| Event name | Type | Detail | Description |\n| :- | :- | :- | :- |\n";
|
|
79
|
-
const MD_TYPE_UNDEFINED = "--";
|
|
80
|
-
const PIPE_REGEX = /\|/g;
|
|
81
|
-
const LT_REGEX = /</g;
|
|
82
|
-
const GT_REGEX = />/g;
|
|
83
|
-
const NEWLINE_REGEX = /\n/g;
|
|
84
|
-
function formatPropType(type) {
|
|
85
|
-
if (type === undefined)
|
|
86
|
-
return MD_TYPE_UNDEFINED;
|
|
87
|
-
return `<code>${type.replace(PIPE_REGEX, "|")}</code>`;
|
|
88
|
-
}
|
|
89
|
-
function escapeHtml(text) {
|
|
90
|
-
return text.replace(LT_REGEX, "<").replace(GT_REGEX, ">");
|
|
91
|
-
}
|
|
92
|
-
function formatPropValue(value) {
|
|
93
|
-
if (value === undefined)
|
|
94
|
-
return MD_TYPE_UNDEFINED;
|
|
95
|
-
return `<code>${value.replace(BACKTICK_REGEX, "\\`").replace(PIPE_REGEX, "|")}</code>`;
|
|
96
|
-
}
|
|
97
|
-
function formatPropDescription(description) {
|
|
98
|
-
if (description === undefined || description.trim().length === 0)
|
|
99
|
-
return MD_TYPE_UNDEFINED;
|
|
100
|
-
return escapeHtml(description).replace(NEWLINE_REGEX, "<br />");
|
|
101
|
-
}
|
|
102
|
-
function formatSlotProps(props) {
|
|
103
|
-
if (props === undefined || props === "{}")
|
|
104
|
-
return MD_TYPE_UNDEFINED;
|
|
105
|
-
return formatPropType((0, writer_ts_definitions_core_1.formatTsProps)(props).replace(NEWLINE_REGEX, " "));
|
|
106
|
-
}
|
|
107
|
-
function formatSlotFallback(fallback) {
|
|
108
|
-
if (fallback === undefined)
|
|
109
|
-
return MD_TYPE_UNDEFINED;
|
|
110
|
-
return formatPropType(escapeHtml(fallback).replace(NEWLINE_REGEX, "<br />"));
|
|
111
|
-
}
|
|
112
|
-
function formatEventDetail(detail) {
|
|
113
|
-
if (detail === undefined)
|
|
114
|
-
return MD_TYPE_UNDEFINED;
|
|
115
|
-
return formatPropType(detail.replace(NEWLINE_REGEX, " "));
|
|
116
|
-
}
|
|
117
77
|
function writeMarkdownCore(components, options) {
|
|
118
78
|
const document = new BrowserWriterMarkdown({
|
|
119
79
|
onAppend: (type, document) => {
|
|
@@ -136,7 +96,7 @@ function writeMarkdownCore(components, options) {
|
|
|
136
96
|
}
|
|
137
97
|
document.append("h3", "Props");
|
|
138
98
|
if (component.props.length > 0) {
|
|
139
|
-
document.append("raw", PROP_TABLE_HEADER);
|
|
99
|
+
document.append("raw", markdown_format_utils_1.PROP_TABLE_HEADER);
|
|
140
100
|
const sortedProps = [...component.props].sort((a) => {
|
|
141
101
|
if (a.reactive)
|
|
142
102
|
return -1;
|
|
@@ -145,7 +105,7 @@ function writeMarkdownCore(components, options) {
|
|
|
145
105
|
return 0;
|
|
146
106
|
});
|
|
147
107
|
for (const prop of sortedProps) {
|
|
148
|
-
document.append("raw", `| ${prop.name} | ${prop.isRequired ? "Yes" : "No"} | ${`<code>${prop.kind}</code>`} | ${prop.reactive ? "Yes" : "No"} | ${formatPropType(prop.type)} | ${formatPropValue(prop.value)} | ${formatPropDescription(prop.description)} |\n`);
|
|
108
|
+
document.append("raw", `| ${prop.name} | ${prop.isRequired ? "Yes" : "No"} | ${`<code>${prop.kind}</code>`} | ${prop.reactive ? "Yes" : "No"} | ${(0, markdown_format_utils_1.formatPropType)(prop.type)} | ${(0, markdown_format_utils_1.formatPropValue)(prop.value)} | ${(0, markdown_format_utils_1.formatPropDescription)(prop.description)} |\n`);
|
|
149
109
|
}
|
|
150
110
|
}
|
|
151
111
|
else {
|
|
@@ -153,9 +113,9 @@ function writeMarkdownCore(components, options) {
|
|
|
153
113
|
}
|
|
154
114
|
document.append("h3", "Slots");
|
|
155
115
|
if (component.slots.length > 0) {
|
|
156
|
-
document.append("raw", SLOT_TABLE_HEADER);
|
|
116
|
+
document.append("raw", markdown_format_utils_1.SLOT_TABLE_HEADER);
|
|
157
117
|
for (const slot of component.slots) {
|
|
158
|
-
document.append("raw", `| ${slot.default ? MD_TYPE_UNDEFINED : slot.name} | ${slot.default ? "Yes" : "No"} | ${formatSlotProps(slot.slot_props)} | ${formatSlotFallback(slot.fallback)} |\n`);
|
|
118
|
+
document.append("raw", `| ${slot.default ? markdown_format_utils_1.MD_TYPE_UNDEFINED : slot.name} | ${slot.default ? "Yes" : "No"} | ${(0, markdown_format_utils_1.formatSlotProps)(slot.slot_props)} | ${(0, markdown_format_utils_1.formatSlotFallback)(slot.fallback)} |\n`);
|
|
159
119
|
}
|
|
160
120
|
}
|
|
161
121
|
else {
|
|
@@ -163,9 +123,9 @@ function writeMarkdownCore(components, options) {
|
|
|
163
123
|
}
|
|
164
124
|
document.append("h3", "Events");
|
|
165
125
|
if (component.events.length > 0) {
|
|
166
|
-
document.append("raw", EVENT_TABLE_HEADER);
|
|
126
|
+
document.append("raw", markdown_format_utils_1.EVENT_TABLE_HEADER);
|
|
167
127
|
for (const event of component.events) {
|
|
168
|
-
document.append("raw", `| ${event.name} | ${event.type} | ${event.type === "dispatched" ? formatEventDetail(event.detail) : MD_TYPE_UNDEFINED} | ${formatPropDescription(event.description)} |\n`);
|
|
128
|
+
document.append("raw", `| ${event.name} | ${event.type} | ${event.type === "dispatched" ? (0, markdown_format_utils_1.formatEventDetail)(event.detail) : markdown_format_utils_1.MD_TYPE_UNDEFINED} | ${(0, markdown_format_utils_1.formatPropDescription)(event.description)} |\n`);
|
|
169
129
|
}
|
|
170
130
|
}
|
|
171
131
|
else {
|
|
@@ -5,50 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.default = writeMarkdown;
|
|
7
7
|
const node_path_1 = require("node:path");
|
|
8
|
+
const markdown_format_utils_1 = require("./markdown-format-utils");
|
|
8
9
|
const WriterMarkdown_1 = __importDefault(require("./WriterMarkdown"));
|
|
9
10
|
const writer_ts_definitions_core_1 = require("./writer-ts-definitions-core");
|
|
10
|
-
const PROP_TABLE_HEADER = "| Prop name | Required | Kind | Reactive | Type | Default value | Description |\n| :- | :- | :- | :- |\n";
|
|
11
|
-
const SLOT_TABLE_HEADER = "| Slot name | Default | Props | Fallback |\n| :- | :- | :- | :- |\n";
|
|
12
|
-
const EVENT_TABLE_HEADER = "| Event name | Type | Detail | Description |\n| :- | :- | :- | :- |\n";
|
|
13
|
-
const MD_TYPE_UNDEFINED = "--";
|
|
14
|
-
const PIPE_REGEX = /\|/g;
|
|
15
|
-
const LT_REGEX = /</g;
|
|
16
|
-
const GT_REGEX = />/g;
|
|
17
|
-
const BACKTICK_REGEX = /`/g;
|
|
18
|
-
const NEWLINE_REGEX = /\n/g;
|
|
19
|
-
function formatPropType(type) {
|
|
20
|
-
if (type === undefined)
|
|
21
|
-
return MD_TYPE_UNDEFINED;
|
|
22
|
-
return `<code>${type.replace(PIPE_REGEX, "|")}</code>`;
|
|
23
|
-
}
|
|
24
|
-
function escapeHtml(text) {
|
|
25
|
-
return text.replace(LT_REGEX, "<").replace(GT_REGEX, ">");
|
|
26
|
-
}
|
|
27
|
-
function formatPropValue(value) {
|
|
28
|
-
if (value === undefined)
|
|
29
|
-
return MD_TYPE_UNDEFINED;
|
|
30
|
-
return `<code>${value.replace(BACKTICK_REGEX, "\\`").replace(PIPE_REGEX, "|")}</code>`;
|
|
31
|
-
}
|
|
32
|
-
function formatPropDescription(description) {
|
|
33
|
-
if (description === undefined || description.trim().length === 0)
|
|
34
|
-
return MD_TYPE_UNDEFINED;
|
|
35
|
-
return escapeHtml(description).replace(NEWLINE_REGEX, "<br />");
|
|
36
|
-
}
|
|
37
|
-
function formatSlotProps(props) {
|
|
38
|
-
if (props === undefined || props === "{}")
|
|
39
|
-
return MD_TYPE_UNDEFINED;
|
|
40
|
-
return formatPropType((0, writer_ts_definitions_core_1.formatTsProps)(props).replace(NEWLINE_REGEX, " "));
|
|
41
|
-
}
|
|
42
|
-
function formatSlotFallback(fallback) {
|
|
43
|
-
if (fallback === undefined)
|
|
44
|
-
return MD_TYPE_UNDEFINED;
|
|
45
|
-
return formatPropType(escapeHtml(fallback).replace(NEWLINE_REGEX, "<br />"));
|
|
46
|
-
}
|
|
47
|
-
function formatEventDetail(detail) {
|
|
48
|
-
if (detail === undefined)
|
|
49
|
-
return MD_TYPE_UNDEFINED;
|
|
50
|
-
return formatPropType(detail.replace(NEWLINE_REGEX, " "));
|
|
51
|
-
}
|
|
52
11
|
async function writeMarkdown(components, options) {
|
|
53
12
|
const write = options?.write !== false;
|
|
54
13
|
const document = new WriterMarkdown_1.default({
|
|
@@ -72,7 +31,7 @@ async function writeMarkdown(components, options) {
|
|
|
72
31
|
}
|
|
73
32
|
document.append("h3", "Props");
|
|
74
33
|
if (component.props.length > 0) {
|
|
75
|
-
document.append("raw", PROP_TABLE_HEADER);
|
|
34
|
+
document.append("raw", markdown_format_utils_1.PROP_TABLE_HEADER);
|
|
76
35
|
const sortedProps = [...component.props].sort((a) => {
|
|
77
36
|
if (a.reactive)
|
|
78
37
|
return -1;
|
|
@@ -81,7 +40,7 @@ async function writeMarkdown(components, options) {
|
|
|
81
40
|
return 0;
|
|
82
41
|
});
|
|
83
42
|
for (const prop of sortedProps) {
|
|
84
|
-
document.append("raw", `| ${prop.name} | ${prop.isRequired ? "Yes" : "No"} | ${`<code>${prop.kind}</code>`} | ${prop.reactive ? "Yes" : "No"} | ${formatPropType(prop.type)} | ${formatPropValue(prop.value)} | ${formatPropDescription(prop.description)} |\n`);
|
|
43
|
+
document.append("raw", `| ${prop.name} | ${prop.isRequired ? "Yes" : "No"} | ${`<code>${prop.kind}</code>`} | ${prop.reactive ? "Yes" : "No"} | ${(0, markdown_format_utils_1.formatPropType)(prop.type)} | ${(0, markdown_format_utils_1.formatPropValue)(prop.value)} | ${(0, markdown_format_utils_1.formatPropDescription)(prop.description)} |\n`);
|
|
85
44
|
}
|
|
86
45
|
}
|
|
87
46
|
else {
|
|
@@ -89,9 +48,9 @@ async function writeMarkdown(components, options) {
|
|
|
89
48
|
}
|
|
90
49
|
document.append("h3", "Slots");
|
|
91
50
|
if (component.slots.length > 0) {
|
|
92
|
-
document.append("raw", SLOT_TABLE_HEADER);
|
|
51
|
+
document.append("raw", markdown_format_utils_1.SLOT_TABLE_HEADER);
|
|
93
52
|
for (const slot of component.slots) {
|
|
94
|
-
document.append("raw", `| ${slot.default ? MD_TYPE_UNDEFINED : slot.name} | ${slot.default ? "Yes" : "No"} | ${formatSlotProps(slot.slot_props)} | ${formatSlotFallback(slot.fallback)} |\n`);
|
|
53
|
+
document.append("raw", `| ${slot.default ? markdown_format_utils_1.MD_TYPE_UNDEFINED : slot.name} | ${slot.default ? "Yes" : "No"} | ${(0, markdown_format_utils_1.formatSlotProps)(slot.slot_props)} | ${(0, markdown_format_utils_1.formatSlotFallback)(slot.fallback)} |\n`);
|
|
95
54
|
}
|
|
96
55
|
}
|
|
97
56
|
else {
|
|
@@ -99,9 +58,9 @@ async function writeMarkdown(components, options) {
|
|
|
99
58
|
}
|
|
100
59
|
document.append("h3", "Events");
|
|
101
60
|
if (component.events.length > 0) {
|
|
102
|
-
document.append("raw", EVENT_TABLE_HEADER);
|
|
61
|
+
document.append("raw", markdown_format_utils_1.EVENT_TABLE_HEADER);
|
|
103
62
|
for (const event of component.events) {
|
|
104
|
-
document.append("raw", `| ${event.name} | ${event.type} | ${event.type === "dispatched" ? formatEventDetail(event.detail) : MD_TYPE_UNDEFINED} | ${formatPropDescription(event.description)} |\n`);
|
|
63
|
+
document.append("raw", `| ${event.name} | ${event.type} | ${event.type === "dispatched" ? (0, markdown_format_utils_1.formatEventDetail)(event.detail) : markdown_format_utils_1.MD_TYPE_UNDEFINED} | ${(0, markdown_format_utils_1.formatPropDescription)(event.description)} |\n`);
|
|
105
64
|
}
|
|
106
65
|
}
|
|
107
66
|
else {
|
|
@@ -133,7 +133,10 @@ function genPropDef(def) {
|
|
|
133
133
|
const props = [...initial_props, ...snippet_props].join("\n");
|
|
134
134
|
const props_name = `${def.moduleName}Props`;
|
|
135
135
|
let prop_def = EMPTY_STR;
|
|
136
|
-
|
|
136
|
+
// Full constraints for type definitions (e.g., `type $Props<T extends Foo = Bar>`)
|
|
137
|
+
const genericsName = def.generics ? `<${def.generics[1]}>` : "";
|
|
138
|
+
// Names only for type references (e.g., `keyof $Props<T>`)
|
|
139
|
+
const genericsNameRef = def.generics ? `<${def.generics[0]}>` : "";
|
|
137
140
|
if (def.rest_props?.type === "Element") {
|
|
138
141
|
let extend_tag_map;
|
|
139
142
|
// Handle svelte:element specially
|
|
@@ -176,7 +179,7 @@ function genPropDef(def) {
|
|
|
176
179
|
${dataAttributes}
|
|
177
180
|
};
|
|
178
181
|
|
|
179
|
-
export type ${props_name}${genericsName} = Omit<$RestProps, keyof ($Props${
|
|
182
|
+
export type ${props_name}${genericsName} = Omit<$RestProps, keyof ($Props${genericsNameRef} & ${def.extends.interface})> & $Props${genericsNameRef} & ${def.extends.interface};
|
|
180
183
|
`;
|
|
181
184
|
}
|
|
182
185
|
else {
|
|
@@ -188,7 +191,7 @@ function genPropDef(def) {
|
|
|
188
191
|
${dataAttributes}
|
|
189
192
|
};
|
|
190
193
|
|
|
191
|
-
export type ${props_name}${genericsName} = Omit<$RestProps, keyof $Props${
|
|
194
|
+
export type ${props_name}${genericsName} = Omit<$RestProps, keyof $Props${genericsNameRef}> & $Props${genericsNameRef};
|
|
192
195
|
`;
|
|
193
196
|
}
|
|
194
197
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sveld",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.10",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Generate TypeScript definitions for your Svelte components.",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"@rollup/plugin-node-resolve": "^13.3.0",
|
|
10
10
|
"acorn": "^8.14.1",
|
|
11
11
|
"comment-parser": "^1.4.1",
|
|
12
|
-
"prettier": "^3.
|
|
12
|
+
"prettier": "^3.8.0",
|
|
13
13
|
"rollup": "^2.79.2",
|
|
14
14
|
"rollup-plugin-svelte": "^7.2.2",
|
|
15
15
|
"svelte": "^4.2.20",
|