sveld 0.25.1 → 0.25.2
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 +4 -0
- package/lib/ComponentParser.js +160 -106
- package/lib/resolve-alias.js +11 -6
- package/lib/rollup-plugin.js +36 -27
- package/lib/writer/WriterMarkdown.d.ts +2 -1
- package/lib/writer/WriterMarkdown.js +13 -12
- package/lib/writer/writer-markdown-core.d.ts +2 -1
- package/lib/writer/writer-markdown-core.js +13 -12
- package/package.json +1 -1
package/lib/ComponentParser.d.ts
CHANGED
|
@@ -112,10 +112,12 @@ export default class ComponentParser {
|
|
|
112
112
|
private readonly bindings;
|
|
113
113
|
private readonly contexts;
|
|
114
114
|
private variableInfoCache;
|
|
115
|
+
private sourceLinesCache?;
|
|
115
116
|
constructor(options?: ComponentParserOptions);
|
|
116
117
|
private static mapToArray;
|
|
117
118
|
private static assignValue;
|
|
118
119
|
private static formatComment;
|
|
120
|
+
private getCommentTags;
|
|
119
121
|
/**
|
|
120
122
|
* Finds the last comment from an array of leading comments.
|
|
121
123
|
* TypeScript directives are stripped before parsing, so we can safely take the last comment.
|
|
@@ -137,6 +139,8 @@ export default class ComponentParser {
|
|
|
137
139
|
private buildEventDetailFromProperties;
|
|
138
140
|
private generateContextTypeName;
|
|
139
141
|
private buildVariableInfoCache;
|
|
142
|
+
private static readonly VAR_NAME_REGEX_CACHE;
|
|
143
|
+
private static getVarNameRegexes;
|
|
140
144
|
private findVariableTypeAndDescription;
|
|
141
145
|
private parseContextValue;
|
|
142
146
|
private parseSetContextCall;
|
package/lib/ComponentParser.js
CHANGED
|
@@ -35,6 +35,7 @@ class ComponentParser {
|
|
|
35
35
|
bindings = new Map();
|
|
36
36
|
contexts = new Map();
|
|
37
37
|
variableInfoCache = new Map();
|
|
38
|
+
sourceLinesCache;
|
|
38
39
|
constructor(options) {
|
|
39
40
|
this.options = options;
|
|
40
41
|
}
|
|
@@ -54,6 +55,45 @@ class ComponentParser {
|
|
|
54
55
|
}
|
|
55
56
|
return formatted_comment;
|
|
56
57
|
}
|
|
58
|
+
getCommentTags(parsed) {
|
|
59
|
+
const tags = parsed[0]?.tags ?? [];
|
|
60
|
+
const excludedTags = new Set([
|
|
61
|
+
"type",
|
|
62
|
+
"param",
|
|
63
|
+
"returns",
|
|
64
|
+
"return",
|
|
65
|
+
"extends",
|
|
66
|
+
"restProps",
|
|
67
|
+
"slot",
|
|
68
|
+
"event",
|
|
69
|
+
"typedef",
|
|
70
|
+
]);
|
|
71
|
+
let typeTag;
|
|
72
|
+
const paramTags = [];
|
|
73
|
+
let returnsTag;
|
|
74
|
+
const additionalTags = [];
|
|
75
|
+
for (const tag of tags) {
|
|
76
|
+
if (tag.tag === "type") {
|
|
77
|
+
typeTag = tag;
|
|
78
|
+
}
|
|
79
|
+
else if (tag.tag === "param") {
|
|
80
|
+
paramTags.push(tag);
|
|
81
|
+
}
|
|
82
|
+
else if (tag.tag === "returns" || tag.tag === "return") {
|
|
83
|
+
returnsTag = tag;
|
|
84
|
+
}
|
|
85
|
+
else if (!excludedTags.has(tag.tag)) {
|
|
86
|
+
additionalTags.push(tag);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
type: typeTag,
|
|
91
|
+
param: paramTags,
|
|
92
|
+
returns: returnsTag,
|
|
93
|
+
additional: additionalTags,
|
|
94
|
+
description: parsed[0]?.description,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
57
97
|
/**
|
|
58
98
|
* Finds the last comment from an array of leading comments.
|
|
59
99
|
* TypeScript directives are stripped before parsing, so we can safely take the last comment.
|
|
@@ -138,7 +178,9 @@ class ComponentParser {
|
|
|
138
178
|
const name = default_slot ? DEFAULT_SLOT_NAME : (slot_name ?? "");
|
|
139
179
|
const fallback = ComponentParser.assignValue(slot_fallback);
|
|
140
180
|
const props = ComponentParser.assignValue(slot_props);
|
|
141
|
-
const description = slot_description
|
|
181
|
+
const description = slot_description
|
|
182
|
+
? slot_description.substring(slot_description.lastIndexOf("-") + 1).trim()
|
|
183
|
+
: undefined;
|
|
142
184
|
if (this.slots.has(name)) {
|
|
143
185
|
const existing_slot = this.slots.get(name);
|
|
144
186
|
this.slots.set(name, {
|
|
@@ -167,7 +209,7 @@ class ComponentParser {
|
|
|
167
209
|
* `@event` is not specified.
|
|
168
210
|
*/
|
|
169
211
|
const default_detail = !has_argument && !detail ? "null" : ComponentParser.assignValue(detail);
|
|
170
|
-
const event_description = description
|
|
212
|
+
const event_description = description ? description.substring(description.lastIndexOf("-") + 1).trim() : undefined;
|
|
171
213
|
if (this.events.has(name)) {
|
|
172
214
|
const existing_event = this.events.get(name);
|
|
173
215
|
this.events.set(name, {
|
|
@@ -453,7 +495,10 @@ class ComponentParser {
|
|
|
453
495
|
buildVariableInfoCache() {
|
|
454
496
|
if (!this.source)
|
|
455
497
|
return;
|
|
456
|
-
|
|
498
|
+
if (!this.sourceLinesCache) {
|
|
499
|
+
this.sourceLinesCache = this.source.split("\n");
|
|
500
|
+
}
|
|
501
|
+
const lines = this.sourceLinesCache;
|
|
457
502
|
for (let i = 0; i < lines.length; i++) {
|
|
458
503
|
const line = lines[i].trim();
|
|
459
504
|
// Match variable declarations
|
|
@@ -477,14 +522,12 @@ class ComponentParser {
|
|
|
477
522
|
const commentBlock = commentLines.join("\n");
|
|
478
523
|
// Parse the JSDoc
|
|
479
524
|
const parsed = (0, comment_parser_1.parse)(commentBlock, { spacing: "preserve" });
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
this.
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
});
|
|
487
|
-
}
|
|
525
|
+
const { type: typeTag, description } = this.getCommentTags(parsed);
|
|
526
|
+
if (typeTag) {
|
|
527
|
+
this.variableInfoCache.set(varName, {
|
|
528
|
+
type: this.aliasType(typeTag.type),
|
|
529
|
+
description: description || typeTag.description,
|
|
530
|
+
});
|
|
488
531
|
}
|
|
489
532
|
break;
|
|
490
533
|
}
|
|
@@ -492,6 +535,20 @@ class ComponentParser {
|
|
|
492
535
|
}
|
|
493
536
|
}
|
|
494
537
|
}
|
|
538
|
+
static VAR_NAME_REGEX_CACHE = new Map();
|
|
539
|
+
static getVarNameRegexes(varName) {
|
|
540
|
+
let cached = ComponentParser.VAR_NAME_REGEX_CACHE.get(varName);
|
|
541
|
+
if (!cached) {
|
|
542
|
+
const escaped = varName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
543
|
+
cached = [
|
|
544
|
+
new RegExp(`const\\s+${escaped}\\s*=`),
|
|
545
|
+
new RegExp(`let\\s+${escaped}\\s*=`),
|
|
546
|
+
new RegExp(`function\\s+${escaped}\\s*\\(`),
|
|
547
|
+
];
|
|
548
|
+
ComponentParser.VAR_NAME_REGEX_CACHE.set(varName, cached);
|
|
549
|
+
}
|
|
550
|
+
return cached;
|
|
551
|
+
}
|
|
495
552
|
findVariableTypeAndDescription(varName) {
|
|
496
553
|
const cached = this.variableInfoCache.get(varName);
|
|
497
554
|
if (cached) {
|
|
@@ -500,15 +557,18 @@ class ComponentParser {
|
|
|
500
557
|
// Search through the source code directly for JSDoc comments
|
|
501
558
|
if (!this.source)
|
|
502
559
|
return null;
|
|
503
|
-
|
|
504
|
-
|
|
560
|
+
if (!this.sourceLinesCache) {
|
|
561
|
+
this.sourceLinesCache = this.source.split("\n");
|
|
562
|
+
}
|
|
563
|
+
const lines = this.sourceLinesCache;
|
|
564
|
+
const [constRegex, letRegex, funcRegex] = ComponentParser.getVarNameRegexes(varName);
|
|
505
565
|
for (let i = 0; i < lines.length; i++) {
|
|
506
566
|
const line = lines[i].trim();
|
|
507
567
|
// Check if this line declares our variable
|
|
508
568
|
// Match patterns like: const varName = ..., let varName = ..., function varName
|
|
509
|
-
const constMatch = line.match(
|
|
510
|
-
const letMatch = line.match(
|
|
511
|
-
const funcMatch = line.match(
|
|
569
|
+
const constMatch = line.match(constRegex);
|
|
570
|
+
const letMatch = line.match(letRegex);
|
|
571
|
+
const funcMatch = line.match(funcRegex);
|
|
512
572
|
if (constMatch || letMatch || funcMatch) {
|
|
513
573
|
// Look backwards for JSDoc comment
|
|
514
574
|
for (let j = i - 1; j >= 0; j--) {
|
|
@@ -527,14 +587,12 @@ class ComponentParser {
|
|
|
527
587
|
const commentBlock = commentLines.join("\n");
|
|
528
588
|
// Parse the JSDoc
|
|
529
589
|
const parsed = (0, comment_parser_1.parse)(commentBlock, { spacing: "preserve" });
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
};
|
|
537
|
-
}
|
|
590
|
+
const { type: typeTag, description } = this.getCommentTags(parsed);
|
|
591
|
+
if (typeTag) {
|
|
592
|
+
return {
|
|
593
|
+
type: this.aliasType(typeTag.type),
|
|
594
|
+
description: description || typeTag.description,
|
|
595
|
+
};
|
|
538
596
|
}
|
|
539
597
|
break;
|
|
540
598
|
}
|
|
@@ -685,6 +743,7 @@ class ComponentParser {
|
|
|
685
743
|
this.bindings.clear();
|
|
686
744
|
this.contexts.clear();
|
|
687
745
|
this.variableInfoCache.clear();
|
|
746
|
+
this.sourceLinesCache = undefined;
|
|
688
747
|
}
|
|
689
748
|
// Pre-compiled regexes for better performance
|
|
690
749
|
static SCRIPT_BLOCK_REGEX = /(<script[^>]*>)([\s\S]*?)(<\/script>)/gi;
|
|
@@ -718,6 +777,7 @@ class ComponentParser {
|
|
|
718
777
|
// The compile result includes the parsed AST
|
|
719
778
|
this.parsed = compiled.ast || (0, compiler_1.parse)(cleanedSource);
|
|
720
779
|
this.collectReactiveVars();
|
|
780
|
+
this.sourceLinesCache = this.source.split("\n");
|
|
721
781
|
this.buildVariableInfoCache();
|
|
722
782
|
this.parseCustomTypes();
|
|
723
783
|
if (this.parsed?.module) {
|
|
@@ -798,12 +858,11 @@ class ComponentParser {
|
|
|
798
858
|
const comment = (0, comment_parser_1.parse)(ComponentParser.formatComment(jsdoc_comment.value), {
|
|
799
859
|
spacing: "preserve",
|
|
800
860
|
});
|
|
861
|
+
const { type: typeTag, param: paramTags, returns: returnsTag, additional: additionalTags, description: commentDescription, } = this.getCommentTags(comment);
|
|
801
862
|
// Extract @type tag
|
|
802
|
-
const typeTag = comment[0]?.tags.find((t) => t.tag === "type");
|
|
803
863
|
if (typeTag)
|
|
804
864
|
type = this.aliasType(typeTag.type);
|
|
805
865
|
// Extract @param tags
|
|
806
|
-
const paramTags = comment[0]?.tags.filter((t) => t.tag === "param") ?? [];
|
|
807
866
|
if (paramTags.length > 0) {
|
|
808
867
|
params = paramTags
|
|
809
868
|
.filter((tag) => !tag.name.includes(".")) // Exclude nested params like "options.expand"
|
|
@@ -815,27 +874,20 @@ class ComponentParser {
|
|
|
815
874
|
}));
|
|
816
875
|
}
|
|
817
876
|
// Extract @returns/@return tag
|
|
818
|
-
const returnsTag = comment[0]?.tags.find((t) => t.tag === "returns" || t.tag === "return");
|
|
819
877
|
if (returnsTag)
|
|
820
878
|
returnType = this.aliasType(returnsTag.type);
|
|
821
879
|
// Build description from comment description and non-param/non-type tags
|
|
822
|
-
const
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
"extends",
|
|
829
|
-
"restProps",
|
|
830
|
-
"slot",
|
|
831
|
-
"event",
|
|
832
|
-
"typedef",
|
|
833
|
-
].includes(tag.tag)) ?? [];
|
|
834
|
-
if (commentDescription || additionalTags.length > 0) {
|
|
835
|
-
description = commentDescription || "";
|
|
880
|
+
const formattedDescription = ComponentParser.assignValue(commentDescription?.trim());
|
|
881
|
+
if (formattedDescription || additionalTags.length > 0) {
|
|
882
|
+
const descriptionParts = [];
|
|
883
|
+
if (formattedDescription) {
|
|
884
|
+
descriptionParts.push(formattedDescription);
|
|
885
|
+
}
|
|
836
886
|
for (const tag of additionalTags) {
|
|
837
|
-
|
|
887
|
+
const tagStr = `@${tag.tag}${tag.name ? ` ${tag.name}` : ""}${tag.description ? ` ${tag.description}` : ""}`;
|
|
888
|
+
descriptionParts.push(tagStr);
|
|
838
889
|
}
|
|
890
|
+
description = descriptionParts.join("\n");
|
|
839
891
|
}
|
|
840
892
|
}
|
|
841
893
|
}
|
|
@@ -994,12 +1046,11 @@ class ComponentParser {
|
|
|
994
1046
|
const comment = (0, comment_parser_1.parse)(ComponentParser.formatComment(jsdoc_comment.value), {
|
|
995
1047
|
spacing: "preserve",
|
|
996
1048
|
});
|
|
1049
|
+
const { type: typeTag, param: paramTags, returns: returnsTag, additional: additional_tags, description: commentDescription, } = this.getCommentTags(comment);
|
|
997
1050
|
// Extract @type tag
|
|
998
|
-
const typeTag = comment[0]?.tags.find((t) => t.tag === "type");
|
|
999
1051
|
if (typeTag)
|
|
1000
1052
|
type = this.aliasType(typeTag.type);
|
|
1001
1053
|
// Extract @param tags
|
|
1002
|
-
const paramTags = comment[0]?.tags.filter((t) => t.tag === "param") ?? [];
|
|
1003
1054
|
if (paramTags.length > 0) {
|
|
1004
1055
|
params = paramTags
|
|
1005
1056
|
.filter((tag) => !tag.name.includes(".")) // Exclude nested params like "options.expand"
|
|
@@ -1011,27 +1062,20 @@ class ComponentParser {
|
|
|
1011
1062
|
}));
|
|
1012
1063
|
}
|
|
1013
1064
|
// Extract @returns/@return tag
|
|
1014
|
-
const returnsTag = comment[0]?.tags.find((t) => t.tag === "returns" || t.tag === "return");
|
|
1015
1065
|
if (returnsTag)
|
|
1016
1066
|
returnType = this.aliasType(returnsTag.type);
|
|
1017
1067
|
// Build description from comment description and non-param/non-type tags
|
|
1018
|
-
const
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
"extends",
|
|
1025
|
-
"restProps",
|
|
1026
|
-
"slot",
|
|
1027
|
-
"event",
|
|
1028
|
-
"typedef",
|
|
1029
|
-
].includes(tag.tag)) ?? [];
|
|
1030
|
-
if (commentDescription || additional_tags.length > 0) {
|
|
1031
|
-
description = commentDescription || "";
|
|
1068
|
+
const formattedDescription = ComponentParser.assignValue(commentDescription?.trim());
|
|
1069
|
+
if (formattedDescription || additional_tags.length > 0) {
|
|
1070
|
+
const descriptionParts = [];
|
|
1071
|
+
if (formattedDescription) {
|
|
1072
|
+
descriptionParts.push(formattedDescription);
|
|
1073
|
+
}
|
|
1032
1074
|
for (const tag of additional_tags) {
|
|
1033
|
-
|
|
1075
|
+
const tagStr = `@${tag.tag}${tag.name ? ` ${tag.name}` : ""}${tag.description ? ` ${tag.description}` : ""}`;
|
|
1076
|
+
descriptionParts.push(tagStr);
|
|
1034
1077
|
}
|
|
1078
|
+
description = descriptionParts.join("\n");
|
|
1035
1079
|
}
|
|
1036
1080
|
}
|
|
1037
1081
|
}
|
|
@@ -1113,7 +1157,9 @@ class ComponentParser {
|
|
|
1113
1157
|
const existing_event = this.events.get(node.name);
|
|
1114
1158
|
// Check if this event has a JSDoc description
|
|
1115
1159
|
const description = this.eventDescriptions.get(node.name);
|
|
1116
|
-
const event_description = description
|
|
1160
|
+
const event_description = description
|
|
1161
|
+
? description.substring(description.lastIndexOf("-") + 1).trim()
|
|
1162
|
+
: undefined;
|
|
1117
1163
|
if (!existing_event) {
|
|
1118
1164
|
// Add new forwarded event
|
|
1119
1165
|
this.events.set(node.name, {
|
|
@@ -1183,7 +1229,9 @@ class ComponentParser {
|
|
|
1183
1229
|
// If event is marked as dispatched but is NOT actually dispatched, convert it to forwarded
|
|
1184
1230
|
if (event && event.type === "dispatched" && !actuallyDispatchedEvents.has(eventName)) {
|
|
1185
1231
|
const description = this.eventDescriptions.get(eventName);
|
|
1186
|
-
const event_description = description
|
|
1232
|
+
const event_description = description
|
|
1233
|
+
? description.substring(description.lastIndexOf("-") + 1).trim()
|
|
1234
|
+
: undefined;
|
|
1187
1235
|
const forwardedEvent = {
|
|
1188
1236
|
type: "forwarded",
|
|
1189
1237
|
name: eventName,
|
|
@@ -1199,56 +1247,62 @@ class ComponentParser {
|
|
|
1199
1247
|
this.events.set(eventName, forwardedEvent);
|
|
1200
1248
|
}
|
|
1201
1249
|
});
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
.
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
if (slot_props[key].replace && slot_props[key].value !== undefined) {
|
|
1225
|
-
slot_props[key].value = this.props.get(slot_props[key].value)?.type;
|
|
1226
|
-
}
|
|
1227
|
-
if (slot_props[key].value === undefined)
|
|
1228
|
-
slot_props[key].value = "any";
|
|
1229
|
-
new_props.push(`${key}: ${slot_props[key].value}`);
|
|
1250
|
+
const processedProps = ComponentParser.mapToArray(this.props).map((prop) => {
|
|
1251
|
+
if (this.bindings.has(prop.name)) {
|
|
1252
|
+
const elementTypes = this.bindings
|
|
1253
|
+
.get(prop.name)
|
|
1254
|
+
?.elements.sort()
|
|
1255
|
+
.map((element) => (0, element_tag_map_1.getElementByTag)(element))
|
|
1256
|
+
.join(" | ");
|
|
1257
|
+
return {
|
|
1258
|
+
...prop,
|
|
1259
|
+
type: `null | ${elementTypes}`,
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
return prop;
|
|
1263
|
+
});
|
|
1264
|
+
const processedSlots = ComponentParser.mapToArray(this.slots)
|
|
1265
|
+
.map((slot) => {
|
|
1266
|
+
try {
|
|
1267
|
+
const slot_props = JSON.parse(slot.slot_props);
|
|
1268
|
+
const new_props = [];
|
|
1269
|
+
for (const key of Object.keys(slot_props)) {
|
|
1270
|
+
if (slot_props[key].replace && slot_props[key].value !== undefined) {
|
|
1271
|
+
slot_props[key].value = this.props.get(slot_props[key].value)?.type;
|
|
1230
1272
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
catch (_e) {
|
|
1235
|
-
return slot;
|
|
1273
|
+
if (slot_props[key].value === undefined)
|
|
1274
|
+
slot_props[key].value = "any";
|
|
1275
|
+
new_props.push(`${key}: ${slot_props[key].value}`);
|
|
1236
1276
|
}
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1277
|
+
const formatted_slot_props = new_props.length === 0 ? "Record<string, never>" : `{ ${new_props.join(", ")} }`;
|
|
1278
|
+
return { ...slot, slot_props: formatted_slot_props };
|
|
1279
|
+
}
|
|
1280
|
+
catch (_e) {
|
|
1281
|
+
return slot;
|
|
1282
|
+
}
|
|
1283
|
+
})
|
|
1284
|
+
.sort((a, b) => {
|
|
1285
|
+
if (a.name < b.name)
|
|
1286
|
+
return -1;
|
|
1287
|
+
if (a.name > b.name)
|
|
1288
|
+
return 1;
|
|
1289
|
+
return 0;
|
|
1290
|
+
});
|
|
1291
|
+
const moduleExportsArray = ComponentParser.mapToArray(this.moduleExports);
|
|
1292
|
+
const eventsArray = ComponentParser.mapToArray(this.events);
|
|
1293
|
+
const typedefsArray = ComponentParser.mapToArray(this.typedefs);
|
|
1294
|
+
const contextsArray = ComponentParser.mapToArray(this.contexts);
|
|
1295
|
+
return {
|
|
1296
|
+
props: processedProps,
|
|
1297
|
+
moduleExports: moduleExportsArray,
|
|
1298
|
+
slots: processedSlots,
|
|
1299
|
+
events: eventsArray,
|
|
1300
|
+
typedefs: typedefsArray,
|
|
1247
1301
|
generics: this.generics,
|
|
1248
1302
|
rest_props: this.rest_props,
|
|
1249
1303
|
extends: this.extends,
|
|
1250
1304
|
componentComment: this.componentComment,
|
|
1251
|
-
contexts:
|
|
1305
|
+
contexts: contextsArray,
|
|
1252
1306
|
};
|
|
1253
1307
|
}
|
|
1254
1308
|
}
|
package/lib/resolve-alias.js
CHANGED
|
@@ -7,6 +7,7 @@ const node_fs_1 = require("node:fs");
|
|
|
7
7
|
const node_path_1 = require("node:path");
|
|
8
8
|
const path_1 = require("./path");
|
|
9
9
|
const configCache = new Map();
|
|
10
|
+
const pathPatternRegexCache = new Map();
|
|
10
11
|
const COMMENT_PATTERN = /\/\*[\s\S]*?\*\/|\/\/.*/g;
|
|
11
12
|
const REGEX_SPECIAL_CHARS = /[.+?^${}()|[\]\\]/g;
|
|
12
13
|
function clearConfigCache() {
|
|
@@ -83,12 +84,16 @@ function resolvePathAliasAbsolute(importPath, fromDir) {
|
|
|
83
84
|
// e.g., "$lib/*" -> /^\$lib\/(.*)$/
|
|
84
85
|
// e.g., "$lib" -> /^\$lib$/
|
|
85
86
|
// e.g., "@components/*" -> /^@components\/(.*)$/
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
let regex = pathPatternRegexCache.get(pattern);
|
|
88
|
+
if (!regex) {
|
|
89
|
+
// Escape special regex chars but keep * for replacement
|
|
90
|
+
const escapedPattern = pattern
|
|
91
|
+
.split("*")
|
|
92
|
+
.map((part) => part.replace(REGEX_SPECIAL_CHARS, "\\$&"))
|
|
93
|
+
.join("(.*)");
|
|
94
|
+
regex = new RegExp(`^${escapedPattern}$`);
|
|
95
|
+
pathPatternRegexCache.set(pattern, regex);
|
|
96
|
+
}
|
|
92
97
|
const match = importPath.match(regex);
|
|
93
98
|
if (match) {
|
|
94
99
|
// Use the first mapping (TypeScript uses the first match)
|
package/lib/rollup-plugin.js
CHANGED
|
@@ -69,42 +69,47 @@ async function generateBundle(input, glob) {
|
|
|
69
69
|
const allComponentsForTypes = new Map();
|
|
70
70
|
const exportEntries = Object.entries(exports);
|
|
71
71
|
const allComponentEntries = Object.entries(allComponents);
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
const uniqueFilePaths = new Set();
|
|
73
|
+
for (const [, entry] of exportEntries) {
|
|
74
74
|
const filePath = entry.source;
|
|
75
|
-
const { ext
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
moduleName = name;
|
|
75
|
+
const { ext } = (0, node_path_1.parse)(filePath);
|
|
76
|
+
if (ext === ".svelte") {
|
|
77
|
+
uniqueFilePaths.add((0, node_path_1.resolve)(dir, filePath));
|
|
79
78
|
}
|
|
79
|
+
}
|
|
80
|
+
for (const [, entry] of allComponentEntries) {
|
|
81
|
+
const filePath = entry.source;
|
|
82
|
+
const { ext } = (0, node_path_1.parse)(filePath);
|
|
80
83
|
if (ext === ".svelte") {
|
|
81
|
-
|
|
82
|
-
const { code: processed } = await (0, compiler_1.preprocess)(source, [(0, svelte_preprocess_1.typescript)(), (0, svelte_preprocess_1.replace)([[STYLE_TAG_REGEX, ""]])], {
|
|
83
|
-
filename: (0, node_path_1.basename)(filePath),
|
|
84
|
-
});
|
|
85
|
-
const parser = new ComponentParser_1.default();
|
|
86
|
-
const parsed = parser.parseSvelteComponent(processed, {
|
|
87
|
-
moduleName,
|
|
88
|
-
filePath,
|
|
89
|
-
});
|
|
90
|
-
return {
|
|
91
|
-
moduleName,
|
|
92
|
-
filePath,
|
|
93
|
-
...parsed,
|
|
94
|
-
};
|
|
84
|
+
uniqueFilePaths.add((0, node_path_1.resolve)(dir, filePath));
|
|
95
85
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
86
|
+
}
|
|
87
|
+
const fileContents = await Promise.all(Array.from(uniqueFilePaths).map(async (filePath) => {
|
|
88
|
+
try {
|
|
89
|
+
const content = await (0, promises_1.readFile)(filePath, "utf-8");
|
|
90
|
+
return { path: filePath, content };
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.warn(`Warning: Failed to read file ${filePath}:`, error);
|
|
94
|
+
return { path: filePath, content: null };
|
|
95
|
+
}
|
|
96
|
+
}));
|
|
97
|
+
const fileMap = new Map(fileContents.map(({ path, content }) => [path, content]));
|
|
98
|
+
// Helper function to process a single component
|
|
99
|
+
const processComponent = async ([exportName, entry], entries, fileMap) => {
|
|
100
100
|
const filePath = entry.source;
|
|
101
101
|
const { ext, name } = (0, node_path_1.parse)(filePath);
|
|
102
102
|
let moduleName = exportName;
|
|
103
|
-
if (
|
|
103
|
+
if (entries.length === 1 && exportName === "default") {
|
|
104
104
|
moduleName = name;
|
|
105
105
|
}
|
|
106
106
|
if (ext === ".svelte") {
|
|
107
|
-
const
|
|
107
|
+
const resolvedPath = (0, node_path_1.resolve)(dir, filePath);
|
|
108
|
+
const source = fileMap.get(resolvedPath);
|
|
109
|
+
if (source === null || source === undefined) {
|
|
110
|
+
// File was not found or failed to read, skip this component
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
108
113
|
const { code: processed } = await (0, compiler_1.preprocess)(source, [(0, svelte_preprocess_1.typescript)(), (0, svelte_preprocess_1.replace)([[STYLE_TAG_REGEX, ""]])], {
|
|
109
114
|
filename: (0, node_path_1.basename)(filePath),
|
|
110
115
|
});
|
|
@@ -120,7 +125,11 @@ async function generateBundle(input, glob) {
|
|
|
120
125
|
};
|
|
121
126
|
}
|
|
122
127
|
return null;
|
|
123
|
-
}
|
|
128
|
+
};
|
|
129
|
+
// Process exported components (for metadata/JSON/Markdown)
|
|
130
|
+
const componentPromises = exportEntries.map((entry) => processComponent(entry, exportEntries, fileMap));
|
|
131
|
+
// Process all components (for .d.ts generation)
|
|
132
|
+
const allComponentPromises = allComponentEntries.map((entry) => processComponent(entry, allComponentEntries, fileMap));
|
|
124
133
|
const [results, allResults] = await Promise.all([Promise.all(componentPromises), Promise.all(allComponentPromises)]);
|
|
125
134
|
for (const result of results) {
|
|
126
135
|
if (result) {
|
|
@@ -10,10 +10,11 @@ interface TocLine {
|
|
|
10
10
|
}
|
|
11
11
|
export default class WriterMarkdown extends Writer {
|
|
12
12
|
onAppend?: OnAppend;
|
|
13
|
-
|
|
13
|
+
private sourceParts;
|
|
14
14
|
hasToC: boolean;
|
|
15
15
|
toc: TocLine[];
|
|
16
16
|
constructor(options: MarkdownOptions);
|
|
17
|
+
get source(): string;
|
|
17
18
|
appendLineBreaks(): this;
|
|
18
19
|
append(type: AppendType, raw?: string): this;
|
|
19
20
|
tableOfContents(): this;
|
|
@@ -8,15 +8,18 @@ const BACKTICK_REGEX = /`/g;
|
|
|
8
8
|
const WHITESPACE_REGEX = /\s+/g;
|
|
9
9
|
class WriterMarkdown extends Writer_1.default {
|
|
10
10
|
onAppend;
|
|
11
|
-
|
|
11
|
+
sourceParts = [];
|
|
12
12
|
hasToC = false;
|
|
13
13
|
toc = [];
|
|
14
14
|
constructor(options) {
|
|
15
15
|
super({ parser: "markdown", printWidth: 80 });
|
|
16
16
|
this.onAppend = options.onAppend;
|
|
17
17
|
}
|
|
18
|
+
get source() {
|
|
19
|
+
return this.sourceParts.join("");
|
|
20
|
+
}
|
|
18
21
|
appendLineBreaks() {
|
|
19
|
-
this.
|
|
22
|
+
this.sourceParts.push("\n\n");
|
|
20
23
|
return this;
|
|
21
24
|
}
|
|
22
25
|
append(type, raw) {
|
|
@@ -28,9 +31,7 @@ class WriterMarkdown extends Writer_1.default {
|
|
|
28
31
|
case "h5":
|
|
29
32
|
case "h6": {
|
|
30
33
|
const length = Number(type.slice(-1));
|
|
31
|
-
this.
|
|
32
|
-
.map((_) => "#")
|
|
33
|
-
.join("")} ${raw}`;
|
|
34
|
+
this.sourceParts.push(`${"#".repeat(length)} ${raw}`);
|
|
34
35
|
if (this.hasToC && type === "h2") {
|
|
35
36
|
this.toc.push({
|
|
36
37
|
array: Array.from({ length: (length - 1) * 2 }),
|
|
@@ -40,16 +41,16 @@ class WriterMarkdown extends Writer_1.default {
|
|
|
40
41
|
break;
|
|
41
42
|
}
|
|
42
43
|
case "quote":
|
|
43
|
-
this.
|
|
44
|
+
this.sourceParts.push(`> ${raw}`);
|
|
44
45
|
break;
|
|
45
46
|
case "p":
|
|
46
|
-
this.
|
|
47
|
+
this.sourceParts.push(raw ?? "");
|
|
47
48
|
break;
|
|
48
49
|
case "divider":
|
|
49
|
-
this.
|
|
50
|
+
this.sourceParts.push("---");
|
|
50
51
|
break;
|
|
51
52
|
case "raw":
|
|
52
|
-
this.
|
|
53
|
+
this.sourceParts.push(raw ?? "");
|
|
53
54
|
break;
|
|
54
55
|
}
|
|
55
56
|
if (type !== "raw")
|
|
@@ -58,18 +59,18 @@ class WriterMarkdown extends Writer_1.default {
|
|
|
58
59
|
return this;
|
|
59
60
|
}
|
|
60
61
|
tableOfContents() {
|
|
61
|
-
this.
|
|
62
|
+
this.sourceParts.push("<!-- __TOC__ -->");
|
|
62
63
|
this.hasToC = true;
|
|
63
64
|
this.appendLineBreaks();
|
|
64
65
|
return this;
|
|
65
66
|
}
|
|
66
67
|
end() {
|
|
67
|
-
|
|
68
|
+
const source = this.sourceParts.join("");
|
|
69
|
+
return source.replace("<!-- __TOC__ -->", this.toc
|
|
68
70
|
.map(({ array, raw }) => {
|
|
69
71
|
return `${array.join(" ")} - [${raw}](#${raw.toLowerCase().replace(BACKTICK_REGEX, "").replace(WHITESPACE_REGEX, "-")})`;
|
|
70
72
|
})
|
|
71
73
|
.join("\n"));
|
|
72
|
-
return this.source;
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
exports.default = WriterMarkdown;
|
|
@@ -10,10 +10,11 @@ interface TocLine {
|
|
|
10
10
|
}
|
|
11
11
|
export declare class BrowserWriterMarkdown {
|
|
12
12
|
onAppend?: OnAppend;
|
|
13
|
-
|
|
13
|
+
private sourceParts;
|
|
14
14
|
hasToC: boolean;
|
|
15
15
|
toc: TocLine[];
|
|
16
16
|
constructor(options: MarkdownOptions);
|
|
17
|
+
get source(): string;
|
|
17
18
|
appendLineBreaks(): this;
|
|
18
19
|
append(type: AppendType, raw?: string): this;
|
|
19
20
|
tableOfContents(): this;
|
|
@@ -8,14 +8,17 @@ const WHITESPACE_REGEX = /\s+/g;
|
|
|
8
8
|
// Browser-compatible WriterMarkdown that doesn't extend Writer
|
|
9
9
|
class BrowserWriterMarkdown {
|
|
10
10
|
onAppend;
|
|
11
|
-
|
|
11
|
+
sourceParts = [];
|
|
12
12
|
hasToC = false;
|
|
13
13
|
toc = [];
|
|
14
14
|
constructor(options) {
|
|
15
15
|
this.onAppend = options.onAppend;
|
|
16
16
|
}
|
|
17
|
+
get source() {
|
|
18
|
+
return this.sourceParts.join("");
|
|
19
|
+
}
|
|
17
20
|
appendLineBreaks() {
|
|
18
|
-
this.
|
|
21
|
+
this.sourceParts.push("\n\n");
|
|
19
22
|
return this;
|
|
20
23
|
}
|
|
21
24
|
append(type, raw) {
|
|
@@ -27,9 +30,7 @@ class BrowserWriterMarkdown {
|
|
|
27
30
|
case "h5":
|
|
28
31
|
case "h6": {
|
|
29
32
|
const length = Number(type.slice(-1));
|
|
30
|
-
this.
|
|
31
|
-
.map((_) => "#")
|
|
32
|
-
.join("")} ${raw}`;
|
|
33
|
+
this.sourceParts.push(`${"#".repeat(length)} ${raw}`);
|
|
33
34
|
if (this.hasToC && type === "h2") {
|
|
34
35
|
this.toc.push({
|
|
35
36
|
array: Array.from({ length: (length - 1) * 2 }),
|
|
@@ -39,16 +40,16 @@ class BrowserWriterMarkdown {
|
|
|
39
40
|
break;
|
|
40
41
|
}
|
|
41
42
|
case "quote":
|
|
42
|
-
this.
|
|
43
|
+
this.sourceParts.push(`> ${raw}`);
|
|
43
44
|
break;
|
|
44
45
|
case "p":
|
|
45
|
-
this.
|
|
46
|
+
this.sourceParts.push(raw ?? "");
|
|
46
47
|
break;
|
|
47
48
|
case "divider":
|
|
48
|
-
this.
|
|
49
|
+
this.sourceParts.push("---");
|
|
49
50
|
break;
|
|
50
51
|
case "raw":
|
|
51
|
-
this.
|
|
52
|
+
this.sourceParts.push(raw ?? "");
|
|
52
53
|
break;
|
|
53
54
|
}
|
|
54
55
|
if (type !== "raw")
|
|
@@ -57,18 +58,18 @@ class BrowserWriterMarkdown {
|
|
|
57
58
|
return this;
|
|
58
59
|
}
|
|
59
60
|
tableOfContents() {
|
|
60
|
-
this.
|
|
61
|
+
this.sourceParts.push("<!-- __TOC__ -->");
|
|
61
62
|
this.hasToC = true;
|
|
62
63
|
this.appendLineBreaks();
|
|
63
64
|
return this;
|
|
64
65
|
}
|
|
65
66
|
end() {
|
|
66
|
-
|
|
67
|
+
const source = this.sourceParts.join("");
|
|
68
|
+
return source.replace("<!-- __TOC__ -->", this.toc
|
|
67
69
|
.map(({ array, raw }) => {
|
|
68
70
|
return `${array.join(" ")} - [${raw}](#${raw.toLowerCase().replace(BACKTICK_REGEX, "").replace(WHITESPACE_REGEX, "-")})`;
|
|
69
71
|
})
|
|
70
72
|
.join("\n"));
|
|
71
|
-
return this.source;
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
exports.BrowserWriterMarkdown = BrowserWriterMarkdown;
|